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

📄 dstegr.f

📁 计算矩阵的经典开源库.全世界都在用它.相信你也不能例外.
💻 F
字号:
      SUBROUTINE DSTEGR( JOBZ, RANGE, N, D, E, VL, VU, IL, IU, ABSTOL,     $                   M, W, Z, LDZ, ISUPPZ, WORK, LWORK, IWORK,     $                   LIWORK, INFO )**  -- LAPACK computational routine (instru to count ops, 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          JOBZ, RANGE      INTEGER            IL, INFO, IU, LDZ, LIWORK, LWORK, M, N      DOUBLE PRECISION   ABSTOL, VL, VU*     ..*     .. Array Arguments ..      INTEGER            ISUPPZ( * ), IWORK( * )      DOUBLE PRECISION   D( * ), E( * ), W( * ), WORK( * ), Z( LDZ, * )*     ..*     Common block to return operation count*     .. Common blocks ..      COMMON             / LATIME / OPS, ITCNT*     ..*     .. Scalars in Common ..      DOUBLE PRECISION   ITCNT, OPS*     ..**  Purpose*  =======**  DSTEGR computes eigenvalues by the dqds algorithm, while*  orthogonal eigenvectors are computed from various "good" L D L^T*  representations (also known as Relatively Robust Representations).*  Gram-Schmidt orthogonalization is avoided as far as possible. More*  specifically, the various steps of the algorithm are as follows.*  For the i-th unreduced block of T,*     (a) Compute T - sigma_i = L_i D_i L_i^T, such that L_i D_i L_i^T*         is a relatively robust representation,*     (b) Compute the eigenvalues, lambda_j, of L_i D_i L_i^T to high*         relative accuracy by the dqds algorithm,*     (c) If there is a cluster of close eigenvalues, "choose" sigma_i*         close to the cluster, and go to step (a),*     (d) Given the approximate eigenvalue lambda_j of L_i D_i L_i^T,*         compute the corresponding eigenvector by forming a*         rank-revealing twisted factorization.*  The desired accuracy of the output can be specified by the input*  parameter ABSTOL.**  For more details, see "A new O(n^2) algorithm for the symmetric*  tridiagonal eigenvalue/eigenvector problem", by Inderjit Dhillon,*  Computer Science Division Technical Report No. UCB/CSD-97-971,*  UC Berkeley, May 1997.**  Note 1 : Currently DSTEGR is only set up to find ALL the n*  eigenvalues and eigenvectors of T in O(n^2) time*  Note 2 : Currently the routine DSTEIN is called when an appropriate*  sigma_i cannot be chosen in step (c) above. DSTEIN invokes modified*  Gram-Schmidt when eigenvalues are close.*  Note 3 : DSTEGR works only on machines which follow ieee-754*  floating-point standard in their handling of infinities and NaNs.*  Normal execution of DSTEGR may create NaNs and infinities and hence*  may abort due to a floating point exception in environments which*  do not conform to the ieee standard.**  Arguments*  =========**  JOBZ    (input) CHARACTER*1*          = 'N':  Compute eigenvalues only;*          = 'V':  Compute eigenvalues and eigenvectors.**  RANGE   (input) CHARACTER*1*          = 'A': all eigenvalues will be found.*          = 'V': all eigenvalues in the half-open interval (VL,VU]*                 will be found.*          = 'I': the IL-th through IU-th eigenvalues will be found.********** Only RANGE = 'A' is currently supported ***********************  N       (input) INTEGER*          The order of the matrix.  N >= 0.**  D       (input/output) DOUBLE PRECISION array, dimension (N)*          On entry, the n diagonal elements of the tridiagonal matrix*          T. On exit, D is overwritten.**  E       (input/output) DOUBLE PRECISION array, dimension (N)*          On entry, the (n-1) subdiagonal elements of the tridiagonal*          matrix T in elements 1 to N-1 of E; E(N) need not be set.*          On exit, E is overwritten.**  VL      (input) DOUBLE PRECISION*  VU      (input) DOUBLE PRECISION*          If RANGE='V', the lower and upper bounds of the interval to*          be searched for eigenvalues. 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 error tolerance for the*          eigenvalues/eigenvectors. IF JOBZ = 'V', the eigenvalues and*          eigenvectors output have residual norms bounded by ABSTOL,*          and the dot products between different eigenvectors are*          bounded by ABSTOL. If ABSTOL is less than N*EPS*|T|, then*          N*EPS*|T| will be used in its place, where EPS is the*          machine precision and |T| is the 1-norm of the tridiagonal*          matrix. The eigenvalues are computed to an accuracy of*          EPS*|T| irrespective of ABSTOL. If high relative accuracy*          is important, set ABSTOL to DLAMCH( 'Safe minimum' ).*          See Barlow and Demmel "Computing Accurate Eigensystems of*          Scaled Diagonally Dominant Matrices", LAPACK Working Note #7*          for a discussion of which matrices define their eigenvalues*          to high relative accuracy.**  M       (output) INTEGER*          The total number of eigenvalues found.  0 <= M <= N.*          If RANGE = 'A', M = N, and if RANGE = 'I', M = IU-IL+1.**  W       (output) DOUBLE PRECISION array, dimension (N)*          The first M elements contain the selected eigenvalues in*          ascending order.**  Z       (output) DOUBLE PRECISION array, dimension (LDZ, max(1,M) )*          If JOBZ = 'V', then if INFO = 0, the first M columns of Z*          contain the orthonormal eigenvectors of the matrix T*          corresponding to the selected eigenvalues, with the i-th*          column of Z holding the eigenvector associated with W(i).*          If JOBZ = 'N', then Z is not referenced.*          Note: the user must ensure that at least max(1,M) columns are*          supplied in the array Z; if RANGE = 'V', the exact value of M*          is not known in advance and an upper bound must be used.**  LDZ     (input) INTEGER*          The leading dimension of the array Z.  LDZ >= 1, and if*          JOBZ = 'V', LDZ >= max(1,N).**  ISUPPZ  (output) INTEGER ARRAY, dimension ( 2*max(1,M) )*          The support of the eigenvectors in Z, i.e., the indices*          indicating the nonzero elements in Z. The i-th eigenvector*          is nonzero only in elements ISUPPZ( 2*i-1 ) through*          ISUPPZ( 2*i ).**  WORK    (workspace/output) DOUBLE PRECISION array, dimension (LWORK)*          On exit, if INFO = 0, WORK(1) returns the optimal*          (and minimal) LWORK.**  LWORK   (input) INTEGER*          The dimension of the array WORK.  LWORK >= max(1,18*N)**          If LWORK = -1, then a workspace query is assumed; the routine*          only calculates the optimal size of the WORK array, returns*          this value as the first entry of the WORK array, and no error*          message related to LWORK is issued by XERBLA.**  IWORK   (workspace/output) INTEGER array, dimension (LIWORK)*          On exit, if INFO = 0, IWORK(1) returns the optimal LIWORK.**  LIWORK  (input) INTEGER*          The dimension of the array IWORK.  LIWORK >= max(1,10*N)**          If LIWORK = -1, then a workspace query is assumed; the*          routine only calculates the optimal size of the IWORK array,*          returns this value as the first entry of the IWORK array, and*          no error message related to LIWORK is issued by XERBLA.**  INFO    (output) INTEGER*          = 0:  successful exit*          < 0:  if INFO = -i, the i-th argument had an illegal value*          > 0:  if INFO = 1, internal error in DLARRE,*                if INFO = 2, internal error in DLARRV.**  Further Details*  ===============**  Based on contributions by*     Inderjit Dhillon, IBM Almaden, USA*     Osni Marques, LBNL/NERSC, USA**  =====================================================================**     .. Parameters ..      DOUBLE PRECISION   ZERO, ONE      PARAMETER          ( ZERO = 0.0D0, ONE = 1.0D0 )*     ..*     .. Local Scalars ..      LOGICAL            ALLEIG, INDEIG, LQUERY, VALEIG, WANTZ      INTEGER            I, IBEGIN, IEND, IINDBL, IINDWK, IINFO, IINSPL,     $                   INDGRS, INDWOF, INDWRK, ITMP, J, JJ, LIWMIN,     $                   LWMIN, NSPLIT      DOUBLE PRECISION   BIGNUM, EPS, RMAX, RMIN, SAFMIN, SCALE, SMLNUM,     $                   THRESH, TMP, TNRM, TOL*     ..*     .. External Functions ..      LOGICAL            LSAME      DOUBLE PRECISION   DLAMCH, DLANST      EXTERNAL           LSAME, DLAMCH, DLANST*     ..*     .. External Subroutines ..      EXTERNAL           DLARRE, DLARRV, DLASET, DSCAL, DSWAP, XERBLA*     ..*     .. Intrinsic Functions ..      INTRINSIC          DBLE, MAX, MIN, SQRT*     ..*     .. Executable Statements ..**     Test the input parameters.*      WANTZ = LSAME( JOBZ, 'V' )      ALLEIG = LSAME( RANGE, 'A' )      VALEIG = LSAME( RANGE, 'V' )      INDEIG = LSAME( RANGE, 'I' )*      LQUERY = ( ( LWORK.EQ.-1 ) .OR. ( LIWORK.EQ.-1 ) )      LWMIN = 18*N      LIWMIN = 10*N*      INFO = 0      IF( .NOT.( WANTZ .OR. LSAME( JOBZ, 'N' ) ) ) THEN         INFO = -1      ELSE IF( .NOT.( ALLEIG .OR. VALEIG .OR. INDEIG ) ) THEN         INFO = -2**     The following two lines need to be removed once the*     RANGE = 'V' and RANGE = 'I' options are provided.*      ELSE IF( VALEIG .OR. INDEIG ) THEN         INFO = -2      ELSE IF( N.LT.0 ) THEN         INFO = -3      ELSE IF( VALEIG .AND. N.GT.0 .AND. VU.LE.VL ) THEN         INFO = -7      ELSE IF( INDEIG .AND. IL.LT.1 ) THEN         INFO = -8*     The following change should be made in DSTEVX also, otherwise*     IL can be specified as N+1 and IU as N.*     ELSE IF( INDEIG .AND. ( IU.LT.MIN( N, IL ) .OR. IU.GT.N ) ) THEN      ELSE IF( INDEIG .AND. ( IU.LT.IL .OR. IU.GT.N ) ) THEN         INFO = -9      ELSE IF( LDZ.LT.1 .OR. ( WANTZ .AND. LDZ.LT.N ) ) THEN         INFO = -14      ELSE IF( LWORK.LT.LWMIN .AND. .NOT.LQUERY ) THEN         INFO = -17      ELSE IF( LIWORK.LT.LIWMIN .AND. .NOT.LQUERY ) THEN         INFO = -19      END IF      IF( INFO.EQ.0 ) THEN         WORK( 1 ) = LWMIN         IWORK( 1 ) = LIWMIN      END IF*      IF( INFO.NE.0 ) THEN         CALL XERBLA( 'DSTEGR', -INFO )         RETURN      ELSE IF( LQUERY ) THEN         RETURN      END IF**     Quick return if possible*      M = 0      IF( N.EQ.0 )     $   RETURN*      IF( N.EQ.1 ) THEN         IF( ALLEIG .OR. INDEIG ) THEN            M = 1            W( 1 ) = D( 1 )         ELSE            IF( VL.LT.D( 1 ) .AND. VU.GE.D( 1 ) ) THEN               M = 1               W( 1 ) = D( 1 )            END IF         END IF         IF( WANTZ )     $      Z( 1, 1 ) = ONE         RETURN      END IF**     Get machine constants.*      OPS = OPS + DBLE( 7 )      SAFMIN = DLAMCH( 'Safe minimum' )      EPS = DLAMCH( 'Precision' )      SMLNUM = SAFMIN / EPS      BIGNUM = ONE / SMLNUM      RMIN = SQRT( SMLNUM )      RMAX = MIN( SQRT( BIGNUM ), ONE / SQRT( SQRT( SAFMIN ) ) )**     Scale matrix to allowable range, if necessary.*      SCALE = ONE      TNRM = DLANST( 'M', N, D, E )      IF( TNRM.GT.ZERO .AND. TNRM.LT.RMIN ) THEN         OPS = OPS + DBLE( 1 )         SCALE = RMIN / TNRM      ELSE IF( TNRM.GT.RMAX ) THEN         OPS = OPS + DBLE( 1 )         SCALE = RMAX / TNRM      END IF      IF( SCALE.NE.ONE ) THEN         OPS = OPS + DBLE( 2*N )         CALL DSCAL( N, SCALE, D, 1 )         CALL DSCAL( N-1, SCALE, E, 1 )         TNRM = TNRM*SCALE      END IF      INDGRS = 1      INDWOF = 2*N + 1      INDWRK = 3*N + 1*      IINSPL = 1      IINDBL = N + 1      IINDWK = 2*N + 1*      CALL DLASET( 'Full', N, N, ZERO, ZERO, Z, LDZ )**     Compute the desired eigenvalues of the tridiagonal after splitting*     into smaller subblocks if the corresponding of-diagonal elements*     are small*      OPS = OPS + DBLE( 1 )      THRESH = EPS*TNRM      CALL DLARRE( N, D, E, THRESH, NSPLIT, IWORK( IINSPL ), M, W,     $             WORK( INDWOF ), WORK( INDGRS ), WORK( INDWRK ),     $             IINFO )      IF( IINFO.NE.0 ) THEN         INFO = 1         RETURN      END IF*      IF( WANTZ ) THEN**        Compute the desired eigenvectors corresponding to the computed*        eigenvalues*         OPS = OPS + DBLE( 1 )         TOL = MAX( ABSTOL, DBLE( N )*THRESH )         IBEGIN = 1         DO 20 I = 1, NSPLIT            IEND = IWORK( IINSPL+I-1 )            DO 10 J = IBEGIN, IEND               IWORK( IINDBL+J-1 ) = I   10       CONTINUE            IBEGIN = IEND + 1   20    CONTINUE*         CALL DLARRV( N, D, E, IWORK( IINSPL ), M, W, IWORK( IINDBL ),     $                WORK( INDGRS ), TOL, Z, LDZ, ISUPPZ,     $                WORK( INDWRK ), IWORK( IINDWK ), IINFO )         IF( IINFO.NE.0 ) THEN            INFO = 2            RETURN         END IF*      END IF*      IBEGIN = 1      DO 40 I = 1, NSPLIT         IEND = IWORK( IINSPL+I-1 )         DO 30 J = IBEGIN, IEND            OPS = OPS + DBLE( 1 )            W( J ) = W( J ) + WORK( INDWOF+I-1 )   30    CONTINUE         IBEGIN = IEND + 1   40 CONTINUE**     If matrix was scaled, then rescale eigenvalues appropriately.*      IF( SCALE.NE.ONE ) THEN         CALL DSCAL( M, ONE / SCALE, W, 1 )      END IF**     If eigenvalues are not in order, then sort them, along with*     eigenvectors.*      IF( NSPLIT.GT.1 ) THEN         DO 60 J = 1, M - 1            I = 0            TMP = W( J )            DO 50 JJ = J + 1, M               IF( W( JJ ).LT.TMP ) THEN                  I = JJ                  TMP = W( JJ )               END IF   50       CONTINUE            IF( I.NE.0 ) THEN               W( I ) = W( J )               W( J ) = TMP               IF( WANTZ ) THEN                  CALL DSWAP( N, Z( 1, I ), 1, Z( 1, J ), 1 )                  ITMP = ISUPPZ( 2*I-1 )                  ISUPPZ( 2*I-1 ) = ISUPPZ( 2*J-1 )                  ISUPPZ( 2*J-1 ) = ITMP                  ITMP = ISUPPZ( 2*I )                  ISUPPZ( 2*I ) = ISUPPZ( 2*J )                  ISUPPZ( 2*J ) = ITMP               END IF            END IF   60    CONTINUE      END IF*      WORK( 1 ) = LWMIN      IWORK( 1 ) = LIWMIN      RETURN**     End of DSTEGR*      END

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -