⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 dstebz.f

📁 计算矩阵的经典开源库.全世界都在用它.相信你也不能例外.
💻 F
📖 第 1 页 / 共 2 页
字号:
      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 + -