LAPACK 3.3.1
Linear Algebra PACKage
|
00001 SUBROUTINE DTREVC( SIDE, HOWMNY, SELECT, N, T, LDT, VL, LDVL, VR, 00002 $ LDVR, MM, M, WORK, INFO ) 00003 * 00004 * -- LAPACK routine (version 3.3.1) -- 00005 * -- LAPACK is a software package provided by Univ. of Tennessee, -- 00006 * -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..-- 00007 * -- April 2011 -- 00008 * 00009 * .. Scalar Arguments .. 00010 CHARACTER HOWMNY, SIDE 00011 INTEGER INFO, LDT, LDVL, LDVR, M, MM, N 00012 * .. 00013 * .. Array Arguments .. 00014 LOGICAL SELECT( * ) 00015 DOUBLE PRECISION T( LDT, * ), VL( LDVL, * ), VR( LDVR, * ), 00016 $ WORK( * ) 00017 * .. 00018 * 00019 * Purpose 00020 * ======= 00021 * 00022 * DTREVC computes some or all of the right and/or left eigenvectors of 00023 * a real upper quasi-triangular matrix T. 00024 * Matrices of this type are produced by the Schur factorization of 00025 * a real general matrix: A = Q*T*Q**T, as computed by DHSEQR. 00026 * 00027 * The right eigenvector x and the left eigenvector y of T corresponding 00028 * to an eigenvalue w are defined by: 00029 * 00030 * T*x = w*x, (y**T)*T = w*(y**T) 00031 * 00032 * where y**T denotes the transpose of y. 00033 * The eigenvalues are not input to this routine, but are read directly 00034 * from the diagonal blocks of T. 00035 * 00036 * This routine returns the matrices X and/or Y of right and left 00037 * eigenvectors of T, or the products Q*X and/or Q*Y, where Q is an 00038 * input matrix. If Q is the orthogonal factor that reduces a matrix 00039 * A to Schur form T, then Q*X and Q*Y are the matrices of right and 00040 * left eigenvectors of A. 00041 * 00042 * Arguments 00043 * ========= 00044 * 00045 * SIDE (input) CHARACTER*1 00046 * = 'R': compute right eigenvectors only; 00047 * = 'L': compute left eigenvectors only; 00048 * = 'B': compute both right and left eigenvectors. 00049 * 00050 * HOWMNY (input) CHARACTER*1 00051 * = 'A': compute all right and/or left eigenvectors; 00052 * = 'B': compute all right and/or left eigenvectors, 00053 * backtransformed by the matrices in VR and/or VL; 00054 * = 'S': compute selected right and/or left eigenvectors, 00055 * as indicated by the logical array SELECT. 00056 * 00057 * SELECT (input/output) LOGICAL array, dimension (N) 00058 * If HOWMNY = 'S', SELECT specifies the eigenvectors to be 00059 * computed. 00060 * If w(j) is a real eigenvalue, the corresponding real 00061 * eigenvector is computed if SELECT(j) is .TRUE.. 00062 * If w(j) and w(j+1) are the real and imaginary parts of a 00063 * complex eigenvalue, the corresponding complex eigenvector is 00064 * computed if either SELECT(j) or SELECT(j+1) is .TRUE., and 00065 * on exit SELECT(j) is set to .TRUE. and SELECT(j+1) is set to 00066 * .FALSE.. 00067 * Not referenced if HOWMNY = 'A' or 'B'. 00068 * 00069 * N (input) INTEGER 00070 * The order of the matrix T. N >= 0. 00071 * 00072 * T (input) DOUBLE PRECISION array, dimension (LDT,N) 00073 * The upper quasi-triangular matrix T in Schur canonical form. 00074 * 00075 * LDT (input) INTEGER 00076 * The leading dimension of the array T. LDT >= max(1,N). 00077 * 00078 * VL (input/output) DOUBLE PRECISION array, dimension (LDVL,MM) 00079 * On entry, if SIDE = 'L' or 'B' and HOWMNY = 'B', VL must 00080 * contain an N-by-N matrix Q (usually the orthogonal matrix Q 00081 * of Schur vectors returned by DHSEQR). 00082 * On exit, if SIDE = 'L' or 'B', VL contains: 00083 * if HOWMNY = 'A', the matrix Y of left eigenvectors of T; 00084 * if HOWMNY = 'B', the matrix Q*Y; 00085 * if HOWMNY = 'S', the left eigenvectors of T specified by 00086 * SELECT, stored consecutively in the columns 00087 * of VL, in the same order as their 00088 * eigenvalues. 00089 * A complex eigenvector corresponding to a complex eigenvalue 00090 * is stored in two consecutive columns, the first holding the 00091 * real part, and the second the imaginary part. 00092 * Not referenced if SIDE = 'R'. 00093 * 00094 * LDVL (input) INTEGER 00095 * The leading dimension of the array VL. LDVL >= 1, and if 00096 * SIDE = 'L' or 'B', LDVL >= N. 00097 * 00098 * VR (input/output) DOUBLE PRECISION array, dimension (LDVR,MM) 00099 * On entry, if SIDE = 'R' or 'B' and HOWMNY = 'B', VR must 00100 * contain an N-by-N matrix Q (usually the orthogonal matrix Q 00101 * of Schur vectors returned by DHSEQR). 00102 * On exit, if SIDE = 'R' or 'B', VR contains: 00103 * if HOWMNY = 'A', the matrix X of right eigenvectors of T; 00104 * if HOWMNY = 'B', the matrix Q*X; 00105 * if HOWMNY = 'S', the right eigenvectors of T specified by 00106 * SELECT, stored consecutively in the columns 00107 * of VR, in the same order as their 00108 * eigenvalues. 00109 * A complex eigenvector corresponding to a complex eigenvalue 00110 * is stored in two consecutive columns, the first holding the 00111 * real part and the second the imaginary part. 00112 * Not referenced if SIDE = 'L'. 00113 * 00114 * LDVR (input) INTEGER 00115 * The leading dimension of the array VR. LDVR >= 1, and if 00116 * SIDE = 'R' or 'B', LDVR >= N. 00117 * 00118 * MM (input) INTEGER 00119 * The number of columns in the arrays VL and/or VR. MM >= M. 00120 * 00121 * M (output) INTEGER 00122 * The number of columns in the arrays VL and/or VR actually 00123 * used to store the eigenvectors. 00124 * If HOWMNY = 'A' or 'B', M is set to N. 00125 * Each selected real eigenvector occupies one column and each 00126 * selected complex eigenvector occupies two columns. 00127 * 00128 * WORK (workspace) DOUBLE PRECISION array, dimension (3*N) 00129 * 00130 * INFO (output) INTEGER 00131 * = 0: successful exit 00132 * < 0: if INFO = -i, the i-th argument had an illegal value 00133 * 00134 * Further Details 00135 * =============== 00136 * 00137 * The algorithm used in this program is basically backward (forward) 00138 * substitution, with scaling to make the the code robust against 00139 * possible overflow. 00140 * 00141 * Each eigenvector is normalized so that the element of largest 00142 * magnitude has magnitude 1; here the magnitude of a complex number 00143 * (x,y) is taken to be |x| + |y|. 00144 * 00145 * ===================================================================== 00146 * 00147 * .. Parameters .. 00148 DOUBLE PRECISION ZERO, ONE 00149 PARAMETER ( ZERO = 0.0D+0, ONE = 1.0D+0 ) 00150 * .. 00151 * .. Local Scalars .. 00152 LOGICAL ALLV, BOTHV, LEFTV, OVER, PAIR, RIGHTV, SOMEV 00153 INTEGER I, IERR, II, IP, IS, J, J1, J2, JNXT, K, KI, N2 00154 DOUBLE PRECISION BETA, BIGNUM, EMAX, OVFL, REC, REMAX, SCALE, 00155 $ SMIN, SMLNUM, ULP, UNFL, VCRIT, VMAX, WI, WR, 00156 $ XNORM 00157 * .. 00158 * .. External Functions .. 00159 LOGICAL LSAME 00160 INTEGER IDAMAX 00161 DOUBLE PRECISION DDOT, DLAMCH 00162 EXTERNAL LSAME, IDAMAX, DDOT, DLAMCH 00163 * .. 00164 * .. External Subroutines .. 00165 EXTERNAL DAXPY, DCOPY, DGEMV, DLALN2, DSCAL, XERBLA 00166 * .. 00167 * .. Intrinsic Functions .. 00168 INTRINSIC ABS, MAX, SQRT 00169 * .. 00170 * .. Local Arrays .. 00171 DOUBLE PRECISION X( 2, 2 ) 00172 * .. 00173 * .. Executable Statements .. 00174 * 00175 * Decode and test the input parameters 00176 * 00177 BOTHV = LSAME( SIDE, 'B' ) 00178 RIGHTV = LSAME( SIDE, 'R' ) .OR. BOTHV 00179 LEFTV = LSAME( SIDE, 'L' ) .OR. BOTHV 00180 * 00181 ALLV = LSAME( HOWMNY, 'A' ) 00182 OVER = LSAME( HOWMNY, 'B' ) 00183 SOMEV = LSAME( HOWMNY, 'S' ) 00184 * 00185 INFO = 0 00186 IF( .NOT.RIGHTV .AND. .NOT.LEFTV ) THEN 00187 INFO = -1 00188 ELSE IF( .NOT.ALLV .AND. .NOT.OVER .AND. .NOT.SOMEV ) THEN 00189 INFO = -2 00190 ELSE IF( N.LT.0 ) THEN 00191 INFO = -4 00192 ELSE IF( LDT.LT.MAX( 1, N ) ) THEN 00193 INFO = -6 00194 ELSE IF( LDVL.LT.1 .OR. ( LEFTV .AND. LDVL.LT.N ) ) THEN 00195 INFO = -8 00196 ELSE IF( LDVR.LT.1 .OR. ( RIGHTV .AND. LDVR.LT.N ) ) THEN 00197 INFO = -10 00198 ELSE 00199 * 00200 * Set M to the number of columns required to store the selected 00201 * eigenvectors, standardize the array SELECT if necessary, and 00202 * test MM. 00203 * 00204 IF( SOMEV ) THEN 00205 M = 0 00206 PAIR = .FALSE. 00207 DO 10 J = 1, N 00208 IF( PAIR ) THEN 00209 PAIR = .FALSE. 00210 SELECT( J ) = .FALSE. 00211 ELSE 00212 IF( J.LT.N ) THEN 00213 IF( T( J+1, J ).EQ.ZERO ) THEN 00214 IF( SELECT( J ) ) 00215 $ M = M + 1 00216 ELSE 00217 PAIR = .TRUE. 00218 IF( SELECT( J ) .OR. SELECT( J+1 ) ) THEN 00219 SELECT( J ) = .TRUE. 00220 M = M + 2 00221 END IF 00222 END IF 00223 ELSE 00224 IF( SELECT( N ) ) 00225 $ M = M + 1 00226 END IF 00227 END IF 00228 10 CONTINUE 00229 ELSE 00230 M = N 00231 END IF 00232 * 00233 IF( MM.LT.M ) THEN 00234 INFO = -11 00235 END IF 00236 END IF 00237 IF( INFO.NE.0 ) THEN 00238 CALL XERBLA( 'DTREVC', -INFO ) 00239 RETURN 00240 END IF 00241 * 00242 * Quick return if possible. 00243 * 00244 IF( N.EQ.0 ) 00245 $ RETURN 00246 * 00247 * Set the constants to control overflow. 00248 * 00249 UNFL = DLAMCH( 'Safe minimum' ) 00250 OVFL = ONE / UNFL 00251 CALL DLABAD( UNFL, OVFL ) 00252 ULP = DLAMCH( 'Precision' ) 00253 SMLNUM = UNFL*( N / ULP ) 00254 BIGNUM = ( ONE-ULP ) / SMLNUM 00255 * 00256 * Compute 1-norm of each column of strictly upper triangular 00257 * part of T to control overflow in triangular solver. 00258 * 00259 WORK( 1 ) = ZERO 00260 DO 30 J = 2, N 00261 WORK( J ) = ZERO 00262 DO 20 I = 1, J - 1 00263 WORK( J ) = WORK( J ) + ABS( T( I, J ) ) 00264 20 CONTINUE 00265 30 CONTINUE 00266 * 00267 * Index IP is used to specify the real or complex eigenvalue: 00268 * IP = 0, real eigenvalue, 00269 * 1, first of conjugate complex pair: (wr,wi) 00270 * -1, second of conjugate complex pair: (wr,wi) 00271 * 00272 N2 = 2*N 00273 * 00274 IF( RIGHTV ) THEN 00275 * 00276 * Compute right eigenvectors. 00277 * 00278 IP = 0 00279 IS = M 00280 DO 140 KI = N, 1, -1 00281 * 00282 IF( IP.EQ.1 ) 00283 $ GO TO 130 00284 IF( KI.EQ.1 ) 00285 $ GO TO 40 00286 IF( T( KI, KI-1 ).EQ.ZERO ) 00287 $ GO TO 40 00288 IP = -1 00289 * 00290 40 CONTINUE 00291 IF( SOMEV ) THEN 00292 IF( IP.EQ.0 ) THEN 00293 IF( .NOT.SELECT( KI ) ) 00294 $ GO TO 130 00295 ELSE 00296 IF( .NOT.SELECT( KI-1 ) ) 00297 $ GO TO 130 00298 END IF 00299 END IF 00300 * 00301 * Compute the KI-th eigenvalue (WR,WI). 00302 * 00303 WR = T( KI, KI ) 00304 WI = ZERO 00305 IF( IP.NE.0 ) 00306 $ WI = SQRT( ABS( T( KI, KI-1 ) ) )* 00307 $ SQRT( ABS( T( KI-1, KI ) ) ) 00308 SMIN = MAX( ULP*( ABS( WR )+ABS( WI ) ), SMLNUM ) 00309 * 00310 IF( IP.EQ.0 ) THEN 00311 * 00312 * Real right eigenvector 00313 * 00314 WORK( KI+N ) = ONE 00315 * 00316 * Form right-hand side 00317 * 00318 DO 50 K = 1, KI - 1 00319 WORK( K+N ) = -T( K, KI ) 00320 50 CONTINUE 00321 * 00322 * Solve the upper quasi-triangular system: 00323 * (T(1:KI-1,1:KI-1) - WR)*X = SCALE*WORK. 00324 * 00325 JNXT = KI - 1 00326 DO 60 J = KI - 1, 1, -1 00327 IF( J.GT.JNXT ) 00328 $ GO TO 60 00329 J1 = J 00330 J2 = J 00331 JNXT = J - 1 00332 IF( J.GT.1 ) THEN 00333 IF( T( J, J-1 ).NE.ZERO ) THEN 00334 J1 = J - 1 00335 JNXT = J - 2 00336 END IF 00337 END IF 00338 * 00339 IF( J1.EQ.J2 ) THEN 00340 * 00341 * 1-by-1 diagonal block 00342 * 00343 CALL DLALN2( .FALSE., 1, 1, SMIN, ONE, T( J, J ), 00344 $ LDT, ONE, ONE, WORK( J+N ), N, WR, 00345 $ ZERO, X, 2, SCALE, XNORM, IERR ) 00346 * 00347 * Scale X(1,1) to avoid overflow when updating 00348 * the right-hand side. 00349 * 00350 IF( XNORM.GT.ONE ) THEN 00351 IF( WORK( J ).GT.BIGNUM / XNORM ) THEN 00352 X( 1, 1 ) = X( 1, 1 ) / XNORM 00353 SCALE = SCALE / XNORM 00354 END IF 00355 END IF 00356 * 00357 * Scale if necessary 00358 * 00359 IF( SCALE.NE.ONE ) 00360 $ CALL DSCAL( KI, SCALE, WORK( 1+N ), 1 ) 00361 WORK( J+N ) = X( 1, 1 ) 00362 * 00363 * Update right-hand side 00364 * 00365 CALL DAXPY( J-1, -X( 1, 1 ), T( 1, J ), 1, 00366 $ WORK( 1+N ), 1 ) 00367 * 00368 ELSE 00369 * 00370 * 2-by-2 diagonal block 00371 * 00372 CALL DLALN2( .FALSE., 2, 1, SMIN, ONE, 00373 $ T( J-1, J-1 ), LDT, ONE, ONE, 00374 $ WORK( J-1+N ), N, WR, ZERO, X, 2, 00375 $ SCALE, XNORM, IERR ) 00376 * 00377 * Scale X(1,1) and X(2,1) to avoid overflow when 00378 * updating the right-hand side. 00379 * 00380 IF( XNORM.GT.ONE ) THEN 00381 BETA = MAX( WORK( J-1 ), WORK( J ) ) 00382 IF( BETA.GT.BIGNUM / XNORM ) THEN 00383 X( 1, 1 ) = X( 1, 1 ) / XNORM 00384 X( 2, 1 ) = X( 2, 1 ) / XNORM 00385 SCALE = SCALE / XNORM 00386 END IF 00387 END IF 00388 * 00389 * Scale if necessary 00390 * 00391 IF( SCALE.NE.ONE ) 00392 $ CALL DSCAL( KI, SCALE, WORK( 1+N ), 1 ) 00393 WORK( J-1+N ) = X( 1, 1 ) 00394 WORK( J+N ) = X( 2, 1 ) 00395 * 00396 * Update right-hand side 00397 * 00398 CALL DAXPY( J-2, -X( 1, 1 ), T( 1, J-1 ), 1, 00399 $ WORK( 1+N ), 1 ) 00400 CALL DAXPY( J-2, -X( 2, 1 ), T( 1, J ), 1, 00401 $ WORK( 1+N ), 1 ) 00402 END IF 00403 60 CONTINUE 00404 * 00405 * Copy the vector x or Q*x to VR and normalize. 00406 * 00407 IF( .NOT.OVER ) THEN 00408 CALL DCOPY( KI, WORK( 1+N ), 1, VR( 1, IS ), 1 ) 00409 * 00410 II = IDAMAX( KI, VR( 1, IS ), 1 ) 00411 REMAX = ONE / ABS( VR( II, IS ) ) 00412 CALL DSCAL( KI, REMAX, VR( 1, IS ), 1 ) 00413 * 00414 DO 70 K = KI + 1, N 00415 VR( K, IS ) = ZERO 00416 70 CONTINUE 00417 ELSE 00418 IF( KI.GT.1 ) 00419 $ CALL DGEMV( 'N', N, KI-1, ONE, VR, LDVR, 00420 $ WORK( 1+N ), 1, WORK( KI+N ), 00421 $ VR( 1, KI ), 1 ) 00422 * 00423 II = IDAMAX( N, VR( 1, KI ), 1 ) 00424 REMAX = ONE / ABS( VR( II, KI ) ) 00425 CALL DSCAL( N, REMAX, VR( 1, KI ), 1 ) 00426 END IF 00427 * 00428 ELSE 00429 * 00430 * Complex right eigenvector. 00431 * 00432 * Initial solve 00433 * [ (T(KI-1,KI-1) T(KI-1,KI) ) - (WR + I* WI)]*X = 0. 00434 * [ (T(KI,KI-1) T(KI,KI) ) ] 00435 * 00436 IF( ABS( T( KI-1, KI ) ).GE.ABS( T( KI, KI-1 ) ) ) THEN 00437 WORK( KI-1+N ) = ONE 00438 WORK( KI+N2 ) = WI / T( KI-1, KI ) 00439 ELSE 00440 WORK( KI-1+N ) = -WI / T( KI, KI-1 ) 00441 WORK( KI+N2 ) = ONE 00442 END IF 00443 WORK( KI+N ) = ZERO 00444 WORK( KI-1+N2 ) = ZERO 00445 * 00446 * Form right-hand side 00447 * 00448 DO 80 K = 1, KI - 2 00449 WORK( K+N ) = -WORK( KI-1+N )*T( K, KI-1 ) 00450 WORK( K+N2 ) = -WORK( KI+N2 )*T( K, KI ) 00451 80 CONTINUE 00452 * 00453 * Solve upper quasi-triangular system: 00454 * (T(1:KI-2,1:KI-2) - (WR+i*WI))*X = SCALE*(WORK+i*WORK2) 00455 * 00456 JNXT = KI - 2 00457 DO 90 J = KI - 2, 1, -1 00458 IF( J.GT.JNXT ) 00459 $ GO TO 90 00460 J1 = J 00461 J2 = J 00462 JNXT = J - 1 00463 IF( J.GT.1 ) THEN 00464 IF( T( J, J-1 ).NE.ZERO ) THEN 00465 J1 = J - 1 00466 JNXT = J - 2 00467 END IF 00468 END IF 00469 * 00470 IF( J1.EQ.J2 ) THEN 00471 * 00472 * 1-by-1 diagonal block 00473 * 00474 CALL DLALN2( .FALSE., 1, 2, SMIN, ONE, T( J, J ), 00475 $ LDT, ONE, ONE, WORK( J+N ), N, WR, WI, 00476 $ X, 2, SCALE, XNORM, IERR ) 00477 * 00478 * Scale X(1,1) and X(1,2) to avoid overflow when 00479 * updating the right-hand side. 00480 * 00481 IF( XNORM.GT.ONE ) THEN 00482 IF( WORK( J ).GT.BIGNUM / XNORM ) THEN 00483 X( 1, 1 ) = X( 1, 1 ) / XNORM 00484 X( 1, 2 ) = X( 1, 2 ) / XNORM 00485 SCALE = SCALE / XNORM 00486 END IF 00487 END IF 00488 * 00489 * Scale if necessary 00490 * 00491 IF( SCALE.NE.ONE ) THEN 00492 CALL DSCAL( KI, SCALE, WORK( 1+N ), 1 ) 00493 CALL DSCAL( KI, SCALE, WORK( 1+N2 ), 1 ) 00494 END IF 00495 WORK( J+N ) = X( 1, 1 ) 00496 WORK( J+N2 ) = X( 1, 2 ) 00497 * 00498 * Update the right-hand side 00499 * 00500 CALL DAXPY( J-1, -X( 1, 1 ), T( 1, J ), 1, 00501 $ WORK( 1+N ), 1 ) 00502 CALL DAXPY( J-1, -X( 1, 2 ), T( 1, J ), 1, 00503 $ WORK( 1+N2 ), 1 ) 00504 * 00505 ELSE 00506 * 00507 * 2-by-2 diagonal block 00508 * 00509 CALL DLALN2( .FALSE., 2, 2, SMIN, ONE, 00510 $ T( J-1, J-1 ), LDT, ONE, ONE, 00511 $ WORK( J-1+N ), N, WR, WI, X, 2, SCALE, 00512 $ XNORM, IERR ) 00513 * 00514 * Scale X to avoid overflow when updating 00515 * the right-hand side. 00516 * 00517 IF( XNORM.GT.ONE ) THEN 00518 BETA = MAX( WORK( J-1 ), WORK( J ) ) 00519 IF( BETA.GT.BIGNUM / XNORM ) THEN 00520 REC = ONE / XNORM 00521 X( 1, 1 ) = X( 1, 1 )*REC 00522 X( 1, 2 ) = X( 1, 2 )*REC 00523 X( 2, 1 ) = X( 2, 1 )*REC 00524 X( 2, 2 ) = X( 2, 2 )*REC 00525 SCALE = SCALE*REC 00526 END IF 00527 END IF 00528 * 00529 * Scale if necessary 00530 * 00531 IF( SCALE.NE.ONE ) THEN 00532 CALL DSCAL( KI, SCALE, WORK( 1+N ), 1 ) 00533 CALL DSCAL( KI, SCALE, WORK( 1+N2 ), 1 ) 00534 END IF 00535 WORK( J-1+N ) = X( 1, 1 ) 00536 WORK( J+N ) = X( 2, 1 ) 00537 WORK( J-1+N2 ) = X( 1, 2 ) 00538 WORK( J+N2 ) = X( 2, 2 ) 00539 * 00540 * Update the right-hand side 00541 * 00542 CALL DAXPY( J-2, -X( 1, 1 ), T( 1, J-1 ), 1, 00543 $ WORK( 1+N ), 1 ) 00544 CALL DAXPY( J-2, -X( 2, 1 ), T( 1, J ), 1, 00545 $ WORK( 1+N ), 1 ) 00546 CALL DAXPY( J-2, -X( 1, 2 ), T( 1, J-1 ), 1, 00547 $ WORK( 1+N2 ), 1 ) 00548 CALL DAXPY( J-2, -X( 2, 2 ), T( 1, J ), 1, 00549 $ WORK( 1+N2 ), 1 ) 00550 END IF 00551 90 CONTINUE 00552 * 00553 * Copy the vector x or Q*x to VR and normalize. 00554 * 00555 IF( .NOT.OVER ) THEN 00556 CALL DCOPY( KI, WORK( 1+N ), 1, VR( 1, IS-1 ), 1 ) 00557 CALL DCOPY( KI, WORK( 1+N2 ), 1, VR( 1, IS ), 1 ) 00558 * 00559 EMAX = ZERO 00560 DO 100 K = 1, KI 00561 EMAX = MAX( EMAX, ABS( VR( K, IS-1 ) )+ 00562 $ ABS( VR( K, IS ) ) ) 00563 100 CONTINUE 00564 * 00565 REMAX = ONE / EMAX 00566 CALL DSCAL( KI, REMAX, VR( 1, IS-1 ), 1 ) 00567 CALL DSCAL( KI, REMAX, VR( 1, IS ), 1 ) 00568 * 00569 DO 110 K = KI + 1, N 00570 VR( K, IS-1 ) = ZERO 00571 VR( K, IS ) = ZERO 00572 110 CONTINUE 00573 * 00574 ELSE 00575 * 00576 IF( KI.GT.2 ) THEN 00577 CALL DGEMV( 'N', N, KI-2, ONE, VR, LDVR, 00578 $ WORK( 1+N ), 1, WORK( KI-1+N ), 00579 $ VR( 1, KI-1 ), 1 ) 00580 CALL DGEMV( 'N', N, KI-2, ONE, VR, LDVR, 00581 $ WORK( 1+N2 ), 1, WORK( KI+N2 ), 00582 $ VR( 1, KI ), 1 ) 00583 ELSE 00584 CALL DSCAL( N, WORK( KI-1+N ), VR( 1, KI-1 ), 1 ) 00585 CALL DSCAL( N, WORK( KI+N2 ), VR( 1, KI ), 1 ) 00586 END IF 00587 * 00588 EMAX = ZERO 00589 DO 120 K = 1, N 00590 EMAX = MAX( EMAX, ABS( VR( K, KI-1 ) )+ 00591 $ ABS( VR( K, KI ) ) ) 00592 120 CONTINUE 00593 REMAX = ONE / EMAX 00594 CALL DSCAL( N, REMAX, VR( 1, KI-1 ), 1 ) 00595 CALL DSCAL( N, REMAX, VR( 1, KI ), 1 ) 00596 END IF 00597 END IF 00598 * 00599 IS = IS - 1 00600 IF( IP.NE.0 ) 00601 $ IS = IS - 1 00602 130 CONTINUE 00603 IF( IP.EQ.1 ) 00604 $ IP = 0 00605 IF( IP.EQ.-1 ) 00606 $ IP = 1 00607 140 CONTINUE 00608 END IF 00609 * 00610 IF( LEFTV ) THEN 00611 * 00612 * Compute left eigenvectors. 00613 * 00614 IP = 0 00615 IS = 1 00616 DO 260 KI = 1, N 00617 * 00618 IF( IP.EQ.-1 ) 00619 $ GO TO 250 00620 IF( KI.EQ.N ) 00621 $ GO TO 150 00622 IF( T( KI+1, KI ).EQ.ZERO ) 00623 $ GO TO 150 00624 IP = 1 00625 * 00626 150 CONTINUE 00627 IF( SOMEV ) THEN 00628 IF( .NOT.SELECT( KI ) ) 00629 $ GO TO 250 00630 END IF 00631 * 00632 * Compute the KI-th eigenvalue (WR,WI). 00633 * 00634 WR = T( KI, KI ) 00635 WI = ZERO 00636 IF( IP.NE.0 ) 00637 $ WI = SQRT( ABS( T( KI, KI+1 ) ) )* 00638 $ SQRT( ABS( T( KI+1, KI ) ) ) 00639 SMIN = MAX( ULP*( ABS( WR )+ABS( WI ) ), SMLNUM ) 00640 * 00641 IF( IP.EQ.0 ) THEN 00642 * 00643 * Real left eigenvector. 00644 * 00645 WORK( KI+N ) = ONE 00646 * 00647 * Form right-hand side 00648 * 00649 DO 160 K = KI + 1, N 00650 WORK( K+N ) = -T( KI, K ) 00651 160 CONTINUE 00652 * 00653 * Solve the quasi-triangular system: 00654 * (T(KI+1:N,KI+1:N) - WR)**T*X = SCALE*WORK 00655 * 00656 VMAX = ONE 00657 VCRIT = BIGNUM 00658 * 00659 JNXT = KI + 1 00660 DO 170 J = KI + 1, N 00661 IF( J.LT.JNXT ) 00662 $ GO TO 170 00663 J1 = J 00664 J2 = J 00665 JNXT = J + 1 00666 IF( J.LT.N ) THEN 00667 IF( T( J+1, J ).NE.ZERO ) THEN 00668 J2 = J + 1 00669 JNXT = J + 2 00670 END IF 00671 END IF 00672 * 00673 IF( J1.EQ.J2 ) THEN 00674 * 00675 * 1-by-1 diagonal block 00676 * 00677 * Scale if necessary to avoid overflow when forming 00678 * the right-hand side. 00679 * 00680 IF( WORK( J ).GT.VCRIT ) THEN 00681 REC = ONE / VMAX 00682 CALL DSCAL( N-KI+1, REC, WORK( KI+N ), 1 ) 00683 VMAX = ONE 00684 VCRIT = BIGNUM 00685 END IF 00686 * 00687 WORK( J+N ) = WORK( J+N ) - 00688 $ DDOT( J-KI-1, T( KI+1, J ), 1, 00689 $ WORK( KI+1+N ), 1 ) 00690 * 00691 * Solve (T(J,J)-WR)**T*X = WORK 00692 * 00693 CALL DLALN2( .FALSE., 1, 1, SMIN, ONE, T( J, J ), 00694 $ LDT, ONE, ONE, WORK( J+N ), N, WR, 00695 $ ZERO, X, 2, SCALE, XNORM, IERR ) 00696 * 00697 * Scale if necessary 00698 * 00699 IF( SCALE.NE.ONE ) 00700 $ CALL DSCAL( N-KI+1, SCALE, WORK( KI+N ), 1 ) 00701 WORK( J+N ) = X( 1, 1 ) 00702 VMAX = MAX( ABS( WORK( J+N ) ), VMAX ) 00703 VCRIT = BIGNUM / VMAX 00704 * 00705 ELSE 00706 * 00707 * 2-by-2 diagonal block 00708 * 00709 * Scale if necessary to avoid overflow when forming 00710 * the right-hand side. 00711 * 00712 BETA = MAX( WORK( J ), WORK( J+1 ) ) 00713 IF( BETA.GT.VCRIT ) THEN 00714 REC = ONE / VMAX 00715 CALL DSCAL( N-KI+1, REC, WORK( KI+N ), 1 ) 00716 VMAX = ONE 00717 VCRIT = BIGNUM 00718 END IF 00719 * 00720 WORK( J+N ) = WORK( J+N ) - 00721 $ DDOT( J-KI-1, T( KI+1, J ), 1, 00722 $ WORK( KI+1+N ), 1 ) 00723 * 00724 WORK( J+1+N ) = WORK( J+1+N ) - 00725 $ DDOT( J-KI-1, T( KI+1, J+1 ), 1, 00726 $ WORK( KI+1+N ), 1 ) 00727 * 00728 * Solve 00729 * [T(J,J)-WR T(J,J+1) ]**T * X = SCALE*( WORK1 ) 00730 * [T(J+1,J) T(J+1,J+1)-WR] ( WORK2 ) 00731 * 00732 CALL DLALN2( .TRUE., 2, 1, SMIN, ONE, T( J, J ), 00733 $ LDT, ONE, ONE, WORK( J+N ), N, WR, 00734 $ ZERO, X, 2, SCALE, XNORM, IERR ) 00735 * 00736 * Scale if necessary 00737 * 00738 IF( SCALE.NE.ONE ) 00739 $ CALL DSCAL( N-KI+1, SCALE, WORK( KI+N ), 1 ) 00740 WORK( J+N ) = X( 1, 1 ) 00741 WORK( J+1+N ) = X( 2, 1 ) 00742 * 00743 VMAX = MAX( ABS( WORK( J+N ) ), 00744 $ ABS( WORK( J+1+N ) ), VMAX ) 00745 VCRIT = BIGNUM / VMAX 00746 * 00747 END IF 00748 170 CONTINUE 00749 * 00750 * Copy the vector x or Q*x to VL and normalize. 00751 * 00752 IF( .NOT.OVER ) THEN 00753 CALL DCOPY( N-KI+1, WORK( KI+N ), 1, VL( KI, IS ), 1 ) 00754 * 00755 II = IDAMAX( N-KI+1, VL( KI, IS ), 1 ) + KI - 1 00756 REMAX = ONE / ABS( VL( II, IS ) ) 00757 CALL DSCAL( N-KI+1, REMAX, VL( KI, IS ), 1 ) 00758 * 00759 DO 180 K = 1, KI - 1 00760 VL( K, IS ) = ZERO 00761 180 CONTINUE 00762 * 00763 ELSE 00764 * 00765 IF( KI.LT.N ) 00766 $ CALL DGEMV( 'N', N, N-KI, ONE, VL( 1, KI+1 ), LDVL, 00767 $ WORK( KI+1+N ), 1, WORK( KI+N ), 00768 $ VL( 1, KI ), 1 ) 00769 * 00770 II = IDAMAX( N, VL( 1, KI ), 1 ) 00771 REMAX = ONE / ABS( VL( II, KI ) ) 00772 CALL DSCAL( N, REMAX, VL( 1, KI ), 1 ) 00773 * 00774 END IF 00775 * 00776 ELSE 00777 * 00778 * Complex left eigenvector. 00779 * 00780 * Initial solve: 00781 * ((T(KI,KI) T(KI,KI+1) )**T - (WR - I* WI))*X = 0. 00782 * ((T(KI+1,KI) T(KI+1,KI+1)) ) 00783 * 00784 IF( ABS( T( KI, KI+1 ) ).GE.ABS( T( KI+1, KI ) ) ) THEN 00785 WORK( KI+N ) = WI / T( KI, KI+1 ) 00786 WORK( KI+1+N2 ) = ONE 00787 ELSE 00788 WORK( KI+N ) = ONE 00789 WORK( KI+1+N2 ) = -WI / T( KI+1, KI ) 00790 END IF 00791 WORK( KI+1+N ) = ZERO 00792 WORK( KI+N2 ) = ZERO 00793 * 00794 * Form right-hand side 00795 * 00796 DO 190 K = KI + 2, N 00797 WORK( K+N ) = -WORK( KI+N )*T( KI, K ) 00798 WORK( K+N2 ) = -WORK( KI+1+N2 )*T( KI+1, K ) 00799 190 CONTINUE 00800 * 00801 * Solve complex quasi-triangular system: 00802 * ( T(KI+2,N:KI+2,N) - (WR-i*WI) )*X = WORK1+i*WORK2 00803 * 00804 VMAX = ONE 00805 VCRIT = BIGNUM 00806 * 00807 JNXT = KI + 2 00808 DO 200 J = KI + 2, N 00809 IF( J.LT.JNXT ) 00810 $ GO TO 200 00811 J1 = J 00812 J2 = J 00813 JNXT = J + 1 00814 IF( J.LT.N ) THEN 00815 IF( T( J+1, J ).NE.ZERO ) THEN 00816 J2 = J + 1 00817 JNXT = J + 2 00818 END IF 00819 END IF 00820 * 00821 IF( J1.EQ.J2 ) THEN 00822 * 00823 * 1-by-1 diagonal block 00824 * 00825 * Scale if necessary to avoid overflow when 00826 * forming the right-hand side elements. 00827 * 00828 IF( WORK( J ).GT.VCRIT ) THEN 00829 REC = ONE / VMAX 00830 CALL DSCAL( N-KI+1, REC, WORK( KI+N ), 1 ) 00831 CALL DSCAL( N-KI+1, REC, WORK( KI+N2 ), 1 ) 00832 VMAX = ONE 00833 VCRIT = BIGNUM 00834 END IF 00835 * 00836 WORK( J+N ) = WORK( J+N ) - 00837 $ DDOT( J-KI-2, T( KI+2, J ), 1, 00838 $ WORK( KI+2+N ), 1 ) 00839 WORK( J+N2 ) = WORK( J+N2 ) - 00840 $ DDOT( J-KI-2, T( KI+2, J ), 1, 00841 $ WORK( KI+2+N2 ), 1 ) 00842 * 00843 * Solve (T(J,J)-(WR-i*WI))*(X11+i*X12)= WK+I*WK2 00844 * 00845 CALL DLALN2( .FALSE., 1, 2, SMIN, ONE, T( J, J ), 00846 $ LDT, ONE, ONE, WORK( J+N ), N, WR, 00847 $ -WI, X, 2, SCALE, XNORM, IERR ) 00848 * 00849 * Scale if necessary 00850 * 00851 IF( SCALE.NE.ONE ) THEN 00852 CALL DSCAL( N-KI+1, SCALE, WORK( KI+N ), 1 ) 00853 CALL DSCAL( N-KI+1, SCALE, WORK( KI+N2 ), 1 ) 00854 END IF 00855 WORK( J+N ) = X( 1, 1 ) 00856 WORK( J+N2 ) = X( 1, 2 ) 00857 VMAX = MAX( ABS( WORK( J+N ) ), 00858 $ ABS( WORK( J+N2 ) ), VMAX ) 00859 VCRIT = BIGNUM / VMAX 00860 * 00861 ELSE 00862 * 00863 * 2-by-2 diagonal block 00864 * 00865 * Scale if necessary to avoid overflow when forming 00866 * the right-hand side elements. 00867 * 00868 BETA = MAX( WORK( J ), WORK( J+1 ) ) 00869 IF( BETA.GT.VCRIT ) THEN 00870 REC = ONE / VMAX 00871 CALL DSCAL( N-KI+1, REC, WORK( KI+N ), 1 ) 00872 CALL DSCAL( N-KI+1, REC, WORK( KI+N2 ), 1 ) 00873 VMAX = ONE 00874 VCRIT = BIGNUM 00875 END IF 00876 * 00877 WORK( J+N ) = WORK( J+N ) - 00878 $ DDOT( J-KI-2, T( KI+2, J ), 1, 00879 $ WORK( KI+2+N ), 1 ) 00880 * 00881 WORK( J+N2 ) = WORK( J+N2 ) - 00882 $ DDOT( J-KI-2, T( KI+2, J ), 1, 00883 $ WORK( KI+2+N2 ), 1 ) 00884 * 00885 WORK( J+1+N ) = WORK( J+1+N ) - 00886 $ DDOT( J-KI-2, T( KI+2, J+1 ), 1, 00887 $ WORK( KI+2+N ), 1 ) 00888 * 00889 WORK( J+1+N2 ) = WORK( J+1+N2 ) - 00890 $ DDOT( J-KI-2, T( KI+2, J+1 ), 1, 00891 $ WORK( KI+2+N2 ), 1 ) 00892 * 00893 * Solve 2-by-2 complex linear equation 00894 * ([T(j,j) T(j,j+1) ]**T-(wr-i*wi)*I)*X = SCALE*B 00895 * ([T(j+1,j) T(j+1,j+1)] ) 00896 * 00897 CALL DLALN2( .TRUE., 2, 2, SMIN, ONE, T( J, J ), 00898 $ LDT, ONE, ONE, WORK( J+N ), N, WR, 00899 $ -WI, X, 2, SCALE, XNORM, IERR ) 00900 * 00901 * Scale if necessary 00902 * 00903 IF( SCALE.NE.ONE ) THEN 00904 CALL DSCAL( N-KI+1, SCALE, WORK( KI+N ), 1 ) 00905 CALL DSCAL( N-KI+1, SCALE, WORK( KI+N2 ), 1 ) 00906 END IF 00907 WORK( J+N ) = X( 1, 1 ) 00908 WORK( J+N2 ) = X( 1, 2 ) 00909 WORK( J+1+N ) = X( 2, 1 ) 00910 WORK( J+1+N2 ) = X( 2, 2 ) 00911 VMAX = MAX( ABS( X( 1, 1 ) ), ABS( X( 1, 2 ) ), 00912 $ ABS( X( 2, 1 ) ), ABS( X( 2, 2 ) ), VMAX ) 00913 VCRIT = BIGNUM / VMAX 00914 * 00915 END IF 00916 200 CONTINUE 00917 * 00918 * Copy the vector x or Q*x to VL and normalize. 00919 * 00920 IF( .NOT.OVER ) THEN 00921 CALL DCOPY( N-KI+1, WORK( KI+N ), 1, VL( KI, IS ), 1 ) 00922 CALL DCOPY( N-KI+1, WORK( KI+N2 ), 1, VL( KI, IS+1 ), 00923 $ 1 ) 00924 * 00925 EMAX = ZERO 00926 DO 220 K = KI, N 00927 EMAX = MAX( EMAX, ABS( VL( K, IS ) )+ 00928 $ ABS( VL( K, IS+1 ) ) ) 00929 220 CONTINUE 00930 REMAX = ONE / EMAX 00931 CALL DSCAL( N-KI+1, REMAX, VL( KI, IS ), 1 ) 00932 CALL DSCAL( N-KI+1, REMAX, VL( KI, IS+1 ), 1 ) 00933 * 00934 DO 230 K = 1, KI - 1 00935 VL( K, IS ) = ZERO 00936 VL( K, IS+1 ) = ZERO 00937 230 CONTINUE 00938 ELSE 00939 IF( KI.LT.N-1 ) THEN 00940 CALL DGEMV( 'N', N, N-KI-1, ONE, VL( 1, KI+2 ), 00941 $ LDVL, WORK( KI+2+N ), 1, WORK( KI+N ), 00942 $ VL( 1, KI ), 1 ) 00943 CALL DGEMV( 'N', N, N-KI-1, ONE, VL( 1, KI+2 ), 00944 $ LDVL, WORK( KI+2+N2 ), 1, 00945 $ WORK( KI+1+N2 ), VL( 1, KI+1 ), 1 ) 00946 ELSE 00947 CALL DSCAL( N, WORK( KI+N ), VL( 1, KI ), 1 ) 00948 CALL DSCAL( N, WORK( KI+1+N2 ), VL( 1, KI+1 ), 1 ) 00949 END IF 00950 * 00951 EMAX = ZERO 00952 DO 240 K = 1, N 00953 EMAX = MAX( EMAX, ABS( VL( K, KI ) )+ 00954 $ ABS( VL( K, KI+1 ) ) ) 00955 240 CONTINUE 00956 REMAX = ONE / EMAX 00957 CALL DSCAL( N, REMAX, VL( 1, KI ), 1 ) 00958 CALL DSCAL( N, REMAX, VL( 1, KI+1 ), 1 ) 00959 * 00960 END IF 00961 * 00962 END IF 00963 * 00964 IS = IS + 1 00965 IF( IP.NE.0 ) 00966 $ IS = IS + 1 00967 250 CONTINUE 00968 IF( IP.EQ.-1 ) 00969 $ IP = 0 00970 IF( IP.EQ.1 ) 00971 $ IP = -1 00972 * 00973 260 CONTINUE 00974 * 00975 END IF 00976 * 00977 RETURN 00978 * 00979 * End of DTREVC 00980 * 00981 END