LAPACK 3.3.1
Linear Algebra PACKage
|
00001 SUBROUTINE STREVC( 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 REAL T( LDT, * ), VL( LDVL, * ), VR( LDVR, * ), 00016 $ WORK( * ) 00017 * .. 00018 * 00019 * Purpose 00020 * ======= 00021 * 00022 * STREVC 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 SHSEQR. 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) REAL 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) REAL 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 SHSEQR). 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) REAL 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 SHSEQR). 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) REAL 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 REAL ZERO, ONE 00149 PARAMETER ( ZERO = 0.0E+0, ONE = 1.0E+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 REAL 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 ISAMAX 00161 REAL SDOT, SLAMCH 00162 EXTERNAL LSAME, ISAMAX, SDOT, SLAMCH 00163 * .. 00164 * .. External Subroutines .. 00165 EXTERNAL SAXPY, SCOPY, SGEMV, SLABAD, SLALN2, SSCAL, 00166 $ XERBLA 00167 * .. 00168 * .. Intrinsic Functions .. 00169 INTRINSIC ABS, MAX, SQRT 00170 * .. 00171 * .. Local Arrays .. 00172 REAL X( 2, 2 ) 00173 * .. 00174 * .. Executable Statements .. 00175 * 00176 * Decode and test the input parameters 00177 * 00178 BOTHV = LSAME( SIDE, 'B' ) 00179 RIGHTV = LSAME( SIDE, 'R' ) .OR. BOTHV 00180 LEFTV = LSAME( SIDE, 'L' ) .OR. BOTHV 00181 * 00182 ALLV = LSAME( HOWMNY, 'A' ) 00183 OVER = LSAME( HOWMNY, 'B' ) 00184 SOMEV = LSAME( HOWMNY, 'S' ) 00185 * 00186 INFO = 0 00187 IF( .NOT.RIGHTV .AND. .NOT.LEFTV ) THEN 00188 INFO = -1 00189 ELSE IF( .NOT.ALLV .AND. .NOT.OVER .AND. .NOT.SOMEV ) THEN 00190 INFO = -2 00191 ELSE IF( N.LT.0 ) THEN 00192 INFO = -4 00193 ELSE IF( LDT.LT.MAX( 1, N ) ) THEN 00194 INFO = -6 00195 ELSE IF( LDVL.LT.1 .OR. ( LEFTV .AND. LDVL.LT.N ) ) THEN 00196 INFO = -8 00197 ELSE IF( LDVR.LT.1 .OR. ( RIGHTV .AND. LDVR.LT.N ) ) THEN 00198 INFO = -10 00199 ELSE 00200 * 00201 * Set M to the number of columns required to store the selected 00202 * eigenvectors, standardize the array SELECT if necessary, and 00203 * test MM. 00204 * 00205 IF( SOMEV ) THEN 00206 M = 0 00207 PAIR = .FALSE. 00208 DO 10 J = 1, N 00209 IF( PAIR ) THEN 00210 PAIR = .FALSE. 00211 SELECT( J ) = .FALSE. 00212 ELSE 00213 IF( J.LT.N ) THEN 00214 IF( T( J+1, J ).EQ.ZERO ) THEN 00215 IF( SELECT( J ) ) 00216 $ M = M + 1 00217 ELSE 00218 PAIR = .TRUE. 00219 IF( SELECT( J ) .OR. SELECT( J+1 ) ) THEN 00220 SELECT( J ) = .TRUE. 00221 M = M + 2 00222 END IF 00223 END IF 00224 ELSE 00225 IF( SELECT( N ) ) 00226 $ M = M + 1 00227 END IF 00228 END IF 00229 10 CONTINUE 00230 ELSE 00231 M = N 00232 END IF 00233 * 00234 IF( MM.LT.M ) THEN 00235 INFO = -11 00236 END IF 00237 END IF 00238 IF( INFO.NE.0 ) THEN 00239 CALL XERBLA( 'STREVC', -INFO ) 00240 RETURN 00241 END IF 00242 * 00243 * Quick return if possible. 00244 * 00245 IF( N.EQ.0 ) 00246 $ RETURN 00247 * 00248 * Set the constants to control overflow. 00249 * 00250 UNFL = SLAMCH( 'Safe minimum' ) 00251 OVFL = ONE / UNFL 00252 CALL SLABAD( UNFL, OVFL ) 00253 ULP = SLAMCH( 'Precision' ) 00254 SMLNUM = UNFL*( N / ULP ) 00255 BIGNUM = ( ONE-ULP ) / SMLNUM 00256 * 00257 * Compute 1-norm of each column of strictly upper triangular 00258 * part of T to control overflow in triangular solver. 00259 * 00260 WORK( 1 ) = ZERO 00261 DO 30 J = 2, N 00262 WORK( J ) = ZERO 00263 DO 20 I = 1, J - 1 00264 WORK( J ) = WORK( J ) + ABS( T( I, J ) ) 00265 20 CONTINUE 00266 30 CONTINUE 00267 * 00268 * Index IP is used to specify the real or complex eigenvalue: 00269 * IP = 0, real eigenvalue, 00270 * 1, first of conjugate complex pair: (wr,wi) 00271 * -1, second of conjugate complex pair: (wr,wi) 00272 * 00273 N2 = 2*N 00274 * 00275 IF( RIGHTV ) THEN 00276 * 00277 * Compute right eigenvectors. 00278 * 00279 IP = 0 00280 IS = M 00281 DO 140 KI = N, 1, -1 00282 * 00283 IF( IP.EQ.1 ) 00284 $ GO TO 130 00285 IF( KI.EQ.1 ) 00286 $ GO TO 40 00287 IF( T( KI, KI-1 ).EQ.ZERO ) 00288 $ GO TO 40 00289 IP = -1 00290 * 00291 40 CONTINUE 00292 IF( SOMEV ) THEN 00293 IF( IP.EQ.0 ) THEN 00294 IF( .NOT.SELECT( KI ) ) 00295 $ GO TO 130 00296 ELSE 00297 IF( .NOT.SELECT( KI-1 ) ) 00298 $ GO TO 130 00299 END IF 00300 END IF 00301 * 00302 * Compute the KI-th eigenvalue (WR,WI). 00303 * 00304 WR = T( KI, KI ) 00305 WI = ZERO 00306 IF( IP.NE.0 ) 00307 $ WI = SQRT( ABS( T( KI, KI-1 ) ) )* 00308 $ SQRT( ABS( T( KI-1, KI ) ) ) 00309 SMIN = MAX( ULP*( ABS( WR )+ABS( WI ) ), SMLNUM ) 00310 * 00311 IF( IP.EQ.0 ) THEN 00312 * 00313 * Real right eigenvector 00314 * 00315 WORK( KI+N ) = ONE 00316 * 00317 * Form right-hand side 00318 * 00319 DO 50 K = 1, KI - 1 00320 WORK( K+N ) = -T( K, KI ) 00321 50 CONTINUE 00322 * 00323 * Solve the upper quasi-triangular system: 00324 * (T(1:KI-1,1:KI-1) - WR)*X = SCALE*WORK. 00325 * 00326 JNXT = KI - 1 00327 DO 60 J = KI - 1, 1, -1 00328 IF( J.GT.JNXT ) 00329 $ GO TO 60 00330 J1 = J 00331 J2 = J 00332 JNXT = J - 1 00333 IF( J.GT.1 ) THEN 00334 IF( T( J, J-1 ).NE.ZERO ) THEN 00335 J1 = J - 1 00336 JNXT = J - 2 00337 END IF 00338 END IF 00339 * 00340 IF( J1.EQ.J2 ) THEN 00341 * 00342 * 1-by-1 diagonal block 00343 * 00344 CALL SLALN2( .FALSE., 1, 1, SMIN, ONE, T( J, J ), 00345 $ LDT, ONE, ONE, WORK( J+N ), N, WR, 00346 $ ZERO, X, 2, SCALE, XNORM, IERR ) 00347 * 00348 * Scale X(1,1) to avoid overflow when updating 00349 * the right-hand side. 00350 * 00351 IF( XNORM.GT.ONE ) THEN 00352 IF( WORK( J ).GT.BIGNUM / XNORM ) THEN 00353 X( 1, 1 ) = X( 1, 1 ) / XNORM 00354 SCALE = SCALE / XNORM 00355 END IF 00356 END IF 00357 * 00358 * Scale if necessary 00359 * 00360 IF( SCALE.NE.ONE ) 00361 $ CALL SSCAL( KI, SCALE, WORK( 1+N ), 1 ) 00362 WORK( J+N ) = X( 1, 1 ) 00363 * 00364 * Update right-hand side 00365 * 00366 CALL SAXPY( J-1, -X( 1, 1 ), T( 1, J ), 1, 00367 $ WORK( 1+N ), 1 ) 00368 * 00369 ELSE 00370 * 00371 * 2-by-2 diagonal block 00372 * 00373 CALL SLALN2( .FALSE., 2, 1, SMIN, ONE, 00374 $ T( J-1, J-1 ), LDT, ONE, ONE, 00375 $ WORK( J-1+N ), N, WR, ZERO, X, 2, 00376 $ SCALE, XNORM, IERR ) 00377 * 00378 * Scale X(1,1) and X(2,1) to avoid overflow when 00379 * updating the right-hand side. 00380 * 00381 IF( XNORM.GT.ONE ) THEN 00382 BETA = MAX( WORK( J-1 ), WORK( J ) ) 00383 IF( BETA.GT.BIGNUM / XNORM ) THEN 00384 X( 1, 1 ) = X( 1, 1 ) / XNORM 00385 X( 2, 1 ) = X( 2, 1 ) / XNORM 00386 SCALE = SCALE / XNORM 00387 END IF 00388 END IF 00389 * 00390 * Scale if necessary 00391 * 00392 IF( SCALE.NE.ONE ) 00393 $ CALL SSCAL( KI, SCALE, WORK( 1+N ), 1 ) 00394 WORK( J-1+N ) = X( 1, 1 ) 00395 WORK( J+N ) = X( 2, 1 ) 00396 * 00397 * Update right-hand side 00398 * 00399 CALL SAXPY( J-2, -X( 1, 1 ), T( 1, J-1 ), 1, 00400 $ WORK( 1+N ), 1 ) 00401 CALL SAXPY( J-2, -X( 2, 1 ), T( 1, J ), 1, 00402 $ WORK( 1+N ), 1 ) 00403 END IF 00404 60 CONTINUE 00405 * 00406 * Copy the vector x or Q*x to VR and normalize. 00407 * 00408 IF( .NOT.OVER ) THEN 00409 CALL SCOPY( KI, WORK( 1+N ), 1, VR( 1, IS ), 1 ) 00410 * 00411 II = ISAMAX( KI, VR( 1, IS ), 1 ) 00412 REMAX = ONE / ABS( VR( II, IS ) ) 00413 CALL SSCAL( KI, REMAX, VR( 1, IS ), 1 ) 00414 * 00415 DO 70 K = KI + 1, N 00416 VR( K, IS ) = ZERO 00417 70 CONTINUE 00418 ELSE 00419 IF( KI.GT.1 ) 00420 $ CALL SGEMV( 'N', N, KI-1, ONE, VR, LDVR, 00421 $ WORK( 1+N ), 1, WORK( KI+N ), 00422 $ VR( 1, KI ), 1 ) 00423 * 00424 II = ISAMAX( N, VR( 1, KI ), 1 ) 00425 REMAX = ONE / ABS( VR( II, KI ) ) 00426 CALL SSCAL( N, REMAX, VR( 1, KI ), 1 ) 00427 END IF 00428 * 00429 ELSE 00430 * 00431 * Complex right eigenvector. 00432 * 00433 * Initial solve 00434 * [ (T(KI-1,KI-1) T(KI-1,KI) ) - (WR + I* WI)]*X = 0. 00435 * [ (T(KI,KI-1) T(KI,KI) ) ] 00436 * 00437 IF( ABS( T( KI-1, KI ) ).GE.ABS( T( KI, KI-1 ) ) ) THEN 00438 WORK( KI-1+N ) = ONE 00439 WORK( KI+N2 ) = WI / T( KI-1, KI ) 00440 ELSE 00441 WORK( KI-1+N ) = -WI / T( KI, KI-1 ) 00442 WORK( KI+N2 ) = ONE 00443 END IF 00444 WORK( KI+N ) = ZERO 00445 WORK( KI-1+N2 ) = ZERO 00446 * 00447 * Form right-hand side 00448 * 00449 DO 80 K = 1, KI - 2 00450 WORK( K+N ) = -WORK( KI-1+N )*T( K, KI-1 ) 00451 WORK( K+N2 ) = -WORK( KI+N2 )*T( K, KI ) 00452 80 CONTINUE 00453 * 00454 * Solve upper quasi-triangular system: 00455 * (T(1:KI-2,1:KI-2) - (WR+i*WI))*X = SCALE*(WORK+i*WORK2) 00456 * 00457 JNXT = KI - 2 00458 DO 90 J = KI - 2, 1, -1 00459 IF( J.GT.JNXT ) 00460 $ GO TO 90 00461 J1 = J 00462 J2 = J 00463 JNXT = J - 1 00464 IF( J.GT.1 ) THEN 00465 IF( T( J, J-1 ).NE.ZERO ) THEN 00466 J1 = J - 1 00467 JNXT = J - 2 00468 END IF 00469 END IF 00470 * 00471 IF( J1.EQ.J2 ) THEN 00472 * 00473 * 1-by-1 diagonal block 00474 * 00475 CALL SLALN2( .FALSE., 1, 2, SMIN, ONE, T( J, J ), 00476 $ LDT, ONE, ONE, WORK( J+N ), N, WR, WI, 00477 $ X, 2, SCALE, XNORM, IERR ) 00478 * 00479 * Scale X(1,1) and X(1,2) to avoid overflow when 00480 * updating the right-hand side. 00481 * 00482 IF( XNORM.GT.ONE ) THEN 00483 IF( WORK( J ).GT.BIGNUM / XNORM ) THEN 00484 X( 1, 1 ) = X( 1, 1 ) / XNORM 00485 X( 1, 2 ) = X( 1, 2 ) / XNORM 00486 SCALE = SCALE / XNORM 00487 END IF 00488 END IF 00489 * 00490 * Scale if necessary 00491 * 00492 IF( SCALE.NE.ONE ) THEN 00493 CALL SSCAL( KI, SCALE, WORK( 1+N ), 1 ) 00494 CALL SSCAL( KI, SCALE, WORK( 1+N2 ), 1 ) 00495 END IF 00496 WORK( J+N ) = X( 1, 1 ) 00497 WORK( J+N2 ) = X( 1, 2 ) 00498 * 00499 * Update the right-hand side 00500 * 00501 CALL SAXPY( J-1, -X( 1, 1 ), T( 1, J ), 1, 00502 $ WORK( 1+N ), 1 ) 00503 CALL SAXPY( J-1, -X( 1, 2 ), T( 1, J ), 1, 00504 $ WORK( 1+N2 ), 1 ) 00505 * 00506 ELSE 00507 * 00508 * 2-by-2 diagonal block 00509 * 00510 CALL SLALN2( .FALSE., 2, 2, SMIN, ONE, 00511 $ T( J-1, J-1 ), LDT, ONE, ONE, 00512 $ WORK( J-1+N ), N, WR, WI, X, 2, SCALE, 00513 $ XNORM, IERR ) 00514 * 00515 * Scale X to avoid overflow when updating 00516 * the right-hand side. 00517 * 00518 IF( XNORM.GT.ONE ) THEN 00519 BETA = MAX( WORK( J-1 ), WORK( J ) ) 00520 IF( BETA.GT.BIGNUM / XNORM ) THEN 00521 REC = ONE / XNORM 00522 X( 1, 1 ) = X( 1, 1 )*REC 00523 X( 1, 2 ) = X( 1, 2 )*REC 00524 X( 2, 1 ) = X( 2, 1 )*REC 00525 X( 2, 2 ) = X( 2, 2 )*REC 00526 SCALE = SCALE*REC 00527 END IF 00528 END IF 00529 * 00530 * Scale if necessary 00531 * 00532 IF( SCALE.NE.ONE ) THEN 00533 CALL SSCAL( KI, SCALE, WORK( 1+N ), 1 ) 00534 CALL SSCAL( KI, SCALE, WORK( 1+N2 ), 1 ) 00535 END IF 00536 WORK( J-1+N ) = X( 1, 1 ) 00537 WORK( J+N ) = X( 2, 1 ) 00538 WORK( J-1+N2 ) = X( 1, 2 ) 00539 WORK( J+N2 ) = X( 2, 2 ) 00540 * 00541 * Update the right-hand side 00542 * 00543 CALL SAXPY( J-2, -X( 1, 1 ), T( 1, J-1 ), 1, 00544 $ WORK( 1+N ), 1 ) 00545 CALL SAXPY( J-2, -X( 2, 1 ), T( 1, J ), 1, 00546 $ WORK( 1+N ), 1 ) 00547 CALL SAXPY( J-2, -X( 1, 2 ), T( 1, J-1 ), 1, 00548 $ WORK( 1+N2 ), 1 ) 00549 CALL SAXPY( J-2, -X( 2, 2 ), T( 1, J ), 1, 00550 $ WORK( 1+N2 ), 1 ) 00551 END IF 00552 90 CONTINUE 00553 * 00554 * Copy the vector x or Q*x to VR and normalize. 00555 * 00556 IF( .NOT.OVER ) THEN 00557 CALL SCOPY( KI, WORK( 1+N ), 1, VR( 1, IS-1 ), 1 ) 00558 CALL SCOPY( KI, WORK( 1+N2 ), 1, VR( 1, IS ), 1 ) 00559 * 00560 EMAX = ZERO 00561 DO 100 K = 1, KI 00562 EMAX = MAX( EMAX, ABS( VR( K, IS-1 ) )+ 00563 $ ABS( VR( K, IS ) ) ) 00564 100 CONTINUE 00565 * 00566 REMAX = ONE / EMAX 00567 CALL SSCAL( KI, REMAX, VR( 1, IS-1 ), 1 ) 00568 CALL SSCAL( KI, REMAX, VR( 1, IS ), 1 ) 00569 * 00570 DO 110 K = KI + 1, N 00571 VR( K, IS-1 ) = ZERO 00572 VR( K, IS ) = ZERO 00573 110 CONTINUE 00574 * 00575 ELSE 00576 * 00577 IF( KI.GT.2 ) THEN 00578 CALL SGEMV( 'N', N, KI-2, ONE, VR, LDVR, 00579 $ WORK( 1+N ), 1, WORK( KI-1+N ), 00580 $ VR( 1, KI-1 ), 1 ) 00581 CALL SGEMV( 'N', N, KI-2, ONE, VR, LDVR, 00582 $ WORK( 1+N2 ), 1, WORK( KI+N2 ), 00583 $ VR( 1, KI ), 1 ) 00584 ELSE 00585 CALL SSCAL( N, WORK( KI-1+N ), VR( 1, KI-1 ), 1 ) 00586 CALL SSCAL( N, WORK( KI+N2 ), VR( 1, KI ), 1 ) 00587 END IF 00588 * 00589 EMAX = ZERO 00590 DO 120 K = 1, N 00591 EMAX = MAX( EMAX, ABS( VR( K, KI-1 ) )+ 00592 $ ABS( VR( K, KI ) ) ) 00593 120 CONTINUE 00594 REMAX = ONE / EMAX 00595 CALL SSCAL( N, REMAX, VR( 1, KI-1 ), 1 ) 00596 CALL SSCAL( N, REMAX, VR( 1, KI ), 1 ) 00597 END IF 00598 END IF 00599 * 00600 IS = IS - 1 00601 IF( IP.NE.0 ) 00602 $ IS = IS - 1 00603 130 CONTINUE 00604 IF( IP.EQ.1 ) 00605 $ IP = 0 00606 IF( IP.EQ.-1 ) 00607 $ IP = 1 00608 140 CONTINUE 00609 END IF 00610 * 00611 IF( LEFTV ) THEN 00612 * 00613 * Compute left eigenvectors. 00614 * 00615 IP = 0 00616 IS = 1 00617 DO 260 KI = 1, N 00618 * 00619 IF( IP.EQ.-1 ) 00620 $ GO TO 250 00621 IF( KI.EQ.N ) 00622 $ GO TO 150 00623 IF( T( KI+1, KI ).EQ.ZERO ) 00624 $ GO TO 150 00625 IP = 1 00626 * 00627 150 CONTINUE 00628 IF( SOMEV ) THEN 00629 IF( .NOT.SELECT( KI ) ) 00630 $ GO TO 250 00631 END IF 00632 * 00633 * Compute the KI-th eigenvalue (WR,WI). 00634 * 00635 WR = T( KI, KI ) 00636 WI = ZERO 00637 IF( IP.NE.0 ) 00638 $ WI = SQRT( ABS( T( KI, KI+1 ) ) )* 00639 $ SQRT( ABS( T( KI+1, KI ) ) ) 00640 SMIN = MAX( ULP*( ABS( WR )+ABS( WI ) ), SMLNUM ) 00641 * 00642 IF( IP.EQ.0 ) THEN 00643 * 00644 * Real left eigenvector. 00645 * 00646 WORK( KI+N ) = ONE 00647 * 00648 * Form right-hand side 00649 * 00650 DO 160 K = KI + 1, N 00651 WORK( K+N ) = -T( KI, K ) 00652 160 CONTINUE 00653 * 00654 * Solve the quasi-triangular system: 00655 * (T(KI+1:N,KI+1:N) - WR)**T*X = SCALE*WORK 00656 * 00657 VMAX = ONE 00658 VCRIT = BIGNUM 00659 * 00660 JNXT = KI + 1 00661 DO 170 J = KI + 1, N 00662 IF( J.LT.JNXT ) 00663 $ GO TO 170 00664 J1 = J 00665 J2 = J 00666 JNXT = J + 1 00667 IF( J.LT.N ) THEN 00668 IF( T( J+1, J ).NE.ZERO ) THEN 00669 J2 = J + 1 00670 JNXT = J + 2 00671 END IF 00672 END IF 00673 * 00674 IF( J1.EQ.J2 ) THEN 00675 * 00676 * 1-by-1 diagonal block 00677 * 00678 * Scale if necessary to avoid overflow when forming 00679 * the right-hand side. 00680 * 00681 IF( WORK( J ).GT.VCRIT ) THEN 00682 REC = ONE / VMAX 00683 CALL SSCAL( N-KI+1, REC, WORK( KI+N ), 1 ) 00684 VMAX = ONE 00685 VCRIT = BIGNUM 00686 END IF 00687 * 00688 WORK( J+N ) = WORK( J+N ) - 00689 $ SDOT( J-KI-1, T( KI+1, J ), 1, 00690 $ WORK( KI+1+N ), 1 ) 00691 * 00692 * Solve (T(J,J)-WR)**T*X = WORK 00693 * 00694 CALL SLALN2( .FALSE., 1, 1, SMIN, ONE, T( J, J ), 00695 $ LDT, ONE, ONE, WORK( J+N ), N, WR, 00696 $ ZERO, X, 2, SCALE, XNORM, IERR ) 00697 * 00698 * Scale if necessary 00699 * 00700 IF( SCALE.NE.ONE ) 00701 $ CALL SSCAL( N-KI+1, SCALE, WORK( KI+N ), 1 ) 00702 WORK( J+N ) = X( 1, 1 ) 00703 VMAX = MAX( ABS( WORK( J+N ) ), VMAX ) 00704 VCRIT = BIGNUM / VMAX 00705 * 00706 ELSE 00707 * 00708 * 2-by-2 diagonal block 00709 * 00710 * Scale if necessary to avoid overflow when forming 00711 * the right-hand side. 00712 * 00713 BETA = MAX( WORK( J ), WORK( J+1 ) ) 00714 IF( BETA.GT.VCRIT ) THEN 00715 REC = ONE / VMAX 00716 CALL SSCAL( N-KI+1, REC, WORK( KI+N ), 1 ) 00717 VMAX = ONE 00718 VCRIT = BIGNUM 00719 END IF 00720 * 00721 WORK( J+N ) = WORK( J+N ) - 00722 $ SDOT( J-KI-1, T( KI+1, J ), 1, 00723 $ WORK( KI+1+N ), 1 ) 00724 * 00725 WORK( J+1+N ) = WORK( J+1+N ) - 00726 $ SDOT( J-KI-1, T( KI+1, J+1 ), 1, 00727 $ WORK( KI+1+N ), 1 ) 00728 * 00729 * Solve 00730 * [T(J,J)-WR T(J,J+1) ]**T* X = SCALE*( WORK1 ) 00731 * [T(J+1,J) T(J+1,J+1)-WR] ( WORK2 ) 00732 * 00733 CALL SLALN2( .TRUE., 2, 1, SMIN, ONE, T( J, J ), 00734 $ LDT, ONE, ONE, WORK( J+N ), N, WR, 00735 $ ZERO, X, 2, SCALE, XNORM, IERR ) 00736 * 00737 * Scale if necessary 00738 * 00739 IF( SCALE.NE.ONE ) 00740 $ CALL SSCAL( N-KI+1, SCALE, WORK( KI+N ), 1 ) 00741 WORK( J+N ) = X( 1, 1 ) 00742 WORK( J+1+N ) = X( 2, 1 ) 00743 * 00744 VMAX = MAX( ABS( WORK( J+N ) ), 00745 $ ABS( WORK( J+1+N ) ), VMAX ) 00746 VCRIT = BIGNUM / VMAX 00747 * 00748 END IF 00749 170 CONTINUE 00750 * 00751 * Copy the vector x or Q*x to VL and normalize. 00752 * 00753 IF( .NOT.OVER ) THEN 00754 CALL SCOPY( N-KI+1, WORK( KI+N ), 1, VL( KI, IS ), 1 ) 00755 * 00756 II = ISAMAX( N-KI+1, VL( KI, IS ), 1 ) + KI - 1 00757 REMAX = ONE / ABS( VL( II, IS ) ) 00758 CALL SSCAL( N-KI+1, REMAX, VL( KI, IS ), 1 ) 00759 * 00760 DO 180 K = 1, KI - 1 00761 VL( K, IS ) = ZERO 00762 180 CONTINUE 00763 * 00764 ELSE 00765 * 00766 IF( KI.LT.N ) 00767 $ CALL SGEMV( 'N', N, N-KI, ONE, VL( 1, KI+1 ), LDVL, 00768 $ WORK( KI+1+N ), 1, WORK( KI+N ), 00769 $ VL( 1, KI ), 1 ) 00770 * 00771 II = ISAMAX( N, VL( 1, KI ), 1 ) 00772 REMAX = ONE / ABS( VL( II, KI ) ) 00773 CALL SSCAL( N, REMAX, VL( 1, KI ), 1 ) 00774 * 00775 END IF 00776 * 00777 ELSE 00778 * 00779 * Complex left eigenvector. 00780 * 00781 * Initial solve: 00782 * ((T(KI,KI) T(KI,KI+1) )**T - (WR - I* WI))*X = 0. 00783 * ((T(KI+1,KI) T(KI+1,KI+1)) ) 00784 * 00785 IF( ABS( T( KI, KI+1 ) ).GE.ABS( T( KI+1, KI ) ) ) THEN 00786 WORK( KI+N ) = WI / T( KI, KI+1 ) 00787 WORK( KI+1+N2 ) = ONE 00788 ELSE 00789 WORK( KI+N ) = ONE 00790 WORK( KI+1+N2 ) = -WI / T( KI+1, KI ) 00791 END IF 00792 WORK( KI+1+N ) = ZERO 00793 WORK( KI+N2 ) = ZERO 00794 * 00795 * Form right-hand side 00796 * 00797 DO 190 K = KI + 2, N 00798 WORK( K+N ) = -WORK( KI+N )*T( KI, K ) 00799 WORK( K+N2 ) = -WORK( KI+1+N2 )*T( KI+1, K ) 00800 190 CONTINUE 00801 * 00802 * Solve complex quasi-triangular system: 00803 * ( T(KI+2,N:KI+2,N) - (WR-i*WI) )*X = WORK1+i*WORK2 00804 * 00805 VMAX = ONE 00806 VCRIT = BIGNUM 00807 * 00808 JNXT = KI + 2 00809 DO 200 J = KI + 2, N 00810 IF( J.LT.JNXT ) 00811 $ GO TO 200 00812 J1 = J 00813 J2 = J 00814 JNXT = J + 1 00815 IF( J.LT.N ) THEN 00816 IF( T( J+1, J ).NE.ZERO ) THEN 00817 J2 = J + 1 00818 JNXT = J + 2 00819 END IF 00820 END IF 00821 * 00822 IF( J1.EQ.J2 ) THEN 00823 * 00824 * 1-by-1 diagonal block 00825 * 00826 * Scale if necessary to avoid overflow when 00827 * forming the right-hand side elements. 00828 * 00829 IF( WORK( J ).GT.VCRIT ) THEN 00830 REC = ONE / VMAX 00831 CALL SSCAL( N-KI+1, REC, WORK( KI+N ), 1 ) 00832 CALL SSCAL( N-KI+1, REC, WORK( KI+N2 ), 1 ) 00833 VMAX = ONE 00834 VCRIT = BIGNUM 00835 END IF 00836 * 00837 WORK( J+N ) = WORK( J+N ) - 00838 $ SDOT( J-KI-2, T( KI+2, J ), 1, 00839 $ WORK( KI+2+N ), 1 ) 00840 WORK( J+N2 ) = WORK( J+N2 ) - 00841 $ SDOT( J-KI-2, T( KI+2, J ), 1, 00842 $ WORK( KI+2+N2 ), 1 ) 00843 * 00844 * Solve (T(J,J)-(WR-i*WI))*(X11+i*X12)= WK+I*WK2 00845 * 00846 CALL SLALN2( .FALSE., 1, 2, SMIN, ONE, T( J, J ), 00847 $ LDT, ONE, ONE, WORK( J+N ), N, WR, 00848 $ -WI, X, 2, SCALE, XNORM, IERR ) 00849 * 00850 * Scale if necessary 00851 * 00852 IF( SCALE.NE.ONE ) THEN 00853 CALL SSCAL( N-KI+1, SCALE, WORK( KI+N ), 1 ) 00854 CALL SSCAL( N-KI+1, SCALE, WORK( KI+N2 ), 1 ) 00855 END IF 00856 WORK( J+N ) = X( 1, 1 ) 00857 WORK( J+N2 ) = X( 1, 2 ) 00858 VMAX = MAX( ABS( WORK( J+N ) ), 00859 $ ABS( WORK( J+N2 ) ), VMAX ) 00860 VCRIT = BIGNUM / VMAX 00861 * 00862 ELSE 00863 * 00864 * 2-by-2 diagonal block 00865 * 00866 * Scale if necessary to avoid overflow when forming 00867 * the right-hand side elements. 00868 * 00869 BETA = MAX( WORK( J ), WORK( J+1 ) ) 00870 IF( BETA.GT.VCRIT ) THEN 00871 REC = ONE / VMAX 00872 CALL SSCAL( N-KI+1, REC, WORK( KI+N ), 1 ) 00873 CALL SSCAL( N-KI+1, REC, WORK( KI+N2 ), 1 ) 00874 VMAX = ONE 00875 VCRIT = BIGNUM 00876 END IF 00877 * 00878 WORK( J+N ) = WORK( J+N ) - 00879 $ SDOT( J-KI-2, T( KI+2, J ), 1, 00880 $ WORK( KI+2+N ), 1 ) 00881 * 00882 WORK( J+N2 ) = WORK( J+N2 ) - 00883 $ SDOT( J-KI-2, T( KI+2, J ), 1, 00884 $ WORK( KI+2+N2 ), 1 ) 00885 * 00886 WORK( J+1+N ) = WORK( J+1+N ) - 00887 $ SDOT( J-KI-2, T( KI+2, J+1 ), 1, 00888 $ WORK( KI+2+N ), 1 ) 00889 * 00890 WORK( J+1+N2 ) = WORK( J+1+N2 ) - 00891 $ SDOT( J-KI-2, T( KI+2, J+1 ), 1, 00892 $ WORK( KI+2+N2 ), 1 ) 00893 * 00894 * Solve 2-by-2 complex linear equation 00895 * ([T(j,j) T(j,j+1) ]**T-(wr-i*wi)*I)*X = SCALE*B 00896 * ([T(j+1,j) T(j+1,j+1)] ) 00897 * 00898 CALL SLALN2( .TRUE., 2, 2, SMIN, ONE, T( J, J ), 00899 $ LDT, ONE, ONE, WORK( J+N ), N, WR, 00900 $ -WI, X, 2, SCALE, XNORM, IERR ) 00901 * 00902 * Scale if necessary 00903 * 00904 IF( SCALE.NE.ONE ) THEN 00905 CALL SSCAL( N-KI+1, SCALE, WORK( KI+N ), 1 ) 00906 CALL SSCAL( N-KI+1, SCALE, WORK( KI+N2 ), 1 ) 00907 END IF 00908 WORK( J+N ) = X( 1, 1 ) 00909 WORK( J+N2 ) = X( 1, 2 ) 00910 WORK( J+1+N ) = X( 2, 1 ) 00911 WORK( J+1+N2 ) = X( 2, 2 ) 00912 VMAX = MAX( ABS( X( 1, 1 ) ), ABS( X( 1, 2 ) ), 00913 $ ABS( X( 2, 1 ) ), ABS( X( 2, 2 ) ), VMAX ) 00914 VCRIT = BIGNUM / VMAX 00915 * 00916 END IF 00917 200 CONTINUE 00918 * 00919 * Copy the vector x or Q*x to VL and normalize. 00920 * 00921 IF( .NOT.OVER ) THEN 00922 CALL SCOPY( N-KI+1, WORK( KI+N ), 1, VL( KI, IS ), 1 ) 00923 CALL SCOPY( N-KI+1, WORK( KI+N2 ), 1, VL( KI, IS+1 ), 00924 $ 1 ) 00925 * 00926 EMAX = ZERO 00927 DO 220 K = KI, N 00928 EMAX = MAX( EMAX, ABS( VL( K, IS ) )+ 00929 $ ABS( VL( K, IS+1 ) ) ) 00930 220 CONTINUE 00931 REMAX = ONE / EMAX 00932 CALL SSCAL( N-KI+1, REMAX, VL( KI, IS ), 1 ) 00933 CALL SSCAL( N-KI+1, REMAX, VL( KI, IS+1 ), 1 ) 00934 * 00935 DO 230 K = 1, KI - 1 00936 VL( K, IS ) = ZERO 00937 VL( K, IS+1 ) = ZERO 00938 230 CONTINUE 00939 ELSE 00940 IF( KI.LT.N-1 ) THEN 00941 CALL SGEMV( 'N', N, N-KI-1, ONE, VL( 1, KI+2 ), 00942 $ LDVL, WORK( KI+2+N ), 1, WORK( KI+N ), 00943 $ VL( 1, KI ), 1 ) 00944 CALL SGEMV( 'N', N, N-KI-1, ONE, VL( 1, KI+2 ), 00945 $ LDVL, WORK( KI+2+N2 ), 1, 00946 $ WORK( KI+1+N2 ), VL( 1, KI+1 ), 1 ) 00947 ELSE 00948 CALL SSCAL( N, WORK( KI+N ), VL( 1, KI ), 1 ) 00949 CALL SSCAL( N, WORK( KI+1+N2 ), VL( 1, KI+1 ), 1 ) 00950 END IF 00951 * 00952 EMAX = ZERO 00953 DO 240 K = 1, N 00954 EMAX = MAX( EMAX, ABS( VL( K, KI ) )+ 00955 $ ABS( VL( K, KI+1 ) ) ) 00956 240 CONTINUE 00957 REMAX = ONE / EMAX 00958 CALL SSCAL( N, REMAX, VL( 1, KI ), 1 ) 00959 CALL SSCAL( N, REMAX, VL( 1, KI+1 ), 1 ) 00960 * 00961 END IF 00962 * 00963 END IF 00964 * 00965 IS = IS + 1 00966 IF( IP.NE.0 ) 00967 $ IS = IS + 1 00968 250 CONTINUE 00969 IF( IP.EQ.-1 ) 00970 $ IP = 0 00971 IF( IP.EQ.1 ) 00972 $ IP = -1 00973 * 00974 260 CONTINUE 00975 * 00976 END IF 00977 * 00978 RETURN 00979 * 00980 * End of STREVC 00981 * 00982 END