LAPACK 3.3.1
Linear Algebra PACKage

zsteqr.f

Go to the documentation of this file.
00001       SUBROUTINE ZSTEQR( COMPZ, N, D, E, Z, LDZ, WORK, INFO )
00002 *
00003 *  -- LAPACK routine (version 3.2) --
00004 *  -- LAPACK is a software package provided by Univ. of Tennessee,    --
00005 *  -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..--
00006 *     November 2006
00007 *
00008 *     .. Scalar Arguments ..
00009       CHARACTER          COMPZ
00010       INTEGER            INFO, LDZ, N
00011 *     ..
00012 *     .. Array Arguments ..
00013       DOUBLE PRECISION   D( * ), E( * ), WORK( * )
00014       COMPLEX*16         Z( LDZ, * )
00015 *     ..
00016 *
00017 *  Purpose
00018 *  =======
00019 *
00020 *  ZSTEQR computes all eigenvalues and, optionally, eigenvectors of a
00021 *  symmetric tridiagonal matrix using the implicit QL or QR method.
00022 *  The eigenvectors of a full or band complex Hermitian matrix can also
00023 *  be found if ZHETRD or ZHPTRD or ZHBTRD has been used to reduce this
00024 *  matrix to tridiagonal form.
00025 *
00026 *  Arguments
00027 *  =========
00028 *
00029 *  COMPZ   (input) CHARACTER*1
00030 *          = 'N':  Compute eigenvalues only.
00031 *          = 'V':  Compute eigenvalues and eigenvectors of the original
00032 *                  Hermitian matrix.  On entry, Z must contain the
00033 *                  unitary matrix used to reduce the original matrix
00034 *                  to tridiagonal form.
00035 *          = 'I':  Compute eigenvalues and eigenvectors of the
00036 *                  tridiagonal matrix.  Z is initialized to the identity
00037 *                  matrix.
00038 *
00039 *  N       (input) INTEGER
00040 *          The order of the matrix.  N >= 0.
00041 *
00042 *  D       (input/output) DOUBLE PRECISION array, dimension (N)
00043 *          On entry, the diagonal elements of the tridiagonal matrix.
00044 *          On exit, if INFO = 0, the eigenvalues in ascending order.
00045 *
00046 *  E       (input/output) DOUBLE PRECISION array, dimension (N-1)
00047 *          On entry, the (n-1) subdiagonal elements of the tridiagonal
00048 *          matrix.
00049 *          On exit, E has been destroyed.
00050 *
00051 *  Z       (input/output) COMPLEX*16 array, dimension (LDZ, N)
00052 *          On entry, if  COMPZ = 'V', then Z contains the unitary
00053 *          matrix used in the reduction to tridiagonal form.
00054 *          On exit, if INFO = 0, then if COMPZ = 'V', Z contains the
00055 *          orthonormal eigenvectors of the original Hermitian matrix,
00056 *          and if COMPZ = 'I', Z contains the orthonormal eigenvectors
00057 *          of the symmetric tridiagonal matrix.
00058 *          If COMPZ = 'N', then Z is not referenced.
00059 *
00060 *  LDZ     (input) INTEGER
00061 *          The leading dimension of the array Z.  LDZ >= 1, and if
00062 *          eigenvectors are desired, then  LDZ >= max(1,N).
00063 *
00064 *  WORK    (workspace) DOUBLE PRECISION array, dimension (max(1,2*N-2))
00065 *          If COMPZ = 'N', then WORK is not referenced.
00066 *
00067 *  INFO    (output) INTEGER
00068 *          = 0:  successful exit
00069 *          < 0:  if INFO = -i, the i-th argument had an illegal value
00070 *          > 0:  the algorithm has failed to find all the eigenvalues in
00071 *                a total of 30*N iterations; if INFO = i, then i
00072 *                elements of E have not converged to zero; on exit, D
00073 *                and E contain the elements of a symmetric tridiagonal
00074 *                matrix which is unitarily similar to the original
00075 *                matrix.
00076 *
00077 *  =====================================================================
00078 *
00079 *     .. Parameters ..
00080       DOUBLE PRECISION   ZERO, ONE, TWO, THREE
00081       PARAMETER          ( ZERO = 0.0D0, ONE = 1.0D0, TWO = 2.0D0,
00082      $                   THREE = 3.0D0 )
00083       COMPLEX*16         CZERO, CONE
00084       PARAMETER          ( CZERO = ( 0.0D0, 0.0D0 ),
00085      $                   CONE = ( 1.0D0, 0.0D0 ) )
00086       INTEGER            MAXIT
00087       PARAMETER          ( MAXIT = 30 )
00088 *     ..
00089 *     .. Local Scalars ..
00090       INTEGER            I, ICOMPZ, II, ISCALE, J, JTOT, K, L, L1, LEND,
00091      $                   LENDM1, LENDP1, LENDSV, LM1, LSV, M, MM, MM1,
00092      $                   NM1, NMAXIT
00093       DOUBLE PRECISION   ANORM, B, C, EPS, EPS2, F, G, P, R, RT1, RT2,
00094      $                   S, SAFMAX, SAFMIN, SSFMAX, SSFMIN, TST
00095 *     ..
00096 *     .. External Functions ..
00097       LOGICAL            LSAME
00098       DOUBLE PRECISION   DLAMCH, DLANST, DLAPY2
00099       EXTERNAL           LSAME, DLAMCH, DLANST, DLAPY2
00100 *     ..
00101 *     .. External Subroutines ..
00102       EXTERNAL           DLAE2, DLAEV2, DLARTG, DLASCL, DLASRT, XERBLA,
00103      $                   ZLASET, ZLASR, ZSWAP
00104 *     ..
00105 *     .. Intrinsic Functions ..
00106       INTRINSIC          ABS, MAX, SIGN, SQRT
00107 *     ..
00108 *     .. Executable Statements ..
00109 *
00110 *     Test the input parameters.
00111 *
00112       INFO = 0
00113 *
00114       IF( LSAME( COMPZ, 'N' ) ) THEN
00115          ICOMPZ = 0
00116       ELSE IF( LSAME( COMPZ, 'V' ) ) THEN
00117          ICOMPZ = 1
00118       ELSE IF( LSAME( COMPZ, 'I' ) ) THEN
00119          ICOMPZ = 2
00120       ELSE
00121          ICOMPZ = -1
00122       END IF
00123       IF( ICOMPZ.LT.0 ) THEN
00124          INFO = -1
00125       ELSE IF( N.LT.0 ) THEN
00126          INFO = -2
00127       ELSE IF( ( LDZ.LT.1 ) .OR. ( ICOMPZ.GT.0 .AND. LDZ.LT.MAX( 1,
00128      $         N ) ) ) THEN
00129          INFO = -6
00130       END IF
00131       IF( INFO.NE.0 ) THEN
00132          CALL XERBLA( 'ZSTEQR', -INFO )
00133          RETURN
00134       END IF
00135 *
00136 *     Quick return if possible
00137 *
00138       IF( N.EQ.0 )
00139      $   RETURN
00140 *
00141       IF( N.EQ.1 ) THEN
00142          IF( ICOMPZ.EQ.2 )
00143      $      Z( 1, 1 ) = CONE
00144          RETURN
00145       END IF
00146 *
00147 *     Determine the unit roundoff and over/underflow thresholds.
00148 *
00149       EPS = DLAMCH( 'E' )
00150       EPS2 = EPS**2
00151       SAFMIN = DLAMCH( 'S' )
00152       SAFMAX = ONE / SAFMIN
00153       SSFMAX = SQRT( SAFMAX ) / THREE
00154       SSFMIN = SQRT( SAFMIN ) / EPS2
00155 *
00156 *     Compute the eigenvalues and eigenvectors of the tridiagonal
00157 *     matrix.
00158 *
00159       IF( ICOMPZ.EQ.2 )
00160      $   CALL ZLASET( 'Full', N, N, CZERO, CONE, Z, LDZ )
00161 *
00162       NMAXIT = N*MAXIT
00163       JTOT = 0
00164 *
00165 *     Determine where the matrix splits and choose QL or QR iteration
00166 *     for each block, according to whether top or bottom diagonal
00167 *     element is smaller.
00168 *
00169       L1 = 1
00170       NM1 = N - 1
00171 *
00172    10 CONTINUE
00173       IF( L1.GT.N )
00174      $   GO TO 160
00175       IF( L1.GT.1 )
00176      $   E( L1-1 ) = ZERO
00177       IF( L1.LE.NM1 ) THEN
00178          DO 20 M = L1, NM1
00179             TST = ABS( E( M ) )
00180             IF( TST.EQ.ZERO )
00181      $         GO TO 30
00182             IF( TST.LE.( SQRT( ABS( D( M ) ) )*SQRT( ABS( D( M+
00183      $          1 ) ) ) )*EPS ) THEN
00184                E( M ) = ZERO
00185                GO TO 30
00186             END IF
00187    20    CONTINUE
00188       END IF
00189       M = N
00190 *
00191    30 CONTINUE
00192       L = L1
00193       LSV = L
00194       LEND = M
00195       LENDSV = LEND
00196       L1 = M + 1
00197       IF( LEND.EQ.L )
00198      $   GO TO 10
00199 *
00200 *     Scale submatrix in rows and columns L to LEND
00201 *
00202       ANORM = DLANST( 'I', LEND-L+1, D( L ), E( L ) )
00203       ISCALE = 0
00204       IF( ANORM.EQ.ZERO )
00205      $   GO TO 10
00206       IF( ANORM.GT.SSFMAX ) THEN
00207          ISCALE = 1
00208          CALL DLASCL( 'G', 0, 0, ANORM, SSFMAX, LEND-L+1, 1, D( L ), N,
00209      $                INFO )
00210          CALL DLASCL( 'G', 0, 0, ANORM, SSFMAX, LEND-L, 1, E( L ), N,
00211      $                INFO )
00212       ELSE IF( ANORM.LT.SSFMIN ) THEN
00213          ISCALE = 2
00214          CALL DLASCL( 'G', 0, 0, ANORM, SSFMIN, LEND-L+1, 1, D( L ), N,
00215      $                INFO )
00216          CALL DLASCL( 'G', 0, 0, ANORM, SSFMIN, LEND-L, 1, E( L ), N,
00217      $                INFO )
00218       END IF
00219 *
00220 *     Choose between QL and QR iteration
00221 *
00222       IF( ABS( D( LEND ) ).LT.ABS( D( L ) ) ) THEN
00223          LEND = LSV
00224          L = LENDSV
00225       END IF
00226 *
00227       IF( LEND.GT.L ) THEN
00228 *
00229 *        QL Iteration
00230 *
00231 *        Look for small subdiagonal element.
00232 *
00233    40    CONTINUE
00234          IF( L.NE.LEND ) THEN
00235             LENDM1 = LEND - 1
00236             DO 50 M = L, LENDM1
00237                TST = ABS( E( M ) )**2
00238                IF( TST.LE.( EPS2*ABS( D( M ) ) )*ABS( D( M+1 ) )+
00239      $             SAFMIN )GO TO 60
00240    50       CONTINUE
00241          END IF
00242 *
00243          M = LEND
00244 *
00245    60    CONTINUE
00246          IF( M.LT.LEND )
00247      $      E( M ) = ZERO
00248          P = D( L )
00249          IF( M.EQ.L )
00250      $      GO TO 80
00251 *
00252 *        If remaining matrix is 2-by-2, use DLAE2 or SLAEV2
00253 *        to compute its eigensystem.
00254 *
00255          IF( M.EQ.L+1 ) THEN
00256             IF( ICOMPZ.GT.0 ) THEN
00257                CALL DLAEV2( D( L ), E( L ), D( L+1 ), RT1, RT2, C, S )
00258                WORK( L ) = C
00259                WORK( N-1+L ) = S
00260                CALL ZLASR( 'R', 'V', 'B', N, 2, WORK( L ),
00261      $                     WORK( N-1+L ), Z( 1, L ), LDZ )
00262             ELSE
00263                CALL DLAE2( D( L ), E( L ), D( L+1 ), RT1, RT2 )
00264             END IF
00265             D( L ) = RT1
00266             D( L+1 ) = RT2
00267             E( L ) = ZERO
00268             L = L + 2
00269             IF( L.LE.LEND )
00270      $         GO TO 40
00271             GO TO 140
00272          END IF
00273 *
00274          IF( JTOT.EQ.NMAXIT )
00275      $      GO TO 140
00276          JTOT = JTOT + 1
00277 *
00278 *        Form shift.
00279 *
00280          G = ( D( L+1 )-P ) / ( TWO*E( L ) )
00281          R = DLAPY2( G, ONE )
00282          G = D( M ) - P + ( E( L ) / ( G+SIGN( R, G ) ) )
00283 *
00284          S = ONE
00285          C = ONE
00286          P = ZERO
00287 *
00288 *        Inner loop
00289 *
00290          MM1 = M - 1
00291          DO 70 I = MM1, L, -1
00292             F = S*E( I )
00293             B = C*E( I )
00294             CALL DLARTG( G, F, C, S, R )
00295             IF( I.NE.M-1 )
00296      $         E( I+1 ) = R
00297             G = D( I+1 ) - P
00298             R = ( D( I )-G )*S + TWO*C*B
00299             P = S*R
00300             D( I+1 ) = G + P
00301             G = C*R - B
00302 *
00303 *           If eigenvectors are desired, then save rotations.
00304 *
00305             IF( ICOMPZ.GT.0 ) THEN
00306                WORK( I ) = C
00307                WORK( N-1+I ) = -S
00308             END IF
00309 *
00310    70    CONTINUE
00311 *
00312 *        If eigenvectors are desired, then apply saved rotations.
00313 *
00314          IF( ICOMPZ.GT.0 ) THEN
00315             MM = M - L + 1
00316             CALL ZLASR( 'R', 'V', 'B', N, MM, WORK( L ), WORK( N-1+L ),
00317      $                  Z( 1, L ), LDZ )
00318          END IF
00319 *
00320          D( L ) = D( L ) - P
00321          E( L ) = G
00322          GO TO 40
00323 *
00324 *        Eigenvalue found.
00325 *
00326    80    CONTINUE
00327          D( L ) = P
00328 *
00329          L = L + 1
00330          IF( L.LE.LEND )
00331      $      GO TO 40
00332          GO TO 140
00333 *
00334       ELSE
00335 *
00336 *        QR Iteration
00337 *
00338 *        Look for small superdiagonal element.
00339 *
00340    90    CONTINUE
00341          IF( L.NE.LEND ) THEN
00342             LENDP1 = LEND + 1
00343             DO 100 M = L, LENDP1, -1
00344                TST = ABS( E( M-1 ) )**2
00345                IF( TST.LE.( EPS2*ABS( D( M ) ) )*ABS( D( M-1 ) )+
00346      $             SAFMIN )GO TO 110
00347   100       CONTINUE
00348          END IF
00349 *
00350          M = LEND
00351 *
00352   110    CONTINUE
00353          IF( M.GT.LEND )
00354      $      E( M-1 ) = ZERO
00355          P = D( L )
00356          IF( M.EQ.L )
00357      $      GO TO 130
00358 *
00359 *        If remaining matrix is 2-by-2, use DLAE2 or SLAEV2
00360 *        to compute its eigensystem.
00361 *
00362          IF( M.EQ.L-1 ) THEN
00363             IF( ICOMPZ.GT.0 ) THEN
00364                CALL DLAEV2( D( L-1 ), E( L-1 ), D( L ), RT1, RT2, C, S )
00365                WORK( M ) = C
00366                WORK( N-1+M ) = S
00367                CALL ZLASR( 'R', 'V', 'F', N, 2, WORK( M ),
00368      $                     WORK( N-1+M ), Z( 1, L-1 ), LDZ )
00369             ELSE
00370                CALL DLAE2( D( L-1 ), E( L-1 ), D( L ), RT1, RT2 )
00371             END IF
00372             D( L-1 ) = RT1
00373             D( L ) = RT2
00374             E( L-1 ) = ZERO
00375             L = L - 2
00376             IF( L.GE.LEND )
00377      $         GO TO 90
00378             GO TO 140
00379          END IF
00380 *
00381          IF( JTOT.EQ.NMAXIT )
00382      $      GO TO 140
00383          JTOT = JTOT + 1
00384 *
00385 *        Form shift.
00386 *
00387          G = ( D( L-1 )-P ) / ( TWO*E( L-1 ) )
00388          R = DLAPY2( G, ONE )
00389          G = D( M ) - P + ( E( L-1 ) / ( G+SIGN( R, G ) ) )
00390 *
00391          S = ONE
00392          C = ONE
00393          P = ZERO
00394 *
00395 *        Inner loop
00396 *
00397          LM1 = L - 1
00398          DO 120 I = M, LM1
00399             F = S*E( I )
00400             B = C*E( I )
00401             CALL DLARTG( G, F, C, S, R )
00402             IF( I.NE.M )
00403      $         E( I-1 ) = R
00404             G = D( I ) - P
00405             R = ( D( I+1 )-G )*S + TWO*C*B
00406             P = S*R
00407             D( I ) = G + P
00408             G = C*R - B
00409 *
00410 *           If eigenvectors are desired, then save rotations.
00411 *
00412             IF( ICOMPZ.GT.0 ) THEN
00413                WORK( I ) = C
00414                WORK( N-1+I ) = S
00415             END IF
00416 *
00417   120    CONTINUE
00418 *
00419 *        If eigenvectors are desired, then apply saved rotations.
00420 *
00421          IF( ICOMPZ.GT.0 ) THEN
00422             MM = L - M + 1
00423             CALL ZLASR( 'R', 'V', 'F', N, MM, WORK( M ), WORK( N-1+M ),
00424      $                  Z( 1, M ), LDZ )
00425          END IF
00426 *
00427          D( L ) = D( L ) - P
00428          E( LM1 ) = G
00429          GO TO 90
00430 *
00431 *        Eigenvalue found.
00432 *
00433   130    CONTINUE
00434          D( L ) = P
00435 *
00436          L = L - 1
00437          IF( L.GE.LEND )
00438      $      GO TO 90
00439          GO TO 140
00440 *
00441       END IF
00442 *
00443 *     Undo scaling if necessary
00444 *
00445   140 CONTINUE
00446       IF( ISCALE.EQ.1 ) THEN
00447          CALL DLASCL( 'G', 0, 0, SSFMAX, ANORM, LENDSV-LSV+1, 1,
00448      $                D( LSV ), N, INFO )
00449          CALL DLASCL( 'G', 0, 0, SSFMAX, ANORM, LENDSV-LSV, 1, E( LSV ),
00450      $                N, INFO )
00451       ELSE IF( ISCALE.EQ.2 ) THEN
00452          CALL DLASCL( 'G', 0, 0, SSFMIN, ANORM, LENDSV-LSV+1, 1,
00453      $                D( LSV ), N, INFO )
00454          CALL DLASCL( 'G', 0, 0, SSFMIN, ANORM, LENDSV-LSV, 1, E( LSV ),
00455      $                N, INFO )
00456       END IF
00457 *
00458 *     Check for no convergence to an eigenvalue after a total
00459 *     of N*MAXIT iterations.
00460 *
00461       IF( JTOT.EQ.NMAXIT ) THEN
00462          DO 150 I = 1, N - 1
00463             IF( E( I ).NE.ZERO )
00464      $         INFO = INFO + 1
00465   150    CONTINUE
00466          RETURN
00467       END IF
00468       GO TO 10
00469 *
00470 *     Order eigenvalues and eigenvectors.
00471 *
00472   160 CONTINUE
00473       IF( ICOMPZ.EQ.0 ) THEN
00474 *
00475 *        Use Quick Sort
00476 *
00477          CALL DLASRT( 'I', N, D, INFO )
00478 *
00479       ELSE
00480 *
00481 *        Use Selection Sort to minimize swaps of eigenvectors
00482 *
00483          DO 180 II = 2, N
00484             I = II - 1
00485             K = I
00486             P = D( I )
00487             DO 170 J = II, N
00488                IF( D( J ).LT.P ) THEN
00489                   K = J
00490                   P = D( J )
00491                END IF
00492   170       CONTINUE
00493             IF( K.NE.I ) THEN
00494                D( K ) = D( I )
00495                D( I ) = P
00496                CALL ZSWAP( N, Z( 1, I ), 1, Z( 1, K ), 1 )
00497             END IF
00498   180    CONTINUE
00499       END IF
00500       RETURN
00501 *
00502 *     End of ZSTEQR
00503 *
00504       END
 All Files Functions