📄 dstebz.f
字号:
SUBROUTINE DSTEBZ( RANGE, ORDER, N, VL, VU, IL, IU, ABSTOL, D, E, $ M, NSPLIT, W, IBLOCK, ISPLIT, WORK, IWORK, $ INFO )** -- LAPACK routine (instrumented to count operations, version 3.0) --* Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd.,* Courant Institute, Argonne National Lab, and Rice University* June 30, 1999** .. Scalar Arguments .. CHARACTER ORDER, RANGE INTEGER IL, INFO, IU, M, N, NSPLIT DOUBLE PRECISION ABSTOL, VL, VU* ..* .. Array Arguments .. INTEGER IBLOCK( * ), ISPLIT( * ), IWORK( * ) DOUBLE PRECISION D( * ), E( * ), W( * ), WORK( * )* ..* Common block to return operation count and iteration count* ITCNT is initialized to 0, OPS is only incremented* .. Common blocks .. COMMON / LATIME / OPS, ITCNT* ..* .. Scalars in Common .. DOUBLE PRECISION ITCNT, OPS* ..** Purpose* =======** DSTEBZ computes the eigenvalues of a symmetric tridiagonal* matrix T. The user may ask for all eigenvalues, all eigenvalues* in the half-open interval (VL, VU], or the IL-th through IU-th* eigenvalues.** To avoid overflow, the matrix must be scaled so that its* largest element is no greater than overflow**(1/2) ** underflow**(1/4) in absolute value, and for greatest* accuracy, it should not be much smaller than that.** See W. Kahan "Accurate Eigenvalues of a Symmetric Tridiagonal* Matrix", Report CS41, Computer Science Dept., Stanford* University, July 21, 1966.** Arguments* =========** RANGE (input) CHARACTER* = 'A': ("All") all eigenvalues will be found.* = 'V': ("Value") all eigenvalues in the half-open interval* (VL, VU] will be found.* = 'I': ("Index") the IL-th through IU-th eigenvalues (of the* entire matrix) will be found.** ORDER (input) CHARACTER* = 'B': ("By Block") the eigenvalues will be grouped by* split-off block (see IBLOCK, ISPLIT) and* ordered from smallest to largest within* the block.* = 'E': ("Entire matrix")* the eigenvalues for the entire matrix* will be ordered from smallest to* largest.** N (input) INTEGER* The order of the tridiagonal matrix T. N >= 0.** VL (input) DOUBLE PRECISION* VU (input) DOUBLE PRECISION* If RANGE='V', the lower and upper bounds of the interval to* be searched for eigenvalues. Eigenvalues less than or equal* to VL, or greater than VU, will not be returned. VL < VU.* Not referenced if RANGE = 'A' or 'I'.** IL (input) INTEGER* IU (input) INTEGER* If RANGE='I', the indices (in ascending order) of the* smallest and largest eigenvalues to be returned.* 1 <= IL <= IU <= N, if N > 0; IL = 1 and IU = 0 if N = 0.* Not referenced if RANGE = 'A' or 'V'.** ABSTOL (input) DOUBLE PRECISION* The absolute tolerance for the eigenvalues. An eigenvalue* (or cluster) is considered to be located if it has been* determined to lie in an interval whose width is ABSTOL or* less. If ABSTOL is less than or equal to zero, then ULP*|T|* will be used, where |T| means the 1-norm of T.** Eigenvalues will be computed most accurately when ABSTOL is* set to twice the underflow threshold 2*DLAMCH('S'), not zero.** D (input) DOUBLE PRECISION array, dimension (N)* The n diagonal elements of the tridiagonal matrix T.** E (input) DOUBLE PRECISION array, dimension (N-1)* The (n-1) off-diagonal elements of the tridiagonal matrix T.** M (output) INTEGER* The actual number of eigenvalues found. 0 <= M <= N.* (See also the description of INFO=2,3.)** NSPLIT (output) INTEGER* The number of diagonal blocks in the matrix T.* 1 <= NSPLIT <= N.** W (output) DOUBLE PRECISION array, dimension (N)* On exit, the first M elements of W will contain the* eigenvalues. (DSTEBZ may use the remaining N-M elements as* workspace.)** IBLOCK (output) INTEGER array, dimension (N)* At each row/column j where E(j) is zero or small, the* matrix T is considered to split into a block diagonal* matrix. On exit, if INFO = 0, IBLOCK(i) specifies to which* block (from 1 to the number of blocks) the eigenvalue W(i)* belongs. (DSTEBZ may use the remaining N-M elements as* workspace.)** ISPLIT (output) INTEGER array, dimension (N)* The splitting points, at which T breaks up into submatrices.* The first submatrix consists of rows/columns 1 to ISPLIT(1),* the second of rows/columns ISPLIT(1)+1 through ISPLIT(2),* etc., and the NSPLIT-th consists of rows/columns* ISPLIT(NSPLIT-1)+1 through ISPLIT(NSPLIT)=N.* (Only the first NSPLIT elements will actually be used, but* since the user cannot know a priori what value NSPLIT will* have, N words must be reserved for ISPLIT.)** WORK (workspace) DOUBLE PRECISION array, dimension (4*N)** IWORK (workspace) INTEGER array, dimension (3*N)** INFO (output) INTEGER* = 0: successful exit* < 0: if INFO = -i, the i-th argument had an illegal value* > 0: some or all of the eigenvalues failed to converge or* were not computed:* =1 or 3: Bisection failed to converge for some* eigenvalues; these eigenvalues are flagged by a* negative block number. The effect is that the* eigenvalues may not be as accurate as the* absolute and relative tolerances. This is* generally caused by unexpectedly inaccurate* arithmetic.* =2 or 3: RANGE='I' only: Not all of the eigenvalues* IL:IU were found.* Effect: M < IU+1-IL* Cause: non-monotonic arithmetic, causing the* Sturm sequence to be non-monotonic.* Cure: recalculate, using RANGE='A', and pick* out eigenvalues IL:IU. In some cases,* increasing the PARAMETER "FUDGE" may* make things work.* = 4: RANGE='I', and the Gershgorin interval* initially used was too small. No eigenvalues* were computed.* Probable cause: your machine has sloppy* floating-point arithmetic.* Cure: Increase the PARAMETER "FUDGE",* recompile, and try again.** Internal Parameters* ===================** RELFAC DOUBLE PRECISION, default = 2.0e0* The relative tolerance. An interval (a,b] lies within* "relative tolerance" if b-a < RELFAC*ulp*max(|a|,|b|),* where "ulp" is the machine precision (distance from 1 to* the next larger floating point number.)** FUDGE DOUBLE PRECISION, default = 2* A "fudge factor" to widen the Gershgorin intervals. Ideally,* a value of 1 should work, but on machines with sloppy* arithmetic, this needs to be larger. The default for* publicly released versions should be large enough to handle* the worst machine around. Note that this has no effect* on accuracy of the solution.** =====================================================================** .. Parameters .. DOUBLE PRECISION ZERO, ONE, TWO, HALF PARAMETER ( ZERO = 0.0D0, ONE = 1.0D0, TWO = 2.0D0, $ HALF = 1.0D0 / TWO ) DOUBLE PRECISION FUDGE, RELFAC PARAMETER ( FUDGE = 2.0D0, RELFAC = 2.0D0 )* ..* .. Local Scalars .. LOGICAL NCNVRG, TOOFEW INTEGER IB, IBEGIN, IDISCL, IDISCU, IE, IEND, IINFO, $ IM, IN, IOFF, IORDER, IOUT, IRANGE, ITMAX, $ ITMP1, IW, IWOFF, J, JB, JDISC, JE, NB, NWL, $ NWU DOUBLE PRECISION ATOLI, BNORM, GL, GU, PIVMIN, RTOLI, SAFEMN, $ TMP1, TMP2, TNORM, ULP, WKILL, WL, WLU, WU, WUL* ..* .. Local Arrays .. INTEGER IDUMMA( 1 )* ..* .. External Functions .. LOGICAL LSAME INTEGER ILAENV DOUBLE PRECISION DLAMCH EXTERNAL LSAME, ILAENV, DLAMCH* ..* .. External Subroutines .. EXTERNAL DLAEBZ, XERBLA* ..* .. Intrinsic Functions .. INTRINSIC ABS, INT, LOG, MAX, MIN, SQRT* ..* .. Executable Statements ..* INFO = 0** Decode RANGE* IF( LSAME( RANGE, 'A' ) ) THEN IRANGE = 1 ELSE IF( LSAME( RANGE, 'V' ) ) THEN IRANGE = 2 ELSE IF( LSAME( RANGE, 'I' ) ) THEN IRANGE = 3 ELSE IRANGE = 0 END IF** Decode ORDER* IF( LSAME( ORDER, 'B' ) ) THEN IORDER = 2 ELSE IF( LSAME( ORDER, 'E' ) ) THEN IORDER = 1 ELSE IORDER = 0 END IF** Check for Errors* IF( IRANGE.LE.0 ) THEN INFO = -1 ELSE IF( IORDER.LE.0 ) THEN INFO = -2 ELSE IF( N.LT.0 ) THEN INFO = -3 ELSE IF( IRANGE.EQ.2 ) THEN IF( VL.GE.VU ) $ INFO = -5 ELSE IF( IRANGE.EQ.3 .AND. ( IL.LT.1 .OR. IL.GT.MAX( 1, N ) ) ) $ THEN INFO = -6 ELSE IF( IRANGE.EQ.3 .AND. ( IU.LT.MIN( N, IL ) .OR. IU.GT.N ) ) $ THEN INFO = -7 END IF* IF( INFO.NE.0 ) THEN CALL XERBLA( 'DSTEBZ', -INFO ) RETURN END IF** Initialize error flags* INFO = 0 NCNVRG = .FALSE. TOOFEW = .FALSE.** Quick return if possible* M = 0 IF( N.EQ.0 ) $ RETURN** Simplifications:* IF( IRANGE.EQ.3 .AND. IL.EQ.1 .AND. IU.EQ.N ) $ IRANGE = 1** Get machine constants* NB is the minimum vector length for vector bisection, or 0* if only scalar is to be done.* SAFEMN = DLAMCH( 'S' ) ULP = DLAMCH( 'P' ) OPS = OPS + 1 RTOLI = ULP*RELFAC NB = ILAENV( 1, 'DSTEBZ', ' ', N, -1, -1, -1 ) IF( NB.LE.1 ) $ NB = 0** Special Case when N=1* IF( N.EQ.1 ) THEN NSPLIT = 1 ISPLIT( 1 ) = 1 IF( IRANGE.EQ.2 .AND. ( VL.GE.D( 1 ) .OR. VU.LT.D( 1 ) ) ) THEN M = 0 ELSE W( 1 ) = D( 1 ) IBLOCK( 1 ) = 1 M = 1 END IF RETURN END IF** Compute Splitting Points* NSPLIT = 1 WORK( N ) = ZERO PIVMIN = ONE* OPS = OPS + ( N-1 )*5 + 1*DIR$ NOVECTOR DO 10 J = 2, N TMP1 = E( J-1 )**2 IF( ABS( D( J )*D( J-1 ) )*ULP**2+SAFEMN.GT.TMP1 ) THEN ISPLIT( NSPLIT ) = J - 1 NSPLIT = NSPLIT + 1 WORK( J-1 ) = ZERO ELSE WORK( J-1 ) = TMP1 PIVMIN = MAX( PIVMIN, TMP1 ) END IF 10 CONTINUE ISPLIT( NSPLIT ) = N PIVMIN = PIVMIN*SAFEMN** Compute Interval and ATOLI* IF( IRANGE.EQ.3 ) THEN** RANGE='I': Compute the interval containing eigenvalues* IL through IU.** Compute Gershgorin interval for entire (split) matrix
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -