Annotation of rpl/lapack/lapack/dtrsna.f, revision 1.1
1.1 ! bertrand 1: SUBROUTINE DTRSNA( JOB, HOWMNY, SELECT, N, T, LDT, VL, LDVL, VR,
! 2: $ LDVR, S, SEP, MM, M, WORK, LDWORK, IWORK,
! 3: $ INFO )
! 4: *
! 5: * -- LAPACK routine (version 3.2) --
! 6: * -- LAPACK is a software package provided by Univ. of Tennessee, --
! 7: * -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..--
! 8: * November 2006
! 9: *
! 10: * Modified to call DLACN2 in place of DLACON, 5 Feb 03, SJH.
! 11: *
! 12: * .. Scalar Arguments ..
! 13: CHARACTER HOWMNY, JOB
! 14: INTEGER INFO, LDT, LDVL, LDVR, LDWORK, M, MM, N
! 15: * ..
! 16: * .. Array Arguments ..
! 17: LOGICAL SELECT( * )
! 18: INTEGER IWORK( * )
! 19: DOUBLE PRECISION S( * ), SEP( * ), T( LDT, * ), VL( LDVL, * ),
! 20: $ VR( LDVR, * ), WORK( LDWORK, * )
! 21: * ..
! 22: *
! 23: * Purpose
! 24: * =======
! 25: *
! 26: * DTRSNA estimates reciprocal condition numbers for specified
! 27: * eigenvalues and/or right eigenvectors of a real upper
! 28: * quasi-triangular matrix T (or of any matrix Q*T*Q**T with Q
! 29: * orthogonal).
! 30: *
! 31: * T must be in Schur canonical form (as returned by DHSEQR), that is,
! 32: * block upper triangular with 1-by-1 and 2-by-2 diagonal blocks; each
! 33: * 2-by-2 diagonal block has its diagonal elements equal and its
! 34: * off-diagonal elements of opposite sign.
! 35: *
! 36: * Arguments
! 37: * =========
! 38: *
! 39: * JOB (input) CHARACTER*1
! 40: * Specifies whether condition numbers are required for
! 41: * eigenvalues (S) or eigenvectors (SEP):
! 42: * = 'E': for eigenvalues only (S);
! 43: * = 'V': for eigenvectors only (SEP);
! 44: * = 'B': for both eigenvalues and eigenvectors (S and SEP).
! 45: *
! 46: * HOWMNY (input) CHARACTER*1
! 47: * = 'A': compute condition numbers for all eigenpairs;
! 48: * = 'S': compute condition numbers for selected eigenpairs
! 49: * specified by the array SELECT.
! 50: *
! 51: * SELECT (input) LOGICAL array, dimension (N)
! 52: * If HOWMNY = 'S', SELECT specifies the eigenpairs for which
! 53: * condition numbers are required. To select condition numbers
! 54: * for the eigenpair corresponding to a real eigenvalue w(j),
! 55: * SELECT(j) must be set to .TRUE.. To select condition numbers
! 56: * corresponding to a complex conjugate pair of eigenvalues w(j)
! 57: * and w(j+1), either SELECT(j) or SELECT(j+1) or both, must be
! 58: * set to .TRUE..
! 59: * If HOWMNY = 'A', SELECT is not referenced.
! 60: *
! 61: * N (input) INTEGER
! 62: * The order of the matrix T. N >= 0.
! 63: *
! 64: * T (input) DOUBLE PRECISION array, dimension (LDT,N)
! 65: * The upper quasi-triangular matrix T, in Schur canonical form.
! 66: *
! 67: * LDT (input) INTEGER
! 68: * The leading dimension of the array T. LDT >= max(1,N).
! 69: *
! 70: * VL (input) DOUBLE PRECISION array, dimension (LDVL,M)
! 71: * If JOB = 'E' or 'B', VL must contain left eigenvectors of T
! 72: * (or of any Q*T*Q**T with Q orthogonal), corresponding to the
! 73: * eigenpairs specified by HOWMNY and SELECT. The eigenvectors
! 74: * must be stored in consecutive columns of VL, as returned by
! 75: * DHSEIN or DTREVC.
! 76: * If JOB = 'V', VL is not referenced.
! 77: *
! 78: * LDVL (input) INTEGER
! 79: * The leading dimension of the array VL.
! 80: * LDVL >= 1; and if JOB = 'E' or 'B', LDVL >= N.
! 81: *
! 82: * VR (input) DOUBLE PRECISION array, dimension (LDVR,M)
! 83: * If JOB = 'E' or 'B', VR must contain right eigenvectors of T
! 84: * (or of any Q*T*Q**T with Q orthogonal), corresponding to the
! 85: * eigenpairs specified by HOWMNY and SELECT. The eigenvectors
! 86: * must be stored in consecutive columns of VR, as returned by
! 87: * DHSEIN or DTREVC.
! 88: * If JOB = 'V', VR is not referenced.
! 89: *
! 90: * LDVR (input) INTEGER
! 91: * The leading dimension of the array VR.
! 92: * LDVR >= 1; and if JOB = 'E' or 'B', LDVR >= N.
! 93: *
! 94: * S (output) DOUBLE PRECISION array, dimension (MM)
! 95: * If JOB = 'E' or 'B', the reciprocal condition numbers of the
! 96: * selected eigenvalues, stored in consecutive elements of the
! 97: * array. For a complex conjugate pair of eigenvalues two
! 98: * consecutive elements of S are set to the same value. Thus
! 99: * S(j), SEP(j), and the j-th columns of VL and VR all
! 100: * correspond to the same eigenpair (but not in general the
! 101: * j-th eigenpair, unless all eigenpairs are selected).
! 102: * If JOB = 'V', S is not referenced.
! 103: *
! 104: * SEP (output) DOUBLE PRECISION array, dimension (MM)
! 105: * If JOB = 'V' or 'B', the estimated reciprocal condition
! 106: * numbers of the selected eigenvectors, stored in consecutive
! 107: * elements of the array. For a complex eigenvector two
! 108: * consecutive elements of SEP are set to the same value. If
! 109: * the eigenvalues cannot be reordered to compute SEP(j), SEP(j)
! 110: * is set to 0; this can only occur when the true value would be
! 111: * very small anyway.
! 112: * If JOB = 'E', SEP is not referenced.
! 113: *
! 114: * MM (input) INTEGER
! 115: * The number of elements in the arrays S (if JOB = 'E' or 'B')
! 116: * and/or SEP (if JOB = 'V' or 'B'). MM >= M.
! 117: *
! 118: * M (output) INTEGER
! 119: * The number of elements of the arrays S and/or SEP actually
! 120: * used to store the estimated condition numbers.
! 121: * If HOWMNY = 'A', M is set to N.
! 122: *
! 123: * WORK (workspace) DOUBLE PRECISION array, dimension (LDWORK,N+6)
! 124: * If JOB = 'E', WORK is not referenced.
! 125: *
! 126: * LDWORK (input) INTEGER
! 127: * The leading dimension of the array WORK.
! 128: * LDWORK >= 1; and if JOB = 'V' or 'B', LDWORK >= N.
! 129: *
! 130: * IWORK (workspace) INTEGER array, dimension (2*(N-1))
! 131: * If JOB = 'E', IWORK is not referenced.
! 132: *
! 133: * INFO (output) INTEGER
! 134: * = 0: successful exit
! 135: * < 0: if INFO = -i, the i-th argument had an illegal value
! 136: *
! 137: * Further Details
! 138: * ===============
! 139: *
! 140: * The reciprocal of the condition number of an eigenvalue lambda is
! 141: * defined as
! 142: *
! 143: * S(lambda) = |v'*u| / (norm(u)*norm(v))
! 144: *
! 145: * where u and v are the right and left eigenvectors of T corresponding
! 146: * to lambda; v' denotes the conjugate-transpose of v, and norm(u)
! 147: * denotes the Euclidean norm. These reciprocal condition numbers always
! 148: * lie between zero (very badly conditioned) and one (very well
! 149: * conditioned). If n = 1, S(lambda) is defined to be 1.
! 150: *
! 151: * An approximate error bound for a computed eigenvalue W(i) is given by
! 152: *
! 153: * EPS * norm(T) / S(i)
! 154: *
! 155: * where EPS is the machine precision.
! 156: *
! 157: * The reciprocal of the condition number of the right eigenvector u
! 158: * corresponding to lambda is defined as follows. Suppose
! 159: *
! 160: * T = ( lambda c )
! 161: * ( 0 T22 )
! 162: *
! 163: * Then the reciprocal condition number is
! 164: *
! 165: * SEP( lambda, T22 ) = sigma-min( T22 - lambda*I )
! 166: *
! 167: * where sigma-min denotes the smallest singular value. We approximate
! 168: * the smallest singular value by the reciprocal of an estimate of the
! 169: * one-norm of the inverse of T22 - lambda*I. If n = 1, SEP(1) is
! 170: * defined to be abs(T(1,1)).
! 171: *
! 172: * An approximate error bound for a computed right eigenvector VR(i)
! 173: * is given by
! 174: *
! 175: * EPS * norm(T) / SEP(i)
! 176: *
! 177: * =====================================================================
! 178: *
! 179: * .. Parameters ..
! 180: DOUBLE PRECISION ZERO, ONE, TWO
! 181: PARAMETER ( ZERO = 0.0D+0, ONE = 1.0D+0, TWO = 2.0D+0 )
! 182: * ..
! 183: * .. Local Scalars ..
! 184: LOGICAL PAIR, SOMCON, WANTBH, WANTS, WANTSP
! 185: INTEGER I, IERR, IFST, ILST, J, K, KASE, KS, N2, NN
! 186: DOUBLE PRECISION BIGNUM, COND, CS, DELTA, DUMM, EPS, EST, LNRM,
! 187: $ MU, PROD, PROD1, PROD2, RNRM, SCALE, SMLNUM, SN
! 188: * ..
! 189: * .. Local Arrays ..
! 190: INTEGER ISAVE( 3 )
! 191: DOUBLE PRECISION DUMMY( 1 )
! 192: * ..
! 193: * .. External Functions ..
! 194: LOGICAL LSAME
! 195: DOUBLE PRECISION DDOT, DLAMCH, DLAPY2, DNRM2
! 196: EXTERNAL LSAME, DDOT, DLAMCH, DLAPY2, DNRM2
! 197: * ..
! 198: * .. External Subroutines ..
! 199: EXTERNAL DLACN2, DLACPY, DLAQTR, DTREXC, XERBLA
! 200: * ..
! 201: * .. Intrinsic Functions ..
! 202: INTRINSIC ABS, MAX, SQRT
! 203: * ..
! 204: * .. Executable Statements ..
! 205: *
! 206: * Decode and test the input parameters
! 207: *
! 208: WANTBH = LSAME( JOB, 'B' )
! 209: WANTS = LSAME( JOB, 'E' ) .OR. WANTBH
! 210: WANTSP = LSAME( JOB, 'V' ) .OR. WANTBH
! 211: *
! 212: SOMCON = LSAME( HOWMNY, 'S' )
! 213: *
! 214: INFO = 0
! 215: IF( .NOT.WANTS .AND. .NOT.WANTSP ) THEN
! 216: INFO = -1
! 217: ELSE IF( .NOT.LSAME( HOWMNY, 'A' ) .AND. .NOT.SOMCON ) THEN
! 218: INFO = -2
! 219: ELSE IF( N.LT.0 ) THEN
! 220: INFO = -4
! 221: ELSE IF( LDT.LT.MAX( 1, N ) ) THEN
! 222: INFO = -6
! 223: ELSE IF( LDVL.LT.1 .OR. ( WANTS .AND. LDVL.LT.N ) ) THEN
! 224: INFO = -8
! 225: ELSE IF( LDVR.LT.1 .OR. ( WANTS .AND. LDVR.LT.N ) ) THEN
! 226: INFO = -10
! 227: ELSE
! 228: *
! 229: * Set M to the number of eigenpairs for which condition numbers
! 230: * are required, and test MM.
! 231: *
! 232: IF( SOMCON ) THEN
! 233: M = 0
! 234: PAIR = .FALSE.
! 235: DO 10 K = 1, N
! 236: IF( PAIR ) THEN
! 237: PAIR = .FALSE.
! 238: ELSE
! 239: IF( K.LT.N ) THEN
! 240: IF( T( K+1, K ).EQ.ZERO ) THEN
! 241: IF( SELECT( K ) )
! 242: $ M = M + 1
! 243: ELSE
! 244: PAIR = .TRUE.
! 245: IF( SELECT( K ) .OR. SELECT( K+1 ) )
! 246: $ M = M + 2
! 247: END IF
! 248: ELSE
! 249: IF( SELECT( N ) )
! 250: $ M = M + 1
! 251: END IF
! 252: END IF
! 253: 10 CONTINUE
! 254: ELSE
! 255: M = N
! 256: END IF
! 257: *
! 258: IF( MM.LT.M ) THEN
! 259: INFO = -13
! 260: ELSE IF( LDWORK.LT.1 .OR. ( WANTSP .AND. LDWORK.LT.N ) ) THEN
! 261: INFO = -16
! 262: END IF
! 263: END IF
! 264: IF( INFO.NE.0 ) THEN
! 265: CALL XERBLA( 'DTRSNA', -INFO )
! 266: RETURN
! 267: END IF
! 268: *
! 269: * Quick return if possible
! 270: *
! 271: IF( N.EQ.0 )
! 272: $ RETURN
! 273: *
! 274: IF( N.EQ.1 ) THEN
! 275: IF( SOMCON ) THEN
! 276: IF( .NOT.SELECT( 1 ) )
! 277: $ RETURN
! 278: END IF
! 279: IF( WANTS )
! 280: $ S( 1 ) = ONE
! 281: IF( WANTSP )
! 282: $ SEP( 1 ) = ABS( T( 1, 1 ) )
! 283: RETURN
! 284: END IF
! 285: *
! 286: * Get machine constants
! 287: *
! 288: EPS = DLAMCH( 'P' )
! 289: SMLNUM = DLAMCH( 'S' ) / EPS
! 290: BIGNUM = ONE / SMLNUM
! 291: CALL DLABAD( SMLNUM, BIGNUM )
! 292: *
! 293: KS = 0
! 294: PAIR = .FALSE.
! 295: DO 60 K = 1, N
! 296: *
! 297: * Determine whether T(k,k) begins a 1-by-1 or 2-by-2 block.
! 298: *
! 299: IF( PAIR ) THEN
! 300: PAIR = .FALSE.
! 301: GO TO 60
! 302: ELSE
! 303: IF( K.LT.N )
! 304: $ PAIR = T( K+1, K ).NE.ZERO
! 305: END IF
! 306: *
! 307: * Determine whether condition numbers are required for the k-th
! 308: * eigenpair.
! 309: *
! 310: IF( SOMCON ) THEN
! 311: IF( PAIR ) THEN
! 312: IF( .NOT.SELECT( K ) .AND. .NOT.SELECT( K+1 ) )
! 313: $ GO TO 60
! 314: ELSE
! 315: IF( .NOT.SELECT( K ) )
! 316: $ GO TO 60
! 317: END IF
! 318: END IF
! 319: *
! 320: KS = KS + 1
! 321: *
! 322: IF( WANTS ) THEN
! 323: *
! 324: * Compute the reciprocal condition number of the k-th
! 325: * eigenvalue.
! 326: *
! 327: IF( .NOT.PAIR ) THEN
! 328: *
! 329: * Real eigenvalue.
! 330: *
! 331: PROD = DDOT( N, VR( 1, KS ), 1, VL( 1, KS ), 1 )
! 332: RNRM = DNRM2( N, VR( 1, KS ), 1 )
! 333: LNRM = DNRM2( N, VL( 1, KS ), 1 )
! 334: S( KS ) = ABS( PROD ) / ( RNRM*LNRM )
! 335: ELSE
! 336: *
! 337: * Complex eigenvalue.
! 338: *
! 339: PROD1 = DDOT( N, VR( 1, KS ), 1, VL( 1, KS ), 1 )
! 340: PROD1 = PROD1 + DDOT( N, VR( 1, KS+1 ), 1, VL( 1, KS+1 ),
! 341: $ 1 )
! 342: PROD2 = DDOT( N, VL( 1, KS ), 1, VR( 1, KS+1 ), 1 )
! 343: PROD2 = PROD2 - DDOT( N, VL( 1, KS+1 ), 1, VR( 1, KS ),
! 344: $ 1 )
! 345: RNRM = DLAPY2( DNRM2( N, VR( 1, KS ), 1 ),
! 346: $ DNRM2( N, VR( 1, KS+1 ), 1 ) )
! 347: LNRM = DLAPY2( DNRM2( N, VL( 1, KS ), 1 ),
! 348: $ DNRM2( N, VL( 1, KS+1 ), 1 ) )
! 349: COND = DLAPY2( PROD1, PROD2 ) / ( RNRM*LNRM )
! 350: S( KS ) = COND
! 351: S( KS+1 ) = COND
! 352: END IF
! 353: END IF
! 354: *
! 355: IF( WANTSP ) THEN
! 356: *
! 357: * Estimate the reciprocal condition number of the k-th
! 358: * eigenvector.
! 359: *
! 360: * Copy the matrix T to the array WORK and swap the diagonal
! 361: * block beginning at T(k,k) to the (1,1) position.
! 362: *
! 363: CALL DLACPY( 'Full', N, N, T, LDT, WORK, LDWORK )
! 364: IFST = K
! 365: ILST = 1
! 366: CALL DTREXC( 'No Q', N, WORK, LDWORK, DUMMY, 1, IFST, ILST,
! 367: $ WORK( 1, N+1 ), IERR )
! 368: *
! 369: IF( IERR.EQ.1 .OR. IERR.EQ.2 ) THEN
! 370: *
! 371: * Could not swap because blocks not well separated
! 372: *
! 373: SCALE = ONE
! 374: EST = BIGNUM
! 375: ELSE
! 376: *
! 377: * Reordering successful
! 378: *
! 379: IF( WORK( 2, 1 ).EQ.ZERO ) THEN
! 380: *
! 381: * Form C = T22 - lambda*I in WORK(2:N,2:N).
! 382: *
! 383: DO 20 I = 2, N
! 384: WORK( I, I ) = WORK( I, I ) - WORK( 1, 1 )
! 385: 20 CONTINUE
! 386: N2 = 1
! 387: NN = N - 1
! 388: ELSE
! 389: *
! 390: * Triangularize the 2 by 2 block by unitary
! 391: * transformation U = [ cs i*ss ]
! 392: * [ i*ss cs ].
! 393: * such that the (1,1) position of WORK is complex
! 394: * eigenvalue lambda with positive imaginary part. (2,2)
! 395: * position of WORK is the complex eigenvalue lambda
! 396: * with negative imaginary part.
! 397: *
! 398: MU = SQRT( ABS( WORK( 1, 2 ) ) )*
! 399: $ SQRT( ABS( WORK( 2, 1 ) ) )
! 400: DELTA = DLAPY2( MU, WORK( 2, 1 ) )
! 401: CS = MU / DELTA
! 402: SN = -WORK( 2, 1 ) / DELTA
! 403: *
! 404: * Form
! 405: *
! 406: * C' = WORK(2:N,2:N) + i*[rwork(1) ..... rwork(n-1) ]
! 407: * [ mu ]
! 408: * [ .. ]
! 409: * [ .. ]
! 410: * [ mu ]
! 411: * where C' is conjugate transpose of complex matrix C,
! 412: * and RWORK is stored starting in the N+1-st column of
! 413: * WORK.
! 414: *
! 415: DO 30 J = 3, N
! 416: WORK( 2, J ) = CS*WORK( 2, J )
! 417: WORK( J, J ) = WORK( J, J ) - WORK( 1, 1 )
! 418: 30 CONTINUE
! 419: WORK( 2, 2 ) = ZERO
! 420: *
! 421: WORK( 1, N+1 ) = TWO*MU
! 422: DO 40 I = 2, N - 1
! 423: WORK( I, N+1 ) = SN*WORK( 1, I+1 )
! 424: 40 CONTINUE
! 425: N2 = 2
! 426: NN = 2*( N-1 )
! 427: END IF
! 428: *
! 429: * Estimate norm(inv(C'))
! 430: *
! 431: EST = ZERO
! 432: KASE = 0
! 433: 50 CONTINUE
! 434: CALL DLACN2( NN, WORK( 1, N+2 ), WORK( 1, N+4 ), IWORK,
! 435: $ EST, KASE, ISAVE )
! 436: IF( KASE.NE.0 ) THEN
! 437: IF( KASE.EQ.1 ) THEN
! 438: IF( N2.EQ.1 ) THEN
! 439: *
! 440: * Real eigenvalue: solve C'*x = scale*c.
! 441: *
! 442: CALL DLAQTR( .TRUE., .TRUE., N-1, WORK( 2, 2 ),
! 443: $ LDWORK, DUMMY, DUMM, SCALE,
! 444: $ WORK( 1, N+4 ), WORK( 1, N+6 ),
! 445: $ IERR )
! 446: ELSE
! 447: *
! 448: * Complex eigenvalue: solve
! 449: * C'*(p+iq) = scale*(c+id) in real arithmetic.
! 450: *
! 451: CALL DLAQTR( .TRUE., .FALSE., N-1, WORK( 2, 2 ),
! 452: $ LDWORK, WORK( 1, N+1 ), MU, SCALE,
! 453: $ WORK( 1, N+4 ), WORK( 1, N+6 ),
! 454: $ IERR )
! 455: END IF
! 456: ELSE
! 457: IF( N2.EQ.1 ) THEN
! 458: *
! 459: * Real eigenvalue: solve C*x = scale*c.
! 460: *
! 461: CALL DLAQTR( .FALSE., .TRUE., N-1, WORK( 2, 2 ),
! 462: $ LDWORK, DUMMY, DUMM, SCALE,
! 463: $ WORK( 1, N+4 ), WORK( 1, N+6 ),
! 464: $ IERR )
! 465: ELSE
! 466: *
! 467: * Complex eigenvalue: solve
! 468: * C*(p+iq) = scale*(c+id) in real arithmetic.
! 469: *
! 470: CALL DLAQTR( .FALSE., .FALSE., N-1,
! 471: $ WORK( 2, 2 ), LDWORK,
! 472: $ WORK( 1, N+1 ), MU, SCALE,
! 473: $ WORK( 1, N+4 ), WORK( 1, N+6 ),
! 474: $ IERR )
! 475: *
! 476: END IF
! 477: END IF
! 478: *
! 479: GO TO 50
! 480: END IF
! 481: END IF
! 482: *
! 483: SEP( KS ) = SCALE / MAX( EST, SMLNUM )
! 484: IF( PAIR )
! 485: $ SEP( KS+1 ) = SEP( KS )
! 486: END IF
! 487: *
! 488: IF( PAIR )
! 489: $ KS = KS + 1
! 490: *
! 491: 60 CONTINUE
! 492: RETURN
! 493: *
! 494: * End of DTRSNA
! 495: *
! 496: END
CVSweb interface <joel.bertrand@systella.fr>