File:  [local] / rpl / lapack / lapack / dtrevc.f
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Tue Jan 26 15:22:46 2010 UTC (14 years, 3 months ago) by bertrand
Branches: JKB
CVS tags: start, rpl-4_0_14, rpl-4_0_13, rpl-4_0_12, rpl-4_0_11, rpl-4_0_10


Commit initial.

    1:       SUBROUTINE DTREVC( SIDE, HOWMNY, SELECT, N, T, LDT, VL, LDVL, VR,
    2:      $                   LDVR, MM, M, WORK, INFO )
    3: *
    4: *  -- LAPACK routine (version 3.2) --
    5: *  -- LAPACK is a software package provided by Univ. of Tennessee,    --
    6: *  -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..--
    7: *     November 2006
    8: *
    9: *     .. Scalar Arguments ..
   10:       CHARACTER          HOWMNY, SIDE
   11:       INTEGER            INFO, LDT, LDVL, LDVR, M, MM, N
   12: *     ..
   13: *     .. Array Arguments ..
   14:       LOGICAL            SELECT( * )
   15:       DOUBLE PRECISION   T( LDT, * ), VL( LDVL, * ), VR( LDVR, * ),
   16:      $                   WORK( * )
   17: *     ..
   18: *
   19: *  Purpose
   20: *  =======
   21: *
   22: *  DTREVC computes some or all of the right and/or left eigenvectors of
   23: *  a real upper quasi-triangular matrix T.
   24: *  Matrices of this type are produced by the Schur factorization of
   25: *  a real general matrix:  A = Q*T*Q**T, as computed by DHSEQR.
   26: *  
   27: *  The right eigenvector x and the left eigenvector y of T corresponding
   28: *  to an eigenvalue w are defined by:
   29: *  
   30: *     T*x = w*x,     (y**H)*T = w*(y**H)
   31: *  
   32: *  where y**H denotes the conjugate transpose of y.
   33: *  The eigenvalues are not input to this routine, but are read directly
   34: *  from the diagonal blocks of T.
   35: *  
   36: *  This routine returns the matrices X and/or Y of right and left
   37: *  eigenvectors of T, or the products Q*X and/or Q*Y, where Q is an
   38: *  input matrix.  If Q is the orthogonal factor that reduces a matrix
   39: *  A to Schur form T, then Q*X and Q*Y are the matrices of right and
   40: *  left eigenvectors of A.
   41: *
   42: *  Arguments
   43: *  =========
   44: *
   45: *  SIDE    (input) CHARACTER*1
   46: *          = 'R':  compute right eigenvectors only;
   47: *          = 'L':  compute left eigenvectors only;
   48: *          = 'B':  compute both right and left eigenvectors.
   49: *
   50: *  HOWMNY  (input) CHARACTER*1
   51: *          = 'A':  compute all right and/or left eigenvectors;
   52: *          = 'B':  compute all right and/or left eigenvectors,
   53: *                  backtransformed by the matrices in VR and/or VL;
   54: *          = 'S':  compute selected right and/or left eigenvectors,
   55: *                  as indicated by the logical array SELECT.
   56: *
   57: *  SELECT  (input/output) LOGICAL array, dimension (N)
   58: *          If HOWMNY = 'S', SELECT specifies the eigenvectors to be
   59: *          computed.
   60: *          If w(j) is a real eigenvalue, the corresponding real
   61: *          eigenvector is computed if SELECT(j) is .TRUE..
   62: *          If w(j) and w(j+1) are the real and imaginary parts of a
   63: *          complex eigenvalue, the corresponding complex eigenvector is
   64: *          computed if either SELECT(j) or SELECT(j+1) is .TRUE., and
   65: *          on exit SELECT(j) is set to .TRUE. and SELECT(j+1) is set to
   66: *          .FALSE..
   67: *          Not referenced if HOWMNY = 'A' or 'B'.
   68: *
   69: *  N       (input) INTEGER
   70: *          The order of the matrix T. N >= 0.
   71: *
   72: *  T       (input) DOUBLE PRECISION array, dimension (LDT,N)
   73: *          The upper quasi-triangular matrix T in Schur canonical form.
   74: *
   75: *  LDT     (input) INTEGER
   76: *          The leading dimension of the array T. LDT >= max(1,N).
   77: *
   78: *  VL      (input/output) DOUBLE PRECISION array, dimension (LDVL,MM)
   79: *          On entry, if SIDE = 'L' or 'B' and HOWMNY = 'B', VL must
   80: *          contain an N-by-N matrix Q (usually the orthogonal matrix Q
   81: *          of Schur vectors returned by DHSEQR).
   82: *          On exit, if SIDE = 'L' or 'B', VL contains:
   83: *          if HOWMNY = 'A', the matrix Y of left eigenvectors of T;
   84: *          if HOWMNY = 'B', the matrix Q*Y;
   85: *          if HOWMNY = 'S', the left eigenvectors of T specified by
   86: *                           SELECT, stored consecutively in the columns
   87: *                           of VL, in the same order as their
   88: *                           eigenvalues.
   89: *          A complex eigenvector corresponding to a complex eigenvalue
   90: *          is stored in two consecutive columns, the first holding the
   91: *          real part, and the second the imaginary part.
   92: *          Not referenced if SIDE = 'R'.
   93: *
   94: *  LDVL    (input) INTEGER
   95: *          The leading dimension of the array VL.  LDVL >= 1, and if
   96: *          SIDE = 'L' or 'B', LDVL >= N.
   97: *
   98: *  VR      (input/output) DOUBLE PRECISION array, dimension (LDVR,MM)
   99: *          On entry, if SIDE = 'R' or 'B' and HOWMNY = 'B', VR must
  100: *          contain an N-by-N matrix Q (usually the orthogonal matrix Q
  101: *          of Schur vectors returned by DHSEQR).
  102: *          On exit, if SIDE = 'R' or 'B', VR contains:
  103: *          if HOWMNY = 'A', the matrix X of right eigenvectors of T;
  104: *          if HOWMNY = 'B', the matrix Q*X;
  105: *          if HOWMNY = 'S', the right eigenvectors of T specified by
  106: *                           SELECT, stored consecutively in the columns
  107: *                           of VR, in the same order as their
  108: *                           eigenvalues.
  109: *          A complex eigenvector corresponding to a complex eigenvalue
  110: *          is stored in two consecutive columns, the first holding the
  111: *          real part and the second the imaginary part.
  112: *          Not referenced if SIDE = 'L'.
  113: *
  114: *  LDVR    (input) INTEGER
  115: *          The leading dimension of the array VR.  LDVR >= 1, and if
  116: *          SIDE = 'R' or 'B', LDVR >= N.
  117: *
  118: *  MM      (input) INTEGER
  119: *          The number of columns in the arrays VL and/or VR. MM >= M.
  120: *
  121: *  M       (output) INTEGER
  122: *          The number of columns in the arrays VL and/or VR actually
  123: *          used to store the eigenvectors.
  124: *          If HOWMNY = 'A' or 'B', M is set to N.
  125: *          Each selected real eigenvector occupies one column and each
  126: *          selected complex eigenvector occupies two columns.
  127: *
  128: *  WORK    (workspace) DOUBLE PRECISION array, dimension (3*N)
  129: *
  130: *  INFO    (output) INTEGER
  131: *          = 0:  successful exit
  132: *          < 0:  if INFO = -i, the i-th argument had an illegal value
  133: *
  134: *  Further Details
  135: *  ===============
  136: *
  137: *  The algorithm used in this program is basically backward (forward)
  138: *  substitution, with scaling to make the the code robust against
  139: *  possible overflow.
  140: *
  141: *  Each eigenvector is normalized so that the element of largest
  142: *  magnitude has magnitude 1; here the magnitude of a complex number
  143: *  (x,y) is taken to be |x| + |y|.
  144: *
  145: *  =====================================================================
  146: *
  147: *     .. Parameters ..
  148:       DOUBLE PRECISION   ZERO, ONE
  149:       PARAMETER          ( ZERO = 0.0D+0, ONE = 1.0D+0 )
  150: *     ..
  151: *     .. Local Scalars ..
  152:       LOGICAL            ALLV, BOTHV, LEFTV, OVER, PAIR, RIGHTV, SOMEV
  153:       INTEGER            I, IERR, II, IP, IS, J, J1, J2, JNXT, K, KI, N2
  154:       DOUBLE PRECISION   BETA, BIGNUM, EMAX, OVFL, REC, REMAX, SCALE,
  155:      $                   SMIN, SMLNUM, ULP, UNFL, VCRIT, VMAX, WI, WR,
  156:      $                   XNORM
  157: *     ..
  158: *     .. External Functions ..
  159:       LOGICAL            LSAME
  160:       INTEGER            IDAMAX
  161:       DOUBLE PRECISION   DDOT, DLAMCH
  162:       EXTERNAL           LSAME, IDAMAX, DDOT, DLAMCH
  163: *     ..
  164: *     .. External Subroutines ..
  165:       EXTERNAL           DAXPY, DCOPY, DGEMV, DLALN2, DSCAL, XERBLA
  166: *     ..
  167: *     .. Intrinsic Functions ..
  168:       INTRINSIC          ABS, MAX, SQRT
  169: *     ..
  170: *     .. Local Arrays ..
  171:       DOUBLE PRECISION   X( 2, 2 )
  172: *     ..
  173: *     .. Executable Statements ..
  174: *
  175: *     Decode and test the input parameters
  176: *
  177:       BOTHV = LSAME( SIDE, 'B' )
  178:       RIGHTV = LSAME( SIDE, 'R' ) .OR. BOTHV
  179:       LEFTV = LSAME( SIDE, 'L' ) .OR. BOTHV
  180: *
  181:       ALLV = LSAME( HOWMNY, 'A' )
  182:       OVER = LSAME( HOWMNY, 'B' )
  183:       SOMEV = LSAME( HOWMNY, 'S' )
  184: *
  185:       INFO = 0
  186:       IF( .NOT.RIGHTV .AND. .NOT.LEFTV ) THEN
  187:          INFO = -1
  188:       ELSE IF( .NOT.ALLV .AND. .NOT.OVER .AND. .NOT.SOMEV ) THEN
  189:          INFO = -2
  190:       ELSE IF( N.LT.0 ) THEN
  191:          INFO = -4
  192:       ELSE IF( LDT.LT.MAX( 1, N ) ) THEN
  193:          INFO = -6
  194:       ELSE IF( LDVL.LT.1 .OR. ( LEFTV .AND. LDVL.LT.N ) ) THEN
  195:          INFO = -8
  196:       ELSE IF( LDVR.LT.1 .OR. ( RIGHTV .AND. LDVR.LT.N ) ) THEN
  197:          INFO = -10
  198:       ELSE
  199: *
  200: *        Set M to the number of columns required to store the selected
  201: *        eigenvectors, standardize the array SELECT if necessary, and
  202: *        test MM.
  203: *
  204:          IF( SOMEV ) THEN
  205:             M = 0
  206:             PAIR = .FALSE.
  207:             DO 10 J = 1, N
  208:                IF( PAIR ) THEN
  209:                   PAIR = .FALSE.
  210:                   SELECT( J ) = .FALSE.
  211:                ELSE
  212:                   IF( J.LT.N ) THEN
  213:                      IF( T( J+1, J ).EQ.ZERO ) THEN
  214:                         IF( SELECT( J ) )
  215:      $                     M = M + 1
  216:                      ELSE
  217:                         PAIR = .TRUE.
  218:                         IF( SELECT( J ) .OR. SELECT( J+1 ) ) THEN
  219:                            SELECT( J ) = .TRUE.
  220:                            M = M + 2
  221:                         END IF
  222:                      END IF
  223:                   ELSE
  224:                      IF( SELECT( N ) )
  225:      $                  M = M + 1
  226:                   END IF
  227:                END IF
  228:    10       CONTINUE
  229:          ELSE
  230:             M = N
  231:          END IF
  232: *
  233:          IF( MM.LT.M ) THEN
  234:             INFO = -11
  235:          END IF
  236:       END IF
  237:       IF( INFO.NE.0 ) THEN
  238:          CALL XERBLA( 'DTREVC', -INFO )
  239:          RETURN
  240:       END IF
  241: *
  242: *     Quick return if possible.
  243: *
  244:       IF( N.EQ.0 )
  245:      $   RETURN
  246: *
  247: *     Set the constants to control overflow.
  248: *
  249:       UNFL = DLAMCH( 'Safe minimum' )
  250:       OVFL = ONE / UNFL
  251:       CALL DLABAD( UNFL, OVFL )
  252:       ULP = DLAMCH( 'Precision' )
  253:       SMLNUM = UNFL*( N / ULP )
  254:       BIGNUM = ( ONE-ULP ) / SMLNUM
  255: *
  256: *     Compute 1-norm of each column of strictly upper triangular
  257: *     part of T to control overflow in triangular solver.
  258: *
  259:       WORK( 1 ) = ZERO
  260:       DO 30 J = 2, N
  261:          WORK( J ) = ZERO
  262:          DO 20 I = 1, J - 1
  263:             WORK( J ) = WORK( J ) + ABS( T( I, J ) )
  264:    20    CONTINUE
  265:    30 CONTINUE
  266: *
  267: *     Index IP is used to specify the real or complex eigenvalue:
  268: *       IP = 0, real eigenvalue,
  269: *            1, first of conjugate complex pair: (wr,wi)
  270: *           -1, second of conjugate complex pair: (wr,wi)
  271: *
  272:       N2 = 2*N
  273: *
  274:       IF( RIGHTV ) THEN
  275: *
  276: *        Compute right eigenvectors.
  277: *
  278:          IP = 0
  279:          IS = M
  280:          DO 140 KI = N, 1, -1
  281: *
  282:             IF( IP.EQ.1 )
  283:      $         GO TO 130
  284:             IF( KI.EQ.1 )
  285:      $         GO TO 40
  286:             IF( T( KI, KI-1 ).EQ.ZERO )
  287:      $         GO TO 40
  288:             IP = -1
  289: *
  290:    40       CONTINUE
  291:             IF( SOMEV ) THEN
  292:                IF( IP.EQ.0 ) THEN
  293:                   IF( .NOT.SELECT( KI ) )
  294:      $               GO TO 130
  295:                ELSE
  296:                   IF( .NOT.SELECT( KI-1 ) )
  297:      $               GO TO 130
  298:                END IF
  299:             END IF
  300: *
  301: *           Compute the KI-th eigenvalue (WR,WI).
  302: *
  303:             WR = T( KI, KI )
  304:             WI = ZERO
  305:             IF( IP.NE.0 )
  306:      $         WI = SQRT( ABS( T( KI, KI-1 ) ) )*
  307:      $              SQRT( ABS( T( KI-1, KI ) ) )
  308:             SMIN = MAX( ULP*( ABS( WR )+ABS( WI ) ), SMLNUM )
  309: *
  310:             IF( IP.EQ.0 ) THEN
  311: *
  312: *              Real right eigenvector
  313: *
  314:                WORK( KI+N ) = ONE
  315: *
  316: *              Form right-hand side
  317: *
  318:                DO 50 K = 1, KI - 1
  319:                   WORK( K+N ) = -T( K, KI )
  320:    50          CONTINUE
  321: *
  322: *              Solve the upper quasi-triangular system:
  323: *                 (T(1:KI-1,1:KI-1) - WR)*X = SCALE*WORK.
  324: *
  325:                JNXT = KI - 1
  326:                DO 60 J = KI - 1, 1, -1
  327:                   IF( J.GT.JNXT )
  328:      $               GO TO 60
  329:                   J1 = J
  330:                   J2 = J
  331:                   JNXT = J - 1
  332:                   IF( J.GT.1 ) THEN
  333:                      IF( T( J, J-1 ).NE.ZERO ) THEN
  334:                         J1 = J - 1
  335:                         JNXT = J - 2
  336:                      END IF
  337:                   END IF
  338: *
  339:                   IF( J1.EQ.J2 ) THEN
  340: *
  341: *                    1-by-1 diagonal block
  342: *
  343:                      CALL DLALN2( .FALSE., 1, 1, SMIN, ONE, T( J, J ),
  344:      $                            LDT, ONE, ONE, WORK( J+N ), N, WR,
  345:      $                            ZERO, X, 2, SCALE, XNORM, IERR )
  346: *
  347: *                    Scale X(1,1) to avoid overflow when updating
  348: *                    the right-hand side.
  349: *
  350:                      IF( XNORM.GT.ONE ) THEN
  351:                         IF( WORK( J ).GT.BIGNUM / XNORM ) THEN
  352:                            X( 1, 1 ) = X( 1, 1 ) / XNORM
  353:                            SCALE = SCALE / XNORM
  354:                         END IF
  355:                      END IF
  356: *
  357: *                    Scale if necessary
  358: *
  359:                      IF( SCALE.NE.ONE )
  360:      $                  CALL DSCAL( KI, SCALE, WORK( 1+N ), 1 )
  361:                      WORK( J+N ) = X( 1, 1 )
  362: *
  363: *                    Update right-hand side
  364: *
  365:                      CALL DAXPY( J-1, -X( 1, 1 ), T( 1, J ), 1,
  366:      $                           WORK( 1+N ), 1 )
  367: *
  368:                   ELSE
  369: *
  370: *                    2-by-2 diagonal block
  371: *
  372:                      CALL DLALN2( .FALSE., 2, 1, SMIN, ONE,
  373:      $                            T( J-1, J-1 ), LDT, ONE, ONE,
  374:      $                            WORK( J-1+N ), N, WR, ZERO, X, 2,
  375:      $                            SCALE, XNORM, IERR )
  376: *
  377: *                    Scale X(1,1) and X(2,1) to avoid overflow when
  378: *                    updating the right-hand side.
  379: *
  380:                      IF( XNORM.GT.ONE ) THEN
  381:                         BETA = MAX( WORK( J-1 ), WORK( J ) )
  382:                         IF( BETA.GT.BIGNUM / XNORM ) THEN
  383:                            X( 1, 1 ) = X( 1, 1 ) / XNORM
  384:                            X( 2, 1 ) = X( 2, 1 ) / XNORM
  385:                            SCALE = SCALE / XNORM
  386:                         END IF
  387:                      END IF
  388: *
  389: *                    Scale if necessary
  390: *
  391:                      IF( SCALE.NE.ONE )
  392:      $                  CALL DSCAL( KI, SCALE, WORK( 1+N ), 1 )
  393:                      WORK( J-1+N ) = X( 1, 1 )
  394:                      WORK( J+N ) = X( 2, 1 )
  395: *
  396: *                    Update right-hand side
  397: *
  398:                      CALL DAXPY( J-2, -X( 1, 1 ), T( 1, J-1 ), 1,
  399:      $                           WORK( 1+N ), 1 )
  400:                      CALL DAXPY( J-2, -X( 2, 1 ), T( 1, J ), 1,
  401:      $                           WORK( 1+N ), 1 )
  402:                   END IF
  403:    60          CONTINUE
  404: *
  405: *              Copy the vector x or Q*x to VR and normalize.
  406: *
  407:                IF( .NOT.OVER ) THEN
  408:                   CALL DCOPY( KI, WORK( 1+N ), 1, VR( 1, IS ), 1 )
  409: *
  410:                   II = IDAMAX( KI, VR( 1, IS ), 1 )
  411:                   REMAX = ONE / ABS( VR( II, IS ) )
  412:                   CALL DSCAL( KI, REMAX, VR( 1, IS ), 1 )
  413: *
  414:                   DO 70 K = KI + 1, N
  415:                      VR( K, IS ) = ZERO
  416:    70             CONTINUE
  417:                ELSE
  418:                   IF( KI.GT.1 )
  419:      $               CALL DGEMV( 'N', N, KI-1, ONE, VR, LDVR,
  420:      $                           WORK( 1+N ), 1, WORK( KI+N ),
  421:      $                           VR( 1, KI ), 1 )
  422: *
  423:                   II = IDAMAX( N, VR( 1, KI ), 1 )
  424:                   REMAX = ONE / ABS( VR( II, KI ) )
  425:                   CALL DSCAL( N, REMAX, VR( 1, KI ), 1 )
  426:                END IF
  427: *
  428:             ELSE
  429: *
  430: *              Complex right eigenvector.
  431: *
  432: *              Initial solve
  433: *                [ (T(KI-1,KI-1) T(KI-1,KI) ) - (WR + I* WI)]*X = 0.
  434: *                [ (T(KI,KI-1)   T(KI,KI)   )               ]
  435: *
  436:                IF( ABS( T( KI-1, KI ) ).GE.ABS( T( KI, KI-1 ) ) ) THEN
  437:                   WORK( KI-1+N ) = ONE
  438:                   WORK( KI+N2 ) = WI / T( KI-1, KI )
  439:                ELSE
  440:                   WORK( KI-1+N ) = -WI / T( KI, KI-1 )
  441:                   WORK( KI+N2 ) = ONE
  442:                END IF
  443:                WORK( KI+N ) = ZERO
  444:                WORK( KI-1+N2 ) = ZERO
  445: *
  446: *              Form right-hand side
  447: *
  448:                DO 80 K = 1, KI - 2
  449:                   WORK( K+N ) = -WORK( KI-1+N )*T( K, KI-1 )
  450:                   WORK( K+N2 ) = -WORK( KI+N2 )*T( K, KI )
  451:    80          CONTINUE
  452: *
  453: *              Solve upper quasi-triangular system:
  454: *              (T(1:KI-2,1:KI-2) - (WR+i*WI))*X = SCALE*(WORK+i*WORK2)
  455: *
  456:                JNXT = KI - 2
  457:                DO 90 J = KI - 2, 1, -1
  458:                   IF( J.GT.JNXT )
  459:      $               GO TO 90
  460:                   J1 = J
  461:                   J2 = J
  462:                   JNXT = J - 1
  463:                   IF( J.GT.1 ) THEN
  464:                      IF( T( J, J-1 ).NE.ZERO ) THEN
  465:                         J1 = J - 1
  466:                         JNXT = J - 2
  467:                      END IF
  468:                   END IF
  469: *
  470:                   IF( J1.EQ.J2 ) THEN
  471: *
  472: *                    1-by-1 diagonal block
  473: *
  474:                      CALL DLALN2( .FALSE., 1, 2, SMIN, ONE, T( J, J ),
  475:      $                            LDT, ONE, ONE, WORK( J+N ), N, WR, WI,
  476:      $                            X, 2, SCALE, XNORM, IERR )
  477: *
  478: *                    Scale X(1,1) and X(1,2) to avoid overflow when
  479: *                    updating the right-hand side.
  480: *
  481:                      IF( XNORM.GT.ONE ) THEN
  482:                         IF( WORK( J ).GT.BIGNUM / XNORM ) THEN
  483:                            X( 1, 1 ) = X( 1, 1 ) / XNORM
  484:                            X( 1, 2 ) = X( 1, 2 ) / XNORM
  485:                            SCALE = SCALE / XNORM
  486:                         END IF
  487:                      END IF
  488: *
  489: *                    Scale if necessary
  490: *
  491:                      IF( SCALE.NE.ONE ) THEN
  492:                         CALL DSCAL( KI, SCALE, WORK( 1+N ), 1 )
  493:                         CALL DSCAL( KI, SCALE, WORK( 1+N2 ), 1 )
  494:                      END IF
  495:                      WORK( J+N ) = X( 1, 1 )
  496:                      WORK( J+N2 ) = X( 1, 2 )
  497: *
  498: *                    Update the right-hand side
  499: *
  500:                      CALL DAXPY( J-1, -X( 1, 1 ), T( 1, J ), 1,
  501:      $                           WORK( 1+N ), 1 )
  502:                      CALL DAXPY( J-1, -X( 1, 2 ), T( 1, J ), 1,
  503:      $                           WORK( 1+N2 ), 1 )
  504: *
  505:                   ELSE
  506: *
  507: *                    2-by-2 diagonal block
  508: *
  509:                      CALL DLALN2( .FALSE., 2, 2, SMIN, ONE,
  510:      $                            T( J-1, J-1 ), LDT, ONE, ONE,
  511:      $                            WORK( J-1+N ), N, WR, WI, X, 2, SCALE,
  512:      $                            XNORM, IERR )
  513: *
  514: *                    Scale X to avoid overflow when updating
  515: *                    the right-hand side.
  516: *
  517:                      IF( XNORM.GT.ONE ) THEN
  518:                         BETA = MAX( WORK( J-1 ), WORK( J ) )
  519:                         IF( BETA.GT.BIGNUM / XNORM ) THEN
  520:                            REC = ONE / XNORM
  521:                            X( 1, 1 ) = X( 1, 1 )*REC
  522:                            X( 1, 2 ) = X( 1, 2 )*REC
  523:                            X( 2, 1 ) = X( 2, 1 )*REC
  524:                            X( 2, 2 ) = X( 2, 2 )*REC
  525:                            SCALE = SCALE*REC
  526:                         END IF
  527:                      END IF
  528: *
  529: *                    Scale if necessary
  530: *
  531:                      IF( SCALE.NE.ONE ) THEN
  532:                         CALL DSCAL( KI, SCALE, WORK( 1+N ), 1 )
  533:                         CALL DSCAL( KI, SCALE, WORK( 1+N2 ), 1 )
  534:                      END IF
  535:                      WORK( J-1+N ) = X( 1, 1 )
  536:                      WORK( J+N ) = X( 2, 1 )
  537:                      WORK( J-1+N2 ) = X( 1, 2 )
  538:                      WORK( J+N2 ) = X( 2, 2 )
  539: *
  540: *                    Update the right-hand side
  541: *
  542:                      CALL DAXPY( J-2, -X( 1, 1 ), T( 1, J-1 ), 1,
  543:      $                           WORK( 1+N ), 1 )
  544:                      CALL DAXPY( J-2, -X( 2, 1 ), T( 1, J ), 1,
  545:      $                           WORK( 1+N ), 1 )
  546:                      CALL DAXPY( J-2, -X( 1, 2 ), T( 1, J-1 ), 1,
  547:      $                           WORK( 1+N2 ), 1 )
  548:                      CALL DAXPY( J-2, -X( 2, 2 ), T( 1, J ), 1,
  549:      $                           WORK( 1+N2 ), 1 )
  550:                   END IF
  551:    90          CONTINUE
  552: *
  553: *              Copy the vector x or Q*x to VR and normalize.
  554: *
  555:                IF( .NOT.OVER ) THEN
  556:                   CALL DCOPY( KI, WORK( 1+N ), 1, VR( 1, IS-1 ), 1 )
  557:                   CALL DCOPY( KI, WORK( 1+N2 ), 1, VR( 1, IS ), 1 )
  558: *
  559:                   EMAX = ZERO
  560:                   DO 100 K = 1, KI
  561:                      EMAX = MAX( EMAX, ABS( VR( K, IS-1 ) )+
  562:      $                      ABS( VR( K, IS ) ) )
  563:   100             CONTINUE
  564: *
  565:                   REMAX = ONE / EMAX
  566:                   CALL DSCAL( KI, REMAX, VR( 1, IS-1 ), 1 )
  567:                   CALL DSCAL( KI, REMAX, VR( 1, IS ), 1 )
  568: *
  569:                   DO 110 K = KI + 1, N
  570:                      VR( K, IS-1 ) = ZERO
  571:                      VR( K, IS ) = ZERO
  572:   110             CONTINUE
  573: *
  574:                ELSE
  575: *
  576:                   IF( KI.GT.2 ) THEN
  577:                      CALL DGEMV( 'N', N, KI-2, ONE, VR, LDVR,
  578:      $                           WORK( 1+N ), 1, WORK( KI-1+N ),
  579:      $                           VR( 1, KI-1 ), 1 )
  580:                      CALL DGEMV( 'N', N, KI-2, ONE, VR, LDVR,
  581:      $                           WORK( 1+N2 ), 1, WORK( KI+N2 ),
  582:      $                           VR( 1, KI ), 1 )
  583:                   ELSE
  584:                      CALL DSCAL( N, WORK( KI-1+N ), VR( 1, KI-1 ), 1 )
  585:                      CALL DSCAL( N, WORK( KI+N2 ), VR( 1, KI ), 1 )
  586:                   END IF
  587: *
  588:                   EMAX = ZERO
  589:                   DO 120 K = 1, N
  590:                      EMAX = MAX( EMAX, ABS( VR( K, KI-1 ) )+
  591:      $                      ABS( VR( K, KI ) ) )
  592:   120             CONTINUE
  593:                   REMAX = ONE / EMAX
  594:                   CALL DSCAL( N, REMAX, VR( 1, KI-1 ), 1 )
  595:                   CALL DSCAL( N, REMAX, VR( 1, KI ), 1 )
  596:                END IF
  597:             END IF
  598: *
  599:             IS = IS - 1
  600:             IF( IP.NE.0 )
  601:      $         IS = IS - 1
  602:   130       CONTINUE
  603:             IF( IP.EQ.1 )
  604:      $         IP = 0
  605:             IF( IP.EQ.-1 )
  606:      $         IP = 1
  607:   140    CONTINUE
  608:       END IF
  609: *
  610:       IF( LEFTV ) THEN
  611: *
  612: *        Compute left eigenvectors.
  613: *
  614:          IP = 0
  615:          IS = 1
  616:          DO 260 KI = 1, N
  617: *
  618:             IF( IP.EQ.-1 )
  619:      $         GO TO 250
  620:             IF( KI.EQ.N )
  621:      $         GO TO 150
  622:             IF( T( KI+1, KI ).EQ.ZERO )
  623:      $         GO TO 150
  624:             IP = 1
  625: *
  626:   150       CONTINUE
  627:             IF( SOMEV ) THEN
  628:                IF( .NOT.SELECT( KI ) )
  629:      $            GO TO 250
  630:             END IF
  631: *
  632: *           Compute the KI-th eigenvalue (WR,WI).
  633: *
  634:             WR = T( KI, KI )
  635:             WI = ZERO
  636:             IF( IP.NE.0 )
  637:      $         WI = SQRT( ABS( T( KI, KI+1 ) ) )*
  638:      $              SQRT( ABS( T( KI+1, KI ) ) )
  639:             SMIN = MAX( ULP*( ABS( WR )+ABS( WI ) ), SMLNUM )
  640: *
  641:             IF( IP.EQ.0 ) THEN
  642: *
  643: *              Real left eigenvector.
  644: *
  645:                WORK( KI+N ) = ONE
  646: *
  647: *              Form right-hand side
  648: *
  649:                DO 160 K = KI + 1, N
  650:                   WORK( K+N ) = -T( KI, K )
  651:   160          CONTINUE
  652: *
  653: *              Solve the quasi-triangular system:
  654: *                 (T(KI+1:N,KI+1:N) - WR)'*X = SCALE*WORK
  655: *
  656:                VMAX = ONE
  657:                VCRIT = BIGNUM
  658: *
  659:                JNXT = KI + 1
  660:                DO 170 J = KI + 1, N
  661:                   IF( J.LT.JNXT )
  662:      $               GO TO 170
  663:                   J1 = J
  664:                   J2 = J
  665:                   JNXT = J + 1
  666:                   IF( J.LT.N ) THEN
  667:                      IF( T( J+1, J ).NE.ZERO ) THEN
  668:                         J2 = J + 1
  669:                         JNXT = J + 2
  670:                      END IF
  671:                   END IF
  672: *
  673:                   IF( J1.EQ.J2 ) THEN
  674: *
  675: *                    1-by-1 diagonal block
  676: *
  677: *                    Scale if necessary to avoid overflow when forming
  678: *                    the right-hand side.
  679: *
  680:                      IF( WORK( J ).GT.VCRIT ) THEN
  681:                         REC = ONE / VMAX
  682:                         CALL DSCAL( N-KI+1, REC, WORK( KI+N ), 1 )
  683:                         VMAX = ONE
  684:                         VCRIT = BIGNUM
  685:                      END IF
  686: *
  687:                      WORK( J+N ) = WORK( J+N ) -
  688:      $                             DDOT( J-KI-1, T( KI+1, J ), 1,
  689:      $                             WORK( KI+1+N ), 1 )
  690: *
  691: *                    Solve (T(J,J)-WR)'*X = WORK
  692: *
  693:                      CALL DLALN2( .FALSE., 1, 1, SMIN, ONE, T( J, J ),
  694:      $                            LDT, ONE, ONE, WORK( J+N ), N, WR,
  695:      $                            ZERO, X, 2, SCALE, XNORM, IERR )
  696: *
  697: *                    Scale if necessary
  698: *
  699:                      IF( SCALE.NE.ONE )
  700:      $                  CALL DSCAL( N-KI+1, SCALE, WORK( KI+N ), 1 )
  701:                      WORK( J+N ) = X( 1, 1 )
  702:                      VMAX = MAX( ABS( WORK( J+N ) ), VMAX )
  703:                      VCRIT = BIGNUM / VMAX
  704: *
  705:                   ELSE
  706: *
  707: *                    2-by-2 diagonal block
  708: *
  709: *                    Scale if necessary to avoid overflow when forming
  710: *                    the right-hand side.
  711: *
  712:                      BETA = MAX( WORK( J ), WORK( J+1 ) )
  713:                      IF( BETA.GT.VCRIT ) THEN
  714:                         REC = ONE / VMAX
  715:                         CALL DSCAL( N-KI+1, REC, WORK( KI+N ), 1 )
  716:                         VMAX = ONE
  717:                         VCRIT = BIGNUM
  718:                      END IF
  719: *
  720:                      WORK( J+N ) = WORK( J+N ) -
  721:      $                             DDOT( J-KI-1, T( KI+1, J ), 1,
  722:      $                             WORK( KI+1+N ), 1 )
  723: *
  724:                      WORK( J+1+N ) = WORK( J+1+N ) -
  725:      $                               DDOT( J-KI-1, T( KI+1, J+1 ), 1,
  726:      $                               WORK( KI+1+N ), 1 )
  727: *
  728: *                    Solve
  729: *                      [T(J,J)-WR   T(J,J+1)     ]'* X = SCALE*( WORK1 )
  730: *                      [T(J+1,J)    T(J+1,J+1)-WR]             ( WORK2 )
  731: *
  732:                      CALL DLALN2( .TRUE., 2, 1, SMIN, ONE, T( J, J ),
  733:      $                            LDT, ONE, ONE, WORK( J+N ), N, WR,
  734:      $                            ZERO, X, 2, SCALE, XNORM, IERR )
  735: *
  736: *                    Scale if necessary
  737: *
  738:                      IF( SCALE.NE.ONE )
  739:      $                  CALL DSCAL( N-KI+1, SCALE, WORK( KI+N ), 1 )
  740:                      WORK( J+N ) = X( 1, 1 )
  741:                      WORK( J+1+N ) = X( 2, 1 )
  742: *
  743:                      VMAX = MAX( ABS( WORK( J+N ) ),
  744:      $                      ABS( WORK( J+1+N ) ), VMAX )
  745:                      VCRIT = BIGNUM / VMAX
  746: *
  747:                   END IF
  748:   170          CONTINUE
  749: *
  750: *              Copy the vector x or Q*x to VL and normalize.
  751: *
  752:                IF( .NOT.OVER ) THEN
  753:                   CALL DCOPY( N-KI+1, WORK( KI+N ), 1, VL( KI, IS ), 1 )
  754: *
  755:                   II = IDAMAX( N-KI+1, VL( KI, IS ), 1 ) + KI - 1
  756:                   REMAX = ONE / ABS( VL( II, IS ) )
  757:                   CALL DSCAL( N-KI+1, REMAX, VL( KI, IS ), 1 )
  758: *
  759:                   DO 180 K = 1, KI - 1
  760:                      VL( K, IS ) = ZERO
  761:   180             CONTINUE
  762: *
  763:                ELSE
  764: *
  765:                   IF( KI.LT.N )
  766:      $               CALL DGEMV( 'N', N, N-KI, ONE, VL( 1, KI+1 ), LDVL,
  767:      $                           WORK( KI+1+N ), 1, WORK( KI+N ),
  768:      $                           VL( 1, KI ), 1 )
  769: *
  770:                   II = IDAMAX( N, VL( 1, KI ), 1 )
  771:                   REMAX = ONE / ABS( VL( II, KI ) )
  772:                   CALL DSCAL( N, REMAX, VL( 1, KI ), 1 )
  773: *
  774:                END IF
  775: *
  776:             ELSE
  777: *
  778: *              Complex left eigenvector.
  779: *
  780: *               Initial solve:
  781: *                 ((T(KI,KI)    T(KI,KI+1) )' - (WR - I* WI))*X = 0.
  782: *                 ((T(KI+1,KI) T(KI+1,KI+1))                )
  783: *
  784:                IF( ABS( T( KI, KI+1 ) ).GE.ABS( T( KI+1, KI ) ) ) THEN
  785:                   WORK( KI+N ) = WI / T( KI, KI+1 )
  786:                   WORK( KI+1+N2 ) = ONE
  787:                ELSE
  788:                   WORK( KI+N ) = ONE
  789:                   WORK( KI+1+N2 ) = -WI / T( KI+1, KI )
  790:                END IF
  791:                WORK( KI+1+N ) = ZERO
  792:                WORK( KI+N2 ) = ZERO
  793: *
  794: *              Form right-hand side
  795: *
  796:                DO 190 K = KI + 2, N
  797:                   WORK( K+N ) = -WORK( KI+N )*T( KI, K )
  798:                   WORK( K+N2 ) = -WORK( KI+1+N2 )*T( KI+1, K )
  799:   190          CONTINUE
  800: *
  801: *              Solve complex quasi-triangular system:
  802: *              ( T(KI+2,N:KI+2,N) - (WR-i*WI) )*X = WORK1+i*WORK2
  803: *
  804:                VMAX = ONE
  805:                VCRIT = BIGNUM
  806: *
  807:                JNXT = KI + 2
  808:                DO 200 J = KI + 2, N
  809:                   IF( J.LT.JNXT )
  810:      $               GO TO 200
  811:                   J1 = J
  812:                   J2 = J
  813:                   JNXT = J + 1
  814:                   IF( J.LT.N ) THEN
  815:                      IF( T( J+1, J ).NE.ZERO ) THEN
  816:                         J2 = J + 1
  817:                         JNXT = J + 2
  818:                      END IF
  819:                   END IF
  820: *
  821:                   IF( J1.EQ.J2 ) THEN
  822: *
  823: *                    1-by-1 diagonal block
  824: *
  825: *                    Scale if necessary to avoid overflow when
  826: *                    forming the right-hand side elements.
  827: *
  828:                      IF( WORK( J ).GT.VCRIT ) THEN
  829:                         REC = ONE / VMAX
  830:                         CALL DSCAL( N-KI+1, REC, WORK( KI+N ), 1 )
  831:                         CALL DSCAL( N-KI+1, REC, WORK( KI+N2 ), 1 )
  832:                         VMAX = ONE
  833:                         VCRIT = BIGNUM
  834:                      END IF
  835: *
  836:                      WORK( J+N ) = WORK( J+N ) -
  837:      $                             DDOT( J-KI-2, T( KI+2, J ), 1,
  838:      $                             WORK( KI+2+N ), 1 )
  839:                      WORK( J+N2 ) = WORK( J+N2 ) -
  840:      $                              DDOT( J-KI-2, T( KI+2, J ), 1,
  841:      $                              WORK( KI+2+N2 ), 1 )
  842: *
  843: *                    Solve (T(J,J)-(WR-i*WI))*(X11+i*X12)= WK+I*WK2
  844: *
  845:                      CALL DLALN2( .FALSE., 1, 2, SMIN, ONE, T( J, J ),
  846:      $                            LDT, ONE, ONE, WORK( J+N ), N, WR,
  847:      $                            -WI, X, 2, SCALE, XNORM, IERR )
  848: *
  849: *                    Scale if necessary
  850: *
  851:                      IF( SCALE.NE.ONE ) THEN
  852:                         CALL DSCAL( N-KI+1, SCALE, WORK( KI+N ), 1 )
  853:                         CALL DSCAL( N-KI+1, SCALE, WORK( KI+N2 ), 1 )
  854:                      END IF
  855:                      WORK( J+N ) = X( 1, 1 )
  856:                      WORK( J+N2 ) = X( 1, 2 )
  857:                      VMAX = MAX( ABS( WORK( J+N ) ),
  858:      $                      ABS( WORK( J+N2 ) ), VMAX )
  859:                      VCRIT = BIGNUM / VMAX
  860: *
  861:                   ELSE
  862: *
  863: *                    2-by-2 diagonal block
  864: *
  865: *                    Scale if necessary to avoid overflow when forming
  866: *                    the right-hand side elements.
  867: *
  868:                      BETA = MAX( WORK( J ), WORK( J+1 ) )
  869:                      IF( BETA.GT.VCRIT ) THEN
  870:                         REC = ONE / VMAX
  871:                         CALL DSCAL( N-KI+1, REC, WORK( KI+N ), 1 )
  872:                         CALL DSCAL( N-KI+1, REC, WORK( KI+N2 ), 1 )
  873:                         VMAX = ONE
  874:                         VCRIT = BIGNUM
  875:                      END IF
  876: *
  877:                      WORK( J+N ) = WORK( J+N ) -
  878:      $                             DDOT( J-KI-2, T( KI+2, J ), 1,
  879:      $                             WORK( KI+2+N ), 1 )
  880: *
  881:                      WORK( J+N2 ) = WORK( J+N2 ) -
  882:      $                              DDOT( J-KI-2, T( KI+2, J ), 1,
  883:      $                              WORK( KI+2+N2 ), 1 )
  884: *
  885:                      WORK( J+1+N ) = WORK( J+1+N ) -
  886:      $                               DDOT( J-KI-2, T( KI+2, J+1 ), 1,
  887:      $                               WORK( KI+2+N ), 1 )
  888: *
  889:                      WORK( J+1+N2 ) = WORK( J+1+N2 ) -
  890:      $                                DDOT( J-KI-2, T( KI+2, J+1 ), 1,
  891:      $                                WORK( KI+2+N2 ), 1 )
  892: *
  893: *                    Solve 2-by-2 complex linear equation
  894: *                      ([T(j,j)   T(j,j+1)  ]'-(wr-i*wi)*I)*X = SCALE*B
  895: *                      ([T(j+1,j) T(j+1,j+1)]             )
  896: *
  897:                      CALL DLALN2( .TRUE., 2, 2, SMIN, ONE, T( J, J ),
  898:      $                            LDT, ONE, ONE, WORK( J+N ), N, WR,
  899:      $                            -WI, X, 2, SCALE, XNORM, IERR )
  900: *
  901: *                    Scale if necessary
  902: *
  903:                      IF( SCALE.NE.ONE ) THEN
  904:                         CALL DSCAL( N-KI+1, SCALE, WORK( KI+N ), 1 )
  905:                         CALL DSCAL( N-KI+1, SCALE, WORK( KI+N2 ), 1 )
  906:                      END IF
  907:                      WORK( J+N ) = X( 1, 1 )
  908:                      WORK( J+N2 ) = X( 1, 2 )
  909:                      WORK( J+1+N ) = X( 2, 1 )
  910:                      WORK( J+1+N2 ) = X( 2, 2 )
  911:                      VMAX = MAX( ABS( X( 1, 1 ) ), ABS( X( 1, 2 ) ),
  912:      $                      ABS( X( 2, 1 ) ), ABS( X( 2, 2 ) ), VMAX )
  913:                      VCRIT = BIGNUM / VMAX
  914: *
  915:                   END IF
  916:   200          CONTINUE
  917: *
  918: *              Copy the vector x or Q*x to VL and normalize.
  919: *
  920:                IF( .NOT.OVER ) THEN
  921:                   CALL DCOPY( N-KI+1, WORK( KI+N ), 1, VL( KI, IS ), 1 )
  922:                   CALL DCOPY( N-KI+1, WORK( KI+N2 ), 1, VL( KI, IS+1 ),
  923:      $                        1 )
  924: *
  925:                   EMAX = ZERO
  926:                   DO 220 K = KI, N
  927:                      EMAX = MAX( EMAX, ABS( VL( K, IS ) )+
  928:      $                      ABS( VL( K, IS+1 ) ) )
  929:   220             CONTINUE
  930:                   REMAX = ONE / EMAX
  931:                   CALL DSCAL( N-KI+1, REMAX, VL( KI, IS ), 1 )
  932:                   CALL DSCAL( N-KI+1, REMAX, VL( KI, IS+1 ), 1 )
  933: *
  934:                   DO 230 K = 1, KI - 1
  935:                      VL( K, IS ) = ZERO
  936:                      VL( K, IS+1 ) = ZERO
  937:   230             CONTINUE
  938:                ELSE
  939:                   IF( KI.LT.N-1 ) THEN
  940:                      CALL DGEMV( 'N', N, N-KI-1, ONE, VL( 1, KI+2 ),
  941:      $                           LDVL, WORK( KI+2+N ), 1, WORK( KI+N ),
  942:      $                           VL( 1, KI ), 1 )
  943:                      CALL DGEMV( 'N', N, N-KI-1, ONE, VL( 1, KI+2 ),
  944:      $                           LDVL, WORK( KI+2+N2 ), 1,
  945:      $                           WORK( KI+1+N2 ), VL( 1, KI+1 ), 1 )
  946:                   ELSE
  947:                      CALL DSCAL( N, WORK( KI+N ), VL( 1, KI ), 1 )
  948:                      CALL DSCAL( N, WORK( KI+1+N2 ), VL( 1, KI+1 ), 1 )
  949:                   END IF
  950: *
  951:                   EMAX = ZERO
  952:                   DO 240 K = 1, N
  953:                      EMAX = MAX( EMAX, ABS( VL( K, KI ) )+
  954:      $                      ABS( VL( K, KI+1 ) ) )
  955:   240             CONTINUE
  956:                   REMAX = ONE / EMAX
  957:                   CALL DSCAL( N, REMAX, VL( 1, KI ), 1 )
  958:                   CALL DSCAL( N, REMAX, VL( 1, KI+1 ), 1 )
  959: *
  960:                END IF
  961: *
  962:             END IF
  963: *
  964:             IS = IS + 1
  965:             IF( IP.NE.0 )
  966:      $         IS = IS + 1
  967:   250       CONTINUE
  968:             IF( IP.EQ.-1 )
  969:      $         IP = 0
  970:             IF( IP.EQ.1 )
  971:      $         IP = -1
  972: *
  973:   260    CONTINUE
  974: *
  975:       END IF
  976: *
  977:       RETURN
  978: *
  979: *     End of DTREVC
  980: *
  981:       END

CVSweb interface <joel.bertrand@systella.fr>