📄 matrix.f
字号:
* N (input) INTEGER* The dimension n of the tridiagonal matrix T. It must be at* least 1.** MMAX (input) INTEGER* The maximum number of intervals. If more than MMAX intervals* are generated, then SLAEBZ will quit with INFO=MMAX+1.** MINP (input) INTEGER* The initial number of intervals. It may not be greater than* MMAX.** NBMIN (input) INTEGER* The smallest number of intervals that should be processed* using a vector loop. If zero, then only the scalar loop* will be used.** ABSTOL (input) REAL* The minimum (absolute) width of an interval. When an* interval is narrower than ABSTOL, or than RELTOL times the* larger (in magnitude) endpoint, then it is considered to be* sufficiently small, i.e., converged. This must be at least* zero.** RELTOL (input) REAL* The minimum relative width of an interval. When an interval* is narrower than ABSTOL, or than RELTOL times the larger (in* magnitude) endpoint, then it is considered to be* sufficiently small, i.e., converged. Note: this should* always be at least radix*machine epsilon.** PIVMIN (input) REAL* The minimum absolute value of a "pivot" in the Sturm* sequence loop. This *must* be at least max |e(j)**2| ** safe_min and at least safe_min, where safe_min is at least* the smallest number that can divide one without overflow.** D (input) REAL array, dimension (N)* The diagonal elements of the tridiagonal matrix T.** E (input) REAL array, dimension (N)* The offdiagonal elements of the tridiagonal matrix T in* positions 1 through N-1. E(N) is arbitrary.** E2 (input) REAL array, dimension (N)* The squares of the offdiagonal elements of the tridiagonal* matrix T. E2(N) is ignored.** NVAL (input/output) INTEGER array, dimension (MINP)* If IJOB=1 or 2, not referenced.* If IJOB=3, the desired values of N(w). The elements of NVAL* will be reordered to correspond with the intervals in AB.* Thus, NVAL(j) on output will not, in general be the same as* NVAL(j) on input, but it will correspond with the interval* (AB(j,1),AB(j,2)] on output.** AB (input/output) REAL array, dimension (MMAX,2)* The endpoints of the intervals. AB(j,1) is a(j), the left* endpoint of the j-th interval, and AB(j,2) is b(j), the* right endpoint of the j-th interval. The input intervals* will, in general, be modified, split, and reordered by the* calculation.** C (input/output) REAL array, dimension (MMAX)* If IJOB=1, ignored.* If IJOB=2, workspace.* If IJOB=3, then on input C(j) should be initialized to the* first search point in the binary search.** MOUT (output) INTEGER* If IJOB=1, the number of eigenvalues in the intervals.* If IJOB=2 or 3, the number of intervals output.* If IJOB=3, MOUT will equal MINP.** NAB (input/output) INTEGER array, dimension (MMAX,2)* If IJOB=1, then on output NAB(i,j) will be set to N(AB(i,j)).* If IJOB=2, then on input, NAB(i,j) should be set. It must* satisfy the condition:* N(AB(i,1)) <= NAB(i,1) <= NAB(i,2) <= N(AB(i,2)),* which means that in interval i only eigenvalues* NAB(i,1)+1,...,NAB(i,2) will be considered. Usually,* NAB(i,j)=N(AB(i,j)), from a previous call to SLAEBZ with* IJOB=1.* On output, NAB(i,j) will contain* max(na(k),min(nb(k),N(AB(i,j)))), where k is the index of* the input interval that the output interval* (AB(j,1),AB(j,2)] came from, and na(k) and nb(k) are the* the input values of NAB(k,1) and NAB(k,2).* If IJOB=3, then on output, NAB(i,j) contains N(AB(i,j)),* unless N(w) > NVAL(i) for all search points w , in which* case NAB(i,1) will not be modified, i.e., the output* value will be the same as the input value (modulo* reorderings -- see NVAL and AB), or unless N(w) < NVAL(i)* for all search points w , in which case NAB(i,2) will* not be modified. Normally, NAB should be set to some* distinctive value(s) before SLAEBZ is called.** WORK (workspace) REAL array, dimension (MMAX)* Workspace.** IWORK (workspace) INTEGER array, dimension (MMAX)* Workspace.** INFO (output) INTEGER* = 0: All intervals converged.* = 1--MMAX: The last INFO intervals did not converge.* = MMAX+1: More than MMAX intervals were generated.** Further Details* ===============** This routine is intended to be called only by other LAPACK* routines, thus the interface is less user-friendly. It is intended* for two purposes:** (a) finding eigenvalues. In this case, SLAEBZ should have one or* more initial intervals set up in AB, and SLAEBZ should be called* with IJOB=1. This sets up NAB, and also counts the eigenvalues.* Intervals with no eigenvalues would usually be thrown out at* this point. Also, if not all the eigenvalues in an interval i* are desired, NAB(i,1) can be increased or NAB(i,2) decreased.* For example, set NAB(i,1)=NAB(i,2)-1 to get the largest* eigenvalue. SLAEBZ is then called with IJOB=2 and MMAX* no smaller than the value of MOUT returned by the call with* IJOB=1. After this (IJOB=2) call, eigenvalues NAB(i,1)+1* through NAB(i,2) are approximately AB(i,1) (or AB(i,2)) to the* tolerance specified by ABSTOL and RELTOL.** (b) finding an interval (a',b'] containing eigenvalues w(f),...,w(l).* In this case, start with a Gershgorin interval (a,b). Set up* AB to contain 2 search intervals, both initially (a,b). One* NVAL element should contain f-1 and the other should contain l* , while C should contain a and b, resp. NAB(i,1) should be -1* and NAB(i,2) should be N+1, to flag an error if the desired* interval does not lie in (a,b). SLAEBZ is then called with* IJOB=3. On exit, if w(f-1) < w(f), then one of the intervals --* j -- will have AB(j,1)=AB(j,2) and NAB(j,1)=NAB(j,2)=f-1, while* if, to the specified tolerance, w(f-k)=...=w(f+r), k > 0 and r* >= 0, then the interval will have N(AB(j,1))=NAB(j,1)=f-k and* N(AB(j,2))=NAB(j,2)=f+r. The cases w(l) < w(l+1) and* w(l-r)=...=w(l+k) are handled similarly.** =====================================================================** .. Parameters .. REAL ZERO, TWO, HALF PARAMETER ( ZERO = 0.0E0, TWO = 2.0E0, $ HALF = 1.0E0 / TWO )* ..* .. Local Scalars .. INTEGER ITMP1, ITMP2, J, JI, JIT, JP, KF, KFNEW, KL, $ KLNEW REAL TMP1, TMP2* ..* .. Intrinsic Functions .. INTRINSIC ABS, MAX, MIN* ..* .. Executable Statements ..** Check for Errors* INFO = 0 IF( IJOB.LT.1 .OR. IJOB.GT.3 ) THEN INFO = -1 RETURN END IF** Initialize NAB* IF( IJOB.EQ.1 ) THEN** Compute the number of eigenvalues in the initial intervals.* MOUT = 0CDIR$ NOVECTOR DO 30 JI = 1, MINP DO 20 JP = 1, 2 TMP1 = D( 1 ) - AB( JI, JP ) IF( ABS( TMP1 ).LT.PIVMIN ) $ TMP1 = -PIVMIN NAB( JI, JP ) = 0 IF( TMP1.LE.ZERO ) $ NAB( JI, JP ) = 1* DO 10 J = 2, N TMP1 = D( J ) - E2( J-1 ) / TMP1 - AB( JI, JP ) IF( ABS( TMP1 ).LT.PIVMIN ) $ TMP1 = -PIVMIN IF( TMP1.LE.ZERO ) $ NAB( JI, JP ) = NAB( JI, JP ) + 1 10 CONTINUE 20 CONTINUE MOUT = MOUT + NAB( JI, 2 ) - NAB( JI, 1 ) 30 CONTINUE RETURN END IF** Initialize for loop** KF and KL have the following meaning:* Intervals 1,...,KF-1 have converged.* Intervals KF,...,KL still need to be refined.* KF = 1 KL = MINP** If IJOB=2, initialize C.* If IJOB=3, use the user-supplied starting point.* IF( IJOB.EQ.2 ) THEN DO 40 JI = 1, MINP C( JI ) = HALF*( AB( JI, 1 )+AB( JI, 2 ) ) 40 CONTINUE END IF** Iteration loop* DO 130 JIT = 1, NITMAX** Loop over intervals* IF( KL-KF+1.GE.NBMIN .AND. NBMIN.GT.0 ) THEN** Begin of Parallel Version of the loop* DO 60 JI = KF, KL** Compute N(c), the number of eigenvalues less than c* WORK( JI ) = D( 1 ) - C( JI ) IWORK( JI ) = 0 IF( WORK( JI ).LE.PIVMIN ) THEN IWORK( JI ) = 1 WORK( JI ) = MIN( WORK( JI ), -PIVMIN ) END IF* DO 50 J = 2, N WORK( JI ) = D( J ) - E2( J-1 ) / WORK( JI ) - C( JI ) IF( WORK( JI ).LE.PIVMIN ) THEN IWORK( JI ) = IWORK( JI ) + 1 WORK( JI ) = MIN( WORK( JI ), -PIVMIN ) END IF 50 CONTINUE 60 CONTINUE* IF( IJOB.LE.2 ) THEN** IJOB=2: Choose all intervals containing eigenvalues.* KLNEW = KL DO 70 JI = KF, KL** Insure that N(w) is monotone* IWORK( JI ) = MIN( NAB( JI, 2 ), $ MAX( NAB( JI, 1 ), IWORK( JI ) ) )** Update the Queue -- add intervals if both halves* contain eigenvalues.* IF( IWORK( JI ).EQ.NAB( JI, 2 ) ) THEN** No eigenvalue in the upper interval:* just use the lower interval.* AB( JI, 2 ) = C( JI )* ELSE IF( IWORK( JI ).EQ.NAB( JI, 1 ) ) THEN** No eigenvalue in the lower interval:* just use the upper interval.* AB( JI, 1 ) = C( JI ) ELSE KLNEW = KLNEW + 1 IF( KLNEW.LE.MMAX ) THEN** Eigenvalue in both intervals -- add upper to* queue.* AB( KLNEW, 2 ) = AB( JI, 2 ) NAB( KLNEW, 2 ) = NAB( JI, 2 ) AB( KLNEW, 1 ) = C( JI ) NAB( KLNEW, 1 ) = IWORK( JI ) AB( JI, 2 ) = C( JI ) NAB( JI, 2 ) = IWORK( JI ) ELSE INFO = MMAX + 1 END IF END IF 70 CONTINUE IF( INFO.NE.0 ) $ RETURN KL = KLNEW ELSE** IJOB=3: Binary search. Keep only the interval containing* w s.t. N(w) = NVAL* DO 80 JI = KF, KL IF( IWORK( JI ).LE.NVAL( JI ) ) THEN AB( JI, 1 ) = C( JI ) NAB( JI, 1 ) = IWORK( JI ) END IF IF( IWORK( JI ).GE.NVAL( JI ) ) THEN AB( JI, 2 ) = C( JI ) NAB( JI, 2 ) = IWORK( JI ) END IF 80 CONTINUE END IF* ELSE** End of Parallel Version of the loop** Begin of Serial Version of the loop* KLNEW = KL DO 100 JI = KF, KL** Compute N(w), the number of eigenvalues less than w* TMP1 = C( JI ) TMP2 = D( 1 ) - TMP1 ITMP1 = 0 IF( TMP2.LE.PIVMIN ) THEN ITMP1 = 1 TMP2 = MIN( TMP2, -PIVMIN ) END IF** A series of compiler directives to defeat vectorization* for the next loop**$PL$ CMCHAR=' 'CDIR$ NEXTSCALARC$DIR SCALARCDIR$ NEXT SCALARCVD$L NOVECTORCDEC$ NOVECTORCVD$ NOVECTOR*VDIR NOVECTOR*VOCL LOOP,SCALARCIBM PREFER SCALAR*$PL$ CMCHAR='*'* DO 90 J = 2, N TMP2 = D( J ) - E2( J-1 ) / TMP2 - TMP1 IF( TMP2.LE.PIVMIN ) THEN ITMP1 = ITMP1 + 1 TMP2 = MIN( TMP2, -PIVMIN ) END IF 90 CONTINUE* IF( IJOB.LE.2 ) THEN** IJOB=2: Choose all intervals containing eigenvalues.** Insure that N(w) is monotone* ITMP1 = MIN( NAB( JI, 2 ), $ MAX( NAB( JI, 1 ), ITMP1 ) )** Update the Queue -- add intervals if both halves* contain eigenvalues.* IF( ITMP1.EQ.NAB( JI, 2 ) ) THEN** No eigenvalue in the upper interval:* just use the lower interval.* AB( JI, 2 ) = TMP1* ELSE IF( ITMP1.EQ.NAB( JI, 1 ) ) THEN** No eigenvalue in the lower interval:* just use the upper interval.* AB( JI, 1 ) = TMP1 ELSE IF( KLNEW.LT.MMAX ) THEN** Eigenvalue in both intervals -- add upper to queue.* KLNEW = KLNEW + 1 AB( KLNEW, 2 ) = AB( JI, 2 ) NAB( KLNEW, 2 ) = NAB( JI, 2 ) AB( KLNEW, 1 ) = TMP1 NAB( KLNEW, 1 ) = ITMP1 AB( JI, 2 ) = TMP1 NAB( JI, 2 ) = ITMP1 ELSE INFO = MMAX + 1 RETURN END IF ELSE** IJOB=3: Binary search. Keep only the interval* containing w s.t. N(w) = NVAL* IF( ITMP1.LE.NVAL( JI ) ) THEN AB( JI, 1 ) = TMP1 NAB( JI, 1 ) = ITMP1 END IF IF( ITMP1.GE.NVAL( JI ) ) THEN AB( JI, 2 ) = TMP1 NAB( JI, 2 ) = ITMP1 END IF END IF 100 CONTINUE KL = KLNEW** End of Serial Version of the loop* END IF** Check for convergence* KFNEW = KF DO 110 JI = KF, KL TMP1 = ABS( AB( JI, 2 )-AB( JI, 1 ) ) TMP2 = MAX( ABS( AB( JI, 2 ) ), ABS( AB( JI, 1 ) ) ) IF( TMP1.LT.MAX( ABSTOL, P
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -