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

📄 dstein.f

📁 计算矩阵的经典开源库.全世界都在用它.相信你也不能例外.
💻 F
字号:
      SUBROUTINE DSTEIN( N, D, E, M, W, IBLOCK, ISPLIT, Z, LDZ, WORK,     $                   IWORK, IFAIL, 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*     September 30, 1994**     .. Scalar Arguments ..      INTEGER            INFO, LDZ, M, N*     ..*     .. Array Arguments ..      INTEGER            IBLOCK( * ), IFAIL( * ), ISPLIT( * ),     $                   IWORK( * )      DOUBLE PRECISION   D( * ), E( * ), W( * ), WORK( * ), Z( LDZ, * )*     ..*     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*  =======**  DSTEIN computes the eigenvectors of a real symmetric tridiagonal*  matrix T corresponding to specified eigenvalues, using inverse*  iteration.**  The maximum number of iterations allowed for each eigenvector is*  specified by an internal parameter MAXITS (currently set to 5).**  Arguments*  =========**  N       (input) INTEGER*          The order of the matrix.  N >= 0.**  D       (input) DOUBLE PRECISION array, dimension (N)*          The n diagonal elements of the tridiagonal matrix T.**  E       (input) DOUBLE PRECISION array, dimension (N)*          The (n-1) subdiagonal elements of the tridiagonal matrix*          T, in elements 1 to N-1.  E(N) need not be set.**  M       (input) INTEGER*          The number of eigenvectors to be found.  0 <= M <= N.**  W       (input) DOUBLE PRECISION array, dimension (N)*          The first M elements of W contain the eigenvalues for*          which eigenvectors are to be computed.  The eigenvalues*          should be grouped by split-off block and ordered from*          smallest to largest within the block.  ( The output array*          W from DSTEBZ with ORDER = 'B' is expected here. )**  IBLOCK  (input) INTEGER array, dimension (N)*          The submatrix indices associated with the corresponding*          eigenvalues in W; IBLOCK(i)=1 if eigenvalue W(i) belongs to*          the first submatrix from the top, =2 if W(i) belongs to*          the second submatrix, etc.  ( The output array IBLOCK*          from DSTEBZ is expected here. )**  ISPLIT  (input) 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.*          ( The output array ISPLIT from DSTEBZ is expected here. )**  Z       (output) DOUBLE PRECISION array, dimension (LDZ, M)*          The computed eigenvectors.  The eigenvector associated*          with the eigenvalue W(i) is stored in the i-th column of*          Z.  Any vector which fails to converge is set to its current*          iterate after MAXITS iterations.**  LDZ     (input) INTEGER*          The leading dimension of the array Z.  LDZ >= max(1,N).**  WORK    (workspace) DOUBLE PRECISION array, dimension (5*N)**  IWORK   (workspace) INTEGER array, dimension (N)**  IFAIL   (output) INTEGER array, dimension (M)*          On normal exit, all elements of IFAIL are zero.*          If one or more eigenvectors fail to converge after*          MAXITS iterations, then their indices are stored in*          array IFAIL.**  INFO    (output) INTEGER*          = 0: successful exit.*          < 0: if INFO = -i, the i-th argument had an illegal value*          > 0: if INFO = i, then i eigenvectors failed to converge*               in MAXITS iterations.  Their indices are stored in*               array IFAIL.**  Internal Parameters*  ===================**  MAXITS  INTEGER, default = 5*          The maximum number of iterations performed.**  EXTRA   INTEGER, default = 2*          The number of iterations performed after norm growth*          criterion is satisfied, should be at least 1.**  =====================================================================**     .. Parameters ..      DOUBLE PRECISION   ZERO, ONE, TEN, ODM3, ODM1      PARAMETER          ( ZERO = 0.0D+0, ONE = 1.0D+0, TEN = 1.0D+1,     $                   ODM3 = 1.0D-3, ODM1 = 1.0D-1 )      INTEGER            MAXITS, EXTRA      PARAMETER          ( MAXITS = 5, EXTRA = 2 )*     ..*     .. Local Scalars ..      INTEGER            B1, BLKSIZ, BN, GPIND, I, IINFO, INDRV1,     $                   INDRV2, INDRV3, INDRV4, INDRV5, ITS, J, J1,     $                   JBLK, JMAX, NBLK, NRMCHK      DOUBLE PRECISION   DTPCRT, EPS, EPS1, NRM, ONENRM, ORTOL, PERTOL,     $                   SCL, SEP, TOL, XJ, XJM, ZTR*     ..*     .. Local Arrays ..      INTEGER            ISEED( 4 )*     ..*     .. External Functions ..      INTEGER            IDAMAX      DOUBLE PRECISION   DASUM, DDOT, DLAMCH, DNRM2      EXTERNAL           IDAMAX, DASUM, DDOT, DLAMCH, DNRM2*     ..*     .. External Subroutines ..      EXTERNAL           DAXPY, DCOPY, DLAGTF, DLAGTS, DLARNV, DSCAL,     $                   XERBLA*     ..*     .. Intrinsic Functions ..      INTRINSIC          ABS, MAX, SQRT*     ..*     .. Executable Statements ..**     Test the input parameters.*      INFO = 0      DO 10 I = 1, M         IFAIL( I ) = 0   10 CONTINUE*      IF( N.LT.0 ) THEN         INFO = -1      ELSE IF( M.LT.0 .OR. M.GT.N ) THEN         INFO = -4      ELSE IF( LDZ.LT.MAX( 1, N ) ) THEN         INFO = -9      ELSE         DO 20 J = 2, M            IF( IBLOCK( J ).LT.IBLOCK( J-1 ) ) THEN               INFO = -6               GO TO 30            END IF            IF( IBLOCK( J ).EQ.IBLOCK( J-1 ) .AND. W( J ).LT.W( J-1 ) )     $           THEN               INFO = -5               GO TO 30            END IF   20    CONTINUE   30    CONTINUE      END IF*      IF( INFO.NE.0 ) THEN         CALL XERBLA( 'DSTEIN', -INFO )         RETURN      END IF**     Initialize iteration count.*      ITCNT = 0**     Quick return if possible*      IF( N.EQ.0 .OR. M.EQ.0 ) THEN         RETURN      ELSE IF( N.EQ.1 ) THEN         Z( 1, 1 ) = ONE         RETURN      END IF**     Get machine constants.*      EPS = DLAMCH( 'Precision' )**     Initialize seed for random number generator DLARNV.*      DO 40 I = 1, 4         ISEED( I ) = 1   40 CONTINUE**     Initialize pointers.*      INDRV1 = 0      INDRV2 = INDRV1 + N      INDRV3 = INDRV2 + N      INDRV4 = INDRV3 + N      INDRV5 = INDRV4 + N**     Compute eigenvectors of matrix blocks.*      J1 = 1      DO 160 NBLK = 1, IBLOCK( M )**        Find starting and ending indices of block nblk.*         IF( NBLK.EQ.1 ) THEN            B1 = 1         ELSE            B1 = ISPLIT( NBLK-1 ) + 1         END IF         BN = ISPLIT( NBLK )         BLKSIZ = BN - B1 + 1         IF( BLKSIZ.EQ.1 )     $      GO TO 60         GPIND = B1**        Compute reorthogonalization criterion and stopping criterion.*         ONENRM = ABS( D( B1 ) ) + ABS( E( B1 ) )         ONENRM = MAX( ONENRM, ABS( D( BN ) )+ABS( E( BN-1 ) ) )         DO 50 I = B1 + 1, BN - 1            ONENRM = MAX( ONENRM, ABS( D( I ) )+ABS( E( I-1 ) )+     $               ABS( E( I ) ) )   50    CONTINUE         ORTOL = ODM3*ONENRM*         DTPCRT = SQRT( ODM1 / BLKSIZ )**        Increment opcount for computing criteria.*         OPS = OPS + ( BN-B1 )*2 + 3**        Loop through eigenvalues of block nblk.*   60    CONTINUE         JBLK = 0         DO 150 J = J1, M            IF( IBLOCK( J ).NE.NBLK ) THEN               J1 = J               GO TO 160            END IF            JBLK = JBLK + 1            XJ = W( J )**           Skip all the work if the block size is one.*            IF( BLKSIZ.EQ.1 ) THEN               WORK( INDRV1+1 ) = ONE               GO TO 120            END IF**           If eigenvalues j and j-1 are too close, add a relatively*           small perturbation.*            IF( JBLK.GT.1 ) THEN               EPS1 = ABS( EPS*XJ )               PERTOL = TEN*EPS1               SEP = XJ - XJM               IF( SEP.LT.PERTOL )     $            XJ = XJM + PERTOL            END IF*            ITS = 0            NRMCHK = 0**           Get random starting vector.*            CALL DLARNV( 2, ISEED, BLKSIZ, WORK( INDRV1+1 ) )**           Increment opcount for getting random starting vector.*           ( DLARND(2,.) requires 9 flops. )*            OPS = OPS + BLKSIZ*9**           Copy the matrix T so it won't be destroyed in factorization.*            CALL DCOPY( BLKSIZ, D( B1 ), 1, WORK( INDRV4+1 ), 1 )            CALL DCOPY( BLKSIZ-1, E( B1 ), 1, WORK( INDRV2+2 ), 1 )            CALL DCOPY( BLKSIZ-1, E( B1 ), 1, WORK( INDRV3+1 ), 1 )**           Compute LU factors with partial pivoting  ( PT = LU )*            TOL = ZERO            CALL DLAGTF( BLKSIZ, WORK( INDRV4+1 ), XJ, WORK( INDRV2+2 ),     $                   WORK( INDRV3+1 ), TOL, WORK( INDRV5+1 ), IWORK,     $                   IINFO )**           Increment opcount for computing LU factors.*           ( DLAGTF(BLKSIZ,...) requires about 8*BLKSIZ flops. )*            OPS = OPS + 8*BLKSIZ**           Update iteration count.*   70       CONTINUE            ITS = ITS + 1            IF( ITS.GT.MAXITS )     $         GO TO 100**           Normalize and scale the righthand side vector Pb.*            SCL = BLKSIZ*ONENRM*MAX( EPS,     $            ABS( WORK( INDRV4+BLKSIZ ) ) ) /     $            DASUM( BLKSIZ, WORK( INDRV1+1 ), 1 )            CALL DSCAL( BLKSIZ, SCL, WORK( INDRV1+1 ), 1 )**           Solve the system LU = Pb.*            CALL DLAGTS( -1, BLKSIZ, WORK( INDRV4+1 ), WORK( INDRV2+2 ),     $                   WORK( INDRV3+1 ), WORK( INDRV5+1 ), IWORK,     $                   WORK( INDRV1+1 ), TOL, IINFO )**           Increment opcount for scaling and solving linear system.*           ( DLAGTS(-1,BLKSIZ,...) requires about 8*BLKSIZ flops. )*            OPS = OPS + 3 + 10*BLKSIZ**           Reorthogonalize by modified Gram-Schmidt if eigenvalues are*           close enough.*            IF( JBLK.EQ.1 )     $         GO TO 90            IF( ABS( XJ-XJM ).GT.ORTOL )     $         GPIND = J            IF( GPIND.NE.J ) THEN               DO 80 I = GPIND, J - 1                  ZTR = -DDOT( BLKSIZ, WORK( INDRV1+1 ), 1, Z( B1, I ),     $                  1 )                  CALL DAXPY( BLKSIZ, ZTR, Z( B1, I ), 1,     $                        WORK( INDRV1+1 ), 1 )   80          CONTINUE**              Increment opcount for reorthogonalizing.*               OPS = OPS + ( J-GPIND )*BLKSIZ*4*            END IF**           Check the infinity norm of the iterate.*   90       CONTINUE            JMAX = IDAMAX( BLKSIZ, WORK( INDRV1+1 ), 1 )            NRM = ABS( WORK( INDRV1+JMAX ) )**           Continue for additional iterations after norm reaches*           stopping criterion.*            IF( NRM.LT.DTPCRT )     $         GO TO 70            NRMCHK = NRMCHK + 1            IF( NRMCHK.LT.EXTRA+1 )     $         GO TO 70*            GO TO 110**           If stopping criterion was not satisfied, update info and*           store eigenvector number in array ifail.*  100       CONTINUE            INFO = INFO + 1            IFAIL( INFO ) = J**           Accept iterate as jth eigenvector.*  110       CONTINUE            SCL = ONE / DNRM2( BLKSIZ, WORK( INDRV1+1 ), 1 )            JMAX = IDAMAX( BLKSIZ, WORK( INDRV1+1 ), 1 )            IF( WORK( INDRV1+JMAX ).LT.ZERO )     $         SCL = -SCL            CALL DSCAL( BLKSIZ, SCL, WORK( INDRV1+1 ), 1 )**           Increment opcount for scaling.*            OPS = OPS + 3*BLKSIZ*  120       CONTINUE            DO 130 I = 1, N               Z( I, J ) = ZERO  130       CONTINUE            DO 140 I = 1, BLKSIZ               Z( B1+I-1, J ) = WORK( INDRV1+I )  140       CONTINUE**           Save the shift to check eigenvalue spacing at next*           iteration.*            XJM = XJ*  150    CONTINUE  160 CONTINUE*      RETURN**     End of DSTEIN*      END

⌨️ 快捷键说明

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