LAPACK 3.3.1 Linear Algebra PACKage

# zstein.f

Go to the documentation of this file.
```00001       SUBROUTINE ZSTEIN( N, D, E, M, W, IBLOCK, ISPLIT, Z, LDZ, WORK,
00002      \$                   IWORK, IFAIL, INFO )
00003 *
00004 *  -- LAPACK routine (version 3.2) --
00005 *  -- LAPACK is a software package provided by Univ. of Tennessee,    --
00006 *  -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..--
00007 *     November 2006
00008 *
00009 *     .. Scalar Arguments ..
00010       INTEGER            INFO, LDZ, M, N
00011 *     ..
00012 *     .. Array Arguments ..
00013       INTEGER            IBLOCK( * ), IFAIL( * ), ISPLIT( * ),
00014      \$                   IWORK( * )
00015       DOUBLE PRECISION   D( * ), E( * ), W( * ), WORK( * )
00016       COMPLEX*16         Z( LDZ, * )
00017 *     ..
00018 *
00019 *  Purpose
00020 *  =======
00021 *
00022 *  ZSTEIN computes the eigenvectors of a real symmetric tridiagonal
00023 *  matrix T corresponding to specified eigenvalues, using inverse
00024 *  iteration.
00025 *
00026 *  The maximum number of iterations allowed for each eigenvector is
00027 *  specified by an internal parameter MAXITS (currently set to 5).
00028 *
00029 *  Although the eigenvectors are real, they are stored in a complex
00030 *  array, which may be passed to ZUNMTR or ZUPMTR for back
00031 *  transformation to the eigenvectors of a complex Hermitian matrix
00032 *  which was reduced to tridiagonal form.
00033 *
00034 *
00035 *  Arguments
00036 *  =========
00037 *
00038 *  N       (input) INTEGER
00039 *          The order of the matrix.  N >= 0.
00040 *
00041 *  D       (input) DOUBLE PRECISION array, dimension (N)
00042 *          The n diagonal elements of the tridiagonal matrix T.
00043 *
00044 *  E       (input) DOUBLE PRECISION array, dimension (N-1)
00045 *          The (n-1) subdiagonal elements of the tridiagonal matrix
00046 *          T, stored in elements 1 to N-1.
00047 *
00048 *  M       (input) INTEGER
00049 *          The number of eigenvectors to be found.  0 <= M <= N.
00050 *
00051 *  W       (input) DOUBLE PRECISION array, dimension (N)
00052 *          The first M elements of W contain the eigenvalues for
00053 *          which eigenvectors are to be computed.  The eigenvalues
00054 *          should be grouped by split-off block and ordered from
00055 *          smallest to largest within the block.  ( The output array
00056 *          W from DSTEBZ with ORDER = 'B' is expected here. )
00057 *
00058 *  IBLOCK  (input) INTEGER array, dimension (N)
00059 *          The submatrix indices associated with the corresponding
00060 *          eigenvalues in W; IBLOCK(i)=1 if eigenvalue W(i) belongs to
00061 *          the first submatrix from the top, =2 if W(i) belongs to
00062 *          the second submatrix, etc.  ( The output array IBLOCK
00063 *          from DSTEBZ is expected here. )
00064 *
00065 *  ISPLIT  (input) INTEGER array, dimension (N)
00066 *          The splitting points, at which T breaks up into submatrices.
00067 *          The first submatrix consists of rows/columns 1 to
00068 *          ISPLIT( 1 ), the second of rows/columns ISPLIT( 1 )+1
00069 *          through ISPLIT( 2 ), etc.
00070 *          ( The output array ISPLIT from DSTEBZ is expected here. )
00071 *
00072 *  Z       (output) COMPLEX*16 array, dimension (LDZ, M)
00073 *          The computed eigenvectors.  The eigenvector associated
00074 *          with the eigenvalue W(i) is stored in the i-th column of
00075 *          Z.  Any vector which fails to converge is set to its current
00076 *          iterate after MAXITS iterations.
00077 *          The imaginary parts of the eigenvectors are set to zero.
00078 *
00079 *  LDZ     (input) INTEGER
00080 *          The leading dimension of the array Z.  LDZ >= max(1,N).
00081 *
00082 *  WORK    (workspace) DOUBLE PRECISION array, dimension (5*N)
00083 *
00084 *  IWORK   (workspace) INTEGER array, dimension (N)
00085 *
00086 *  IFAIL   (output) INTEGER array, dimension (M)
00087 *          On normal exit, all elements of IFAIL are zero.
00088 *          If one or more eigenvectors fail to converge after
00089 *          MAXITS iterations, then their indices are stored in
00090 *          array IFAIL.
00091 *
00092 *  INFO    (output) INTEGER
00093 *          = 0: successful exit
00094 *          < 0: if INFO = -i, the i-th argument had an illegal value
00095 *          > 0: if INFO = i, then i eigenvectors failed to converge
00096 *               in MAXITS iterations.  Their indices are stored in
00097 *               array IFAIL.
00098 *
00099 *  Internal Parameters
00100 *  ===================
00101 *
00102 *  MAXITS  INTEGER, default = 5
00103 *          The maximum number of iterations performed.
00104 *
00105 *  EXTRA   INTEGER, default = 2
00106 *          The number of iterations performed after norm growth
00107 *          criterion is satisfied, should be at least 1.
00108 *
00109 * =====================================================================
00110 *
00111 *     .. Parameters ..
00112       COMPLEX*16         CZERO, CONE
00113       PARAMETER          ( CZERO = ( 0.0D+0, 0.0D+0 ),
00114      \$                   CONE = ( 1.0D+0, 0.0D+0 ) )
00115       DOUBLE PRECISION   ZERO, ONE, TEN, ODM3, ODM1
00116       PARAMETER          ( ZERO = 0.0D+0, ONE = 1.0D+0, TEN = 1.0D+1,
00117      \$                   ODM3 = 1.0D-3, ODM1 = 1.0D-1 )
00118       INTEGER            MAXITS, EXTRA
00119       PARAMETER          ( MAXITS = 5, EXTRA = 2 )
00120 *     ..
00121 *     .. Local Scalars ..
00122       INTEGER            B1, BLKSIZ, BN, GPIND, I, IINFO, INDRV1,
00123      \$                   INDRV2, INDRV3, INDRV4, INDRV5, ITS, J, J1,
00124      \$                   JBLK, JMAX, JR, NBLK, NRMCHK
00125       DOUBLE PRECISION   DTPCRT, EPS, EPS1, NRM, ONENRM, ORTOL, PERTOL,
00126      \$                   SCL, SEP, TOL, XJ, XJM, ZTR
00127 *     ..
00128 *     .. Local Arrays ..
00129       INTEGER            ISEED( 4 )
00130 *     ..
00131 *     .. External Functions ..
00132       INTEGER            IDAMAX
00133       DOUBLE PRECISION   DASUM, DLAMCH, DNRM2
00134       EXTERNAL           IDAMAX, DASUM, DLAMCH, DNRM2
00135 *     ..
00136 *     .. External Subroutines ..
00137       EXTERNAL           DCOPY, DLAGTF, DLAGTS, DLARNV, DSCAL, XERBLA
00138 *     ..
00139 *     .. Intrinsic Functions ..
00140       INTRINSIC          ABS, DBLE, DCMPLX, MAX, SQRT
00141 *     ..
00142 *     .. Executable Statements ..
00143 *
00144 *     Test the input parameters.
00145 *
00146       INFO = 0
00147       DO 10 I = 1, M
00148          IFAIL( I ) = 0
00149    10 CONTINUE
00150 *
00151       IF( N.LT.0 ) THEN
00152          INFO = -1
00153       ELSE IF( M.LT.0 .OR. M.GT.N ) THEN
00154          INFO = -4
00155       ELSE IF( LDZ.LT.MAX( 1, N ) ) THEN
00156          INFO = -9
00157       ELSE
00158          DO 20 J = 2, M
00159             IF( IBLOCK( J ).LT.IBLOCK( J-1 ) ) THEN
00160                INFO = -6
00161                GO TO 30
00162             END IF
00163             IF( IBLOCK( J ).EQ.IBLOCK( J-1 ) .AND. W( J ).LT.W( J-1 ) )
00164      \$           THEN
00165                INFO = -5
00166                GO TO 30
00167             END IF
00168    20    CONTINUE
00169    30    CONTINUE
00170       END IF
00171 *
00172       IF( INFO.NE.0 ) THEN
00173          CALL XERBLA( 'ZSTEIN', -INFO )
00174          RETURN
00175       END IF
00176 *
00177 *     Quick return if possible
00178 *
00179       IF( N.EQ.0 .OR. M.EQ.0 ) THEN
00180          RETURN
00181       ELSE IF( N.EQ.1 ) THEN
00182          Z( 1, 1 ) = CONE
00183          RETURN
00184       END IF
00185 *
00186 *     Get machine constants.
00187 *
00188       EPS = DLAMCH( 'Precision' )
00189 *
00190 *     Initialize seed for random number generator DLARNV.
00191 *
00192       DO 40 I = 1, 4
00193          ISEED( I ) = 1
00194    40 CONTINUE
00195 *
00196 *     Initialize pointers.
00197 *
00198       INDRV1 = 0
00199       INDRV2 = INDRV1 + N
00200       INDRV3 = INDRV2 + N
00201       INDRV4 = INDRV3 + N
00202       INDRV5 = INDRV4 + N
00203 *
00204 *     Compute eigenvectors of matrix blocks.
00205 *
00206       J1 = 1
00207       DO 180 NBLK = 1, IBLOCK( M )
00208 *
00209 *        Find starting and ending indices of block nblk.
00210 *
00211          IF( NBLK.EQ.1 ) THEN
00212             B1 = 1
00213          ELSE
00214             B1 = ISPLIT( NBLK-1 ) + 1
00215          END IF
00216          BN = ISPLIT( NBLK )
00217          BLKSIZ = BN - B1 + 1
00218          IF( BLKSIZ.EQ.1 )
00219      \$      GO TO 60
00220          GPIND = B1
00221 *
00222 *        Compute reorthogonalization criterion and stopping criterion.
00223 *
00224          ONENRM = ABS( D( B1 ) ) + ABS( E( B1 ) )
00225          ONENRM = MAX( ONENRM, ABS( D( BN ) )+ABS( E( BN-1 ) ) )
00226          DO 50 I = B1 + 1, BN - 1
00227             ONENRM = MAX( ONENRM, ABS( D( I ) )+ABS( E( I-1 ) )+
00228      \$               ABS( E( I ) ) )
00229    50    CONTINUE
00230          ORTOL = ODM3*ONENRM
00231 *
00232          DTPCRT = SQRT( ODM1 / BLKSIZ )
00233 *
00234 *        Loop through eigenvalues of block nblk.
00235 *
00236    60    CONTINUE
00237          JBLK = 0
00238          DO 170 J = J1, M
00239             IF( IBLOCK( J ).NE.NBLK ) THEN
00240                J1 = J
00241                GO TO 180
00242             END IF
00243             JBLK = JBLK + 1
00244             XJ = W( J )
00245 *
00246 *           Skip all the work if the block size is one.
00247 *
00248             IF( BLKSIZ.EQ.1 ) THEN
00249                WORK( INDRV1+1 ) = ONE
00250                GO TO 140
00251             END IF
00252 *
00253 *           If eigenvalues j and j-1 are too close, add a relatively
00254 *           small perturbation.
00255 *
00256             IF( JBLK.GT.1 ) THEN
00257                EPS1 = ABS( EPS*XJ )
00258                PERTOL = TEN*EPS1
00259                SEP = XJ - XJM
00260                IF( SEP.LT.PERTOL )
00261      \$            XJ = XJM + PERTOL
00262             END IF
00263 *
00264             ITS = 0
00265             NRMCHK = 0
00266 *
00267 *           Get random starting vector.
00268 *
00269             CALL DLARNV( 2, ISEED, BLKSIZ, WORK( INDRV1+1 ) )
00270 *
00271 *           Copy the matrix T so it won't be destroyed in factorization.
00272 *
00273             CALL DCOPY( BLKSIZ, D( B1 ), 1, WORK( INDRV4+1 ), 1 )
00274             CALL DCOPY( BLKSIZ-1, E( B1 ), 1, WORK( INDRV2+2 ), 1 )
00275             CALL DCOPY( BLKSIZ-1, E( B1 ), 1, WORK( INDRV3+1 ), 1 )
00276 *
00277 *           Compute LU factors with partial pivoting  ( PT = LU )
00278 *
00279             TOL = ZERO
00280             CALL DLAGTF( BLKSIZ, WORK( INDRV4+1 ), XJ, WORK( INDRV2+2 ),
00281      \$                   WORK( INDRV3+1 ), TOL, WORK( INDRV5+1 ), IWORK,
00282      \$                   IINFO )
00283 *
00284 *           Update iteration count.
00285 *
00286    70       CONTINUE
00287             ITS = ITS + 1
00288             IF( ITS.GT.MAXITS )
00289      \$         GO TO 120
00290 *
00291 *           Normalize and scale the righthand side vector Pb.
00292 *
00293             SCL = BLKSIZ*ONENRM*MAX( EPS,
00294      \$            ABS( WORK( INDRV4+BLKSIZ ) ) ) /
00295      \$            DASUM( BLKSIZ, WORK( INDRV1+1 ), 1 )
00296             CALL DSCAL( BLKSIZ, SCL, WORK( INDRV1+1 ), 1 )
00297 *
00298 *           Solve the system LU = Pb.
00299 *
00300             CALL DLAGTS( -1, BLKSIZ, WORK( INDRV4+1 ), WORK( INDRV2+2 ),
00301      \$                   WORK( INDRV3+1 ), WORK( INDRV5+1 ), IWORK,
00302      \$                   WORK( INDRV1+1 ), TOL, IINFO )
00303 *
00304 *           Reorthogonalize by modified Gram-Schmidt if eigenvalues are
00305 *           close enough.
00306 *
00307             IF( JBLK.EQ.1 )
00308      \$         GO TO 110
00309             IF( ABS( XJ-XJM ).GT.ORTOL )
00310      \$         GPIND = J
00311             IF( GPIND.NE.J ) THEN
00312                DO 100 I = GPIND, J - 1
00313                   ZTR = ZERO
00314                   DO 80 JR = 1, BLKSIZ
00315                      ZTR = ZTR + WORK( INDRV1+JR )*
00316      \$                     DBLE( Z( B1-1+JR, I ) )
00317    80             CONTINUE
00318                   DO 90 JR = 1, BLKSIZ
00319                      WORK( INDRV1+JR ) = WORK( INDRV1+JR ) -
00320      \$                                   ZTR*DBLE( Z( B1-1+JR, I ) )
00321    90             CONTINUE
00322   100          CONTINUE
00323             END IF
00324 *
00325 *           Check the infinity norm of the iterate.
00326 *
00327   110       CONTINUE
00328             JMAX = IDAMAX( BLKSIZ, WORK( INDRV1+1 ), 1 )
00329             NRM = ABS( WORK( INDRV1+JMAX ) )
00330 *
00331 *           Continue for additional iterations after norm reaches
00332 *           stopping criterion.
00333 *
00334             IF( NRM.LT.DTPCRT )
00335      \$         GO TO 70
00336             NRMCHK = NRMCHK + 1
00337             IF( NRMCHK.LT.EXTRA+1 )
00338      \$         GO TO 70
00339 *
00340             GO TO 130
00341 *
00342 *           If stopping criterion was not satisfied, update info and
00343 *           store eigenvector number in array ifail.
00344 *
00345   120       CONTINUE
00346             INFO = INFO + 1
00347             IFAIL( INFO ) = J
00348 *
00349 *           Accept iterate as jth eigenvector.
00350 *
00351   130       CONTINUE
00352             SCL = ONE / DNRM2( BLKSIZ, WORK( INDRV1+1 ), 1 )
00353             JMAX = IDAMAX( BLKSIZ, WORK( INDRV1+1 ), 1 )
00354             IF( WORK( INDRV1+JMAX ).LT.ZERO )
00355      \$         SCL = -SCL
00356             CALL DSCAL( BLKSIZ, SCL, WORK( INDRV1+1 ), 1 )
00357   140       CONTINUE
00358             DO 150 I = 1, N
00359                Z( I, J ) = CZERO
00360   150       CONTINUE
00361             DO 160 I = 1, BLKSIZ
00362                Z( B1+I-1, J ) = DCMPLX( WORK( INDRV1+I ), ZERO )
00363   160       CONTINUE
00364 *
00365 *           Save the shift to check eigenvalue spacing at next
00366 *           iteration.
00367 *
00368             XJM = XJ
00369 *
00370   170    CONTINUE
00371   180 CONTINUE
00372 *
00373       RETURN
00374 *
00375 *     End of ZSTEIN
00376 *
00377       END
```