Annotation of rpl/lapack/lapack/dtgevc.f, revision 1.9

1.9     ! bertrand    1: *> \brief \b DTGEVC
        !             2: *
        !             3: *  =========== DOCUMENTATION ===========
        !             4: *
        !             5: * Online html documentation available at 
        !             6: *            http://www.netlib.org/lapack/explore-html/ 
        !             7: *
        !             8: *> \htmlonly
        !             9: *> Download DTGEVC + dependencies 
        !            10: *> <a href="http://www.netlib.org/cgi-bin/netlibfiles.tgz?format=tgz&filename=/lapack/lapack_routine/dtgevc.f"> 
        !            11: *> [TGZ]</a> 
        !            12: *> <a href="http://www.netlib.org/cgi-bin/netlibfiles.zip?format=zip&filename=/lapack/lapack_routine/dtgevc.f"> 
        !            13: *> [ZIP]</a> 
        !            14: *> <a href="http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/dtgevc.f"> 
        !            15: *> [TXT]</a>
        !            16: *> \endhtmlonly 
        !            17: *
        !            18: *  Definition:
        !            19: *  ===========
        !            20: *
        !            21: *       SUBROUTINE DTGEVC( SIDE, HOWMNY, SELECT, N, S, LDS, P, LDP, VL,
        !            22: *                          LDVL, VR, LDVR, MM, M, WORK, INFO )
        !            23: * 
        !            24: *       .. Scalar Arguments ..
        !            25: *       CHARACTER          HOWMNY, SIDE
        !            26: *       INTEGER            INFO, LDP, LDS, LDVL, LDVR, M, MM, N
        !            27: *       ..
        !            28: *       .. Array Arguments ..
        !            29: *       LOGICAL            SELECT( * )
        !            30: *       DOUBLE PRECISION   P( LDP, * ), S( LDS, * ), VL( LDVL, * ),
        !            31: *      $                   VR( LDVR, * ), WORK( * )
        !            32: *       ..
        !            33: *  
        !            34: *  
        !            35: *
        !            36: *> \par Purpose:
        !            37: *  =============
        !            38: *>
        !            39: *> \verbatim
        !            40: *>
        !            41: *> DTGEVC computes some or all of the right and/or left eigenvectors of
        !            42: *> a pair of real matrices (S,P), where S is a quasi-triangular matrix
        !            43: *> and P is upper triangular.  Matrix pairs of this type are produced by
        !            44: *> the generalized Schur factorization of a matrix pair (A,B):
        !            45: *>
        !            46: *>    A = Q*S*Z**T,  B = Q*P*Z**T
        !            47: *>
        !            48: *> as computed by DGGHRD + DHGEQZ.
        !            49: *>
        !            50: *> The right eigenvector x and the left eigenvector y of (S,P)
        !            51: *> corresponding to an eigenvalue w are defined by:
        !            52: *> 
        !            53: *>    S*x = w*P*x,  (y**H)*S = w*(y**H)*P,
        !            54: *> 
        !            55: *> where y**H denotes the conjugate tranpose of y.
        !            56: *> The eigenvalues are not input to this routine, but are computed
        !            57: *> directly from the diagonal blocks of S and P.
        !            58: *> 
        !            59: *> This routine returns the matrices X and/or Y of right and left
        !            60: *> eigenvectors of (S,P), or the products Z*X and/or Q*Y,
        !            61: *> where Z and Q are input matrices.
        !            62: *> If Q and Z are the orthogonal factors from the generalized Schur
        !            63: *> factorization of a matrix pair (A,B), then Z*X and Q*Y
        !            64: *> are the matrices of right and left eigenvectors of (A,B).
        !            65: *> 
        !            66: *> \endverbatim
        !            67: *
        !            68: *  Arguments:
        !            69: *  ==========
        !            70: *
        !            71: *> \param[in] SIDE
        !            72: *> \verbatim
        !            73: *>          SIDE is CHARACTER*1
        !            74: *>          = 'R': compute right eigenvectors only;
        !            75: *>          = 'L': compute left eigenvectors only;
        !            76: *>          = 'B': compute both right and left eigenvectors.
        !            77: *> \endverbatim
        !            78: *>
        !            79: *> \param[in] HOWMNY
        !            80: *> \verbatim
        !            81: *>          HOWMNY is CHARACTER*1
        !            82: *>          = 'A': compute all right and/or left eigenvectors;
        !            83: *>          = 'B': compute all right and/or left eigenvectors,
        !            84: *>                 backtransformed by the matrices in VR and/or VL;
        !            85: *>          = 'S': compute selected right and/or left eigenvectors,
        !            86: *>                 specified by the logical array SELECT.
        !            87: *> \endverbatim
        !            88: *>
        !            89: *> \param[in] SELECT
        !            90: *> \verbatim
        !            91: *>          SELECT is LOGICAL array, dimension (N)
        !            92: *>          If HOWMNY='S', SELECT specifies the eigenvectors to be
        !            93: *>          computed.  If w(j) is a real eigenvalue, the corresponding
        !            94: *>          real eigenvector is computed if SELECT(j) is .TRUE..
        !            95: *>          If w(j) and w(j+1) are the real and imaginary parts of a
        !            96: *>          complex eigenvalue, the corresponding complex eigenvector
        !            97: *>          is computed if either SELECT(j) or SELECT(j+1) is .TRUE.,
        !            98: *>          and on exit SELECT(j) is set to .TRUE. and SELECT(j+1) is
        !            99: *>          set to .FALSE..
        !           100: *>          Not referenced if HOWMNY = 'A' or 'B'.
        !           101: *> \endverbatim
        !           102: *>
        !           103: *> \param[in] N
        !           104: *> \verbatim
        !           105: *>          N is INTEGER
        !           106: *>          The order of the matrices S and P.  N >= 0.
        !           107: *> \endverbatim
        !           108: *>
        !           109: *> \param[in] S
        !           110: *> \verbatim
        !           111: *>          S is DOUBLE PRECISION array, dimension (LDS,N)
        !           112: *>          The upper quasi-triangular matrix S from a generalized Schur
        !           113: *>          factorization, as computed by DHGEQZ.
        !           114: *> \endverbatim
        !           115: *>
        !           116: *> \param[in] LDS
        !           117: *> \verbatim
        !           118: *>          LDS is INTEGER
        !           119: *>          The leading dimension of array S.  LDS >= max(1,N).
        !           120: *> \endverbatim
        !           121: *>
        !           122: *> \param[in] P
        !           123: *> \verbatim
        !           124: *>          P is DOUBLE PRECISION array, dimension (LDP,N)
        !           125: *>          The upper triangular matrix P from a generalized Schur
        !           126: *>          factorization, as computed by DHGEQZ.
        !           127: *>          2-by-2 diagonal blocks of P corresponding to 2-by-2 blocks
        !           128: *>          of S must be in positive diagonal form.
        !           129: *> \endverbatim
        !           130: *>
        !           131: *> \param[in] LDP
        !           132: *> \verbatim
        !           133: *>          LDP is INTEGER
        !           134: *>          The leading dimension of array P.  LDP >= max(1,N).
        !           135: *> \endverbatim
        !           136: *>
        !           137: *> \param[in,out] VL
        !           138: *> \verbatim
        !           139: *>          VL is DOUBLE PRECISION array, dimension (LDVL,MM)
        !           140: *>          On entry, if SIDE = 'L' or 'B' and HOWMNY = 'B', VL must
        !           141: *>          contain an N-by-N matrix Q (usually the orthogonal matrix Q
        !           142: *>          of left Schur vectors returned by DHGEQZ).
        !           143: *>          On exit, if SIDE = 'L' or 'B', VL contains:
        !           144: *>          if HOWMNY = 'A', the matrix Y of left eigenvectors of (S,P);
        !           145: *>          if HOWMNY = 'B', the matrix Q*Y;
        !           146: *>          if HOWMNY = 'S', the left eigenvectors of (S,P) specified by
        !           147: *>                      SELECT, stored consecutively in the columns of
        !           148: *>                      VL, in the same order as their eigenvalues.
        !           149: *>
        !           150: *>          A complex eigenvector corresponding to a complex eigenvalue
        !           151: *>          is stored in two consecutive columns, the first holding the
        !           152: *>          real part, and the second the imaginary part.
        !           153: *>
        !           154: *>          Not referenced if SIDE = 'R'.
        !           155: *> \endverbatim
        !           156: *>
        !           157: *> \param[in] LDVL
        !           158: *> \verbatim
        !           159: *>          LDVL is INTEGER
        !           160: *>          The leading dimension of array VL.  LDVL >= 1, and if
        !           161: *>          SIDE = 'L' or 'B', LDVL >= N.
        !           162: *> \endverbatim
        !           163: *>
        !           164: *> \param[in,out] VR
        !           165: *> \verbatim
        !           166: *>          VR is DOUBLE PRECISION array, dimension (LDVR,MM)
        !           167: *>          On entry, if SIDE = 'R' or 'B' and HOWMNY = 'B', VR must
        !           168: *>          contain an N-by-N matrix Z (usually the orthogonal matrix Z
        !           169: *>          of right Schur vectors returned by DHGEQZ).
        !           170: *>
        !           171: *>          On exit, if SIDE = 'R' or 'B', VR contains:
        !           172: *>          if HOWMNY = 'A', the matrix X of right eigenvectors of (S,P);
        !           173: *>          if HOWMNY = 'B' or 'b', the matrix Z*X;
        !           174: *>          if HOWMNY = 'S' or 's', the right eigenvectors of (S,P)
        !           175: *>                      specified by SELECT, stored consecutively in the
        !           176: *>                      columns of VR, in the same order as their
        !           177: *>                      eigenvalues.
        !           178: *>
        !           179: *>          A complex eigenvector corresponding to a complex eigenvalue
        !           180: *>          is stored in two consecutive columns, the first holding the
        !           181: *>          real part and the second the imaginary part.
        !           182: *>          
        !           183: *>          Not referenced if SIDE = 'L'.
        !           184: *> \endverbatim
        !           185: *>
        !           186: *> \param[in] LDVR
        !           187: *> \verbatim
        !           188: *>          LDVR is INTEGER
        !           189: *>          The leading dimension of the array VR.  LDVR >= 1, and if
        !           190: *>          SIDE = 'R' or 'B', LDVR >= N.
        !           191: *> \endverbatim
        !           192: *>
        !           193: *> \param[in] MM
        !           194: *> \verbatim
        !           195: *>          MM is INTEGER
        !           196: *>          The number of columns in the arrays VL and/or VR. MM >= M.
        !           197: *> \endverbatim
        !           198: *>
        !           199: *> \param[out] M
        !           200: *> \verbatim
        !           201: *>          M is INTEGER
        !           202: *>          The number of columns in the arrays VL and/or VR actually
        !           203: *>          used to store the eigenvectors.  If HOWMNY = 'A' or 'B', M
        !           204: *>          is set to N.  Each selected real eigenvector occupies one
        !           205: *>          column and each selected complex eigenvector occupies two
        !           206: *>          columns.
        !           207: *> \endverbatim
        !           208: *>
        !           209: *> \param[out] WORK
        !           210: *> \verbatim
        !           211: *>          WORK is DOUBLE PRECISION array, dimension (6*N)
        !           212: *> \endverbatim
        !           213: *>
        !           214: *> \param[out] INFO
        !           215: *> \verbatim
        !           216: *>          INFO is INTEGER
        !           217: *>          = 0:  successful exit.
        !           218: *>          < 0:  if INFO = -i, the i-th argument had an illegal value.
        !           219: *>          > 0:  the 2-by-2 block (INFO:INFO+1) does not have a complex
        !           220: *>                eigenvalue.
        !           221: *> \endverbatim
        !           222: *
        !           223: *  Authors:
        !           224: *  ========
        !           225: *
        !           226: *> \author Univ. of Tennessee 
        !           227: *> \author Univ. of California Berkeley 
        !           228: *> \author Univ. of Colorado Denver 
        !           229: *> \author NAG Ltd. 
        !           230: *
        !           231: *> \date November 2011
        !           232: *
        !           233: *> \ingroup doubleGEcomputational
        !           234: *
        !           235: *> \par Further Details:
        !           236: *  =====================
        !           237: *>
        !           238: *> \verbatim
        !           239: *>
        !           240: *>  Allocation of workspace:
        !           241: *>  ---------- -- ---------
        !           242: *>
        !           243: *>     WORK( j ) = 1-norm of j-th column of A, above the diagonal
        !           244: *>     WORK( N+j ) = 1-norm of j-th column of B, above the diagonal
        !           245: *>     WORK( 2*N+1:3*N ) = real part of eigenvector
        !           246: *>     WORK( 3*N+1:4*N ) = imaginary part of eigenvector
        !           247: *>     WORK( 4*N+1:5*N ) = real part of back-transformed eigenvector
        !           248: *>     WORK( 5*N+1:6*N ) = imaginary part of back-transformed eigenvector
        !           249: *>
        !           250: *>  Rowwise vs. columnwise solution methods:
        !           251: *>  ------- --  ---------- -------- -------
        !           252: *>
        !           253: *>  Finding a generalized eigenvector consists basically of solving the
        !           254: *>  singular triangular system
        !           255: *>
        !           256: *>   (A - w B) x = 0     (for right) or:   (A - w B)**H y = 0  (for left)
        !           257: *>
        !           258: *>  Consider finding the i-th right eigenvector (assume all eigenvalues
        !           259: *>  are real). The equation to be solved is:
        !           260: *>       n                   i
        !           261: *>  0 = sum  C(j,k) v(k)  = sum  C(j,k) v(k)     for j = i,. . .,1
        !           262: *>      k=j                 k=j
        !           263: *>
        !           264: *>  where  C = (A - w B)  (The components v(i+1:n) are 0.)
        !           265: *>
        !           266: *>  The "rowwise" method is:
        !           267: *>
        !           268: *>  (1)  v(i) := 1
        !           269: *>  for j = i-1,. . .,1:
        !           270: *>                          i
        !           271: *>      (2) compute  s = - sum C(j,k) v(k)   and
        !           272: *>                        k=j+1
        !           273: *>
        !           274: *>      (3) v(j) := s / C(j,j)
        !           275: *>
        !           276: *>  Step 2 is sometimes called the "dot product" step, since it is an
        !           277: *>  inner product between the j-th row and the portion of the eigenvector
        !           278: *>  that has been computed so far.
        !           279: *>
        !           280: *>  The "columnwise" method consists basically in doing the sums
        !           281: *>  for all the rows in parallel.  As each v(j) is computed, the
        !           282: *>  contribution of v(j) times the j-th column of C is added to the
        !           283: *>  partial sums.  Since FORTRAN arrays are stored columnwise, this has
        !           284: *>  the advantage that at each step, the elements of C that are accessed
        !           285: *>  are adjacent to one another, whereas with the rowwise method, the
        !           286: *>  elements accessed at a step are spaced LDS (and LDP) words apart.
        !           287: *>
        !           288: *>  When finding left eigenvectors, the matrix in question is the
        !           289: *>  transpose of the one in storage, so the rowwise method then
        !           290: *>  actually accesses columns of A and B at each step, and so is the
        !           291: *>  preferred method.
        !           292: *> \endverbatim
        !           293: *>
        !           294: *  =====================================================================
1.1       bertrand  295:       SUBROUTINE DTGEVC( SIDE, HOWMNY, SELECT, N, S, LDS, P, LDP, VL,
                    296:      $                   LDVL, VR, LDVR, MM, M, WORK, INFO )
                    297: *
1.9     ! bertrand  298: *  -- LAPACK computational routine (version 3.4.0) --
1.1       bertrand  299: *  -- LAPACK is a software package provided by Univ. of Tennessee,    --
                    300: *  -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..--
1.9     ! bertrand  301: *     November 2011
1.1       bertrand  302: *
                    303: *     .. Scalar Arguments ..
                    304:       CHARACTER          HOWMNY, SIDE
                    305:       INTEGER            INFO, LDP, LDS, LDVL, LDVR, M, MM, N
                    306: *     ..
                    307: *     .. Array Arguments ..
                    308:       LOGICAL            SELECT( * )
                    309:       DOUBLE PRECISION   P( LDP, * ), S( LDS, * ), VL( LDVL, * ),
                    310:      $                   VR( LDVR, * ), WORK( * )
                    311: *     ..
                    312: *
                    313: *
                    314: *  =====================================================================
                    315: *
                    316: *     .. Parameters ..
                    317:       DOUBLE PRECISION   ZERO, ONE, SAFETY
                    318:       PARAMETER          ( ZERO = 0.0D+0, ONE = 1.0D+0,
                    319:      $                   SAFETY = 1.0D+2 )
                    320: *     ..
                    321: *     .. Local Scalars ..
                    322:       LOGICAL            COMPL, COMPR, IL2BY2, ILABAD, ILALL, ILBACK,
                    323:      $                   ILBBAD, ILCOMP, ILCPLX, LSA, LSB
                    324:       INTEGER            I, IBEG, IEIG, IEND, IHWMNY, IINFO, IM, ISIDE,
                    325:      $                   J, JA, JC, JE, JR, JW, NA, NW
                    326:       DOUBLE PRECISION   ACOEF, ACOEFA, ANORM, ASCALE, BCOEFA, BCOEFI,
                    327:      $                   BCOEFR, BIG, BIGNUM, BNORM, BSCALE, CIM2A,
                    328:      $                   CIM2B, CIMAGA, CIMAGB, CRE2A, CRE2B, CREALA,
                    329:      $                   CREALB, DMIN, SAFMIN, SALFAR, SBETA, SCALE,
                    330:      $                   SMALL, TEMP, TEMP2, TEMP2I, TEMP2R, ULP, XMAX,
                    331:      $                   XSCALE
                    332: *     ..
                    333: *     .. Local Arrays ..
                    334:       DOUBLE PRECISION   BDIAG( 2 ), SUM( 2, 2 ), SUMS( 2, 2 ),
                    335:      $                   SUMP( 2, 2 )
                    336: *     ..
                    337: *     .. External Functions ..
                    338:       LOGICAL            LSAME
                    339:       DOUBLE PRECISION   DLAMCH
                    340:       EXTERNAL           LSAME, DLAMCH
                    341: *     ..
                    342: *     .. External Subroutines ..
                    343:       EXTERNAL           DGEMV, DLABAD, DLACPY, DLAG2, DLALN2, XERBLA
                    344: *     ..
                    345: *     .. Intrinsic Functions ..
                    346:       INTRINSIC          ABS, MAX, MIN
                    347: *     ..
                    348: *     .. Executable Statements ..
                    349: *
                    350: *     Decode and Test the input parameters
                    351: *
                    352:       IF( LSAME( HOWMNY, 'A' ) ) THEN
                    353:          IHWMNY = 1
                    354:          ILALL = .TRUE.
                    355:          ILBACK = .FALSE.
                    356:       ELSE IF( LSAME( HOWMNY, 'S' ) ) THEN
                    357:          IHWMNY = 2
                    358:          ILALL = .FALSE.
                    359:          ILBACK = .FALSE.
                    360:       ELSE IF( LSAME( HOWMNY, 'B' ) ) THEN
                    361:          IHWMNY = 3
                    362:          ILALL = .TRUE.
                    363:          ILBACK = .TRUE.
                    364:       ELSE
                    365:          IHWMNY = -1
                    366:          ILALL = .TRUE.
                    367:       END IF
                    368: *
                    369:       IF( LSAME( SIDE, 'R' ) ) THEN
                    370:          ISIDE = 1
                    371:          COMPL = .FALSE.
                    372:          COMPR = .TRUE.
                    373:       ELSE IF( LSAME( SIDE, 'L' ) ) THEN
                    374:          ISIDE = 2
                    375:          COMPL = .TRUE.
                    376:          COMPR = .FALSE.
                    377:       ELSE IF( LSAME( SIDE, 'B' ) ) THEN
                    378:          ISIDE = 3
                    379:          COMPL = .TRUE.
                    380:          COMPR = .TRUE.
                    381:       ELSE
                    382:          ISIDE = -1
                    383:       END IF
                    384: *
                    385:       INFO = 0
                    386:       IF( ISIDE.LT.0 ) THEN
                    387:          INFO = -1
                    388:       ELSE IF( IHWMNY.LT.0 ) THEN
                    389:          INFO = -2
                    390:       ELSE IF( N.LT.0 ) THEN
                    391:          INFO = -4
                    392:       ELSE IF( LDS.LT.MAX( 1, N ) ) THEN
                    393:          INFO = -6
                    394:       ELSE IF( LDP.LT.MAX( 1, N ) ) THEN
                    395:          INFO = -8
                    396:       END IF
                    397:       IF( INFO.NE.0 ) THEN
                    398:          CALL XERBLA( 'DTGEVC', -INFO )
                    399:          RETURN
                    400:       END IF
                    401: *
                    402: *     Count the number of eigenvectors to be computed
                    403: *
                    404:       IF( .NOT.ILALL ) THEN
                    405:          IM = 0
                    406:          ILCPLX = .FALSE.
                    407:          DO 10 J = 1, N
                    408:             IF( ILCPLX ) THEN
                    409:                ILCPLX = .FALSE.
                    410:                GO TO 10
                    411:             END IF
                    412:             IF( J.LT.N ) THEN
                    413:                IF( S( J+1, J ).NE.ZERO )
                    414:      $            ILCPLX = .TRUE.
                    415:             END IF
                    416:             IF( ILCPLX ) THEN
                    417:                IF( SELECT( J ) .OR. SELECT( J+1 ) )
                    418:      $            IM = IM + 2
                    419:             ELSE
                    420:                IF( SELECT( J ) )
                    421:      $            IM = IM + 1
                    422:             END IF
                    423:    10    CONTINUE
                    424:       ELSE
                    425:          IM = N
                    426:       END IF
                    427: *
                    428: *     Check 2-by-2 diagonal blocks of A, B
                    429: *
                    430:       ILABAD = .FALSE.
                    431:       ILBBAD = .FALSE.
                    432:       DO 20 J = 1, N - 1
                    433:          IF( S( J+1, J ).NE.ZERO ) THEN
                    434:             IF( P( J, J ).EQ.ZERO .OR. P( J+1, J+1 ).EQ.ZERO .OR.
                    435:      $          P( J, J+1 ).NE.ZERO )ILBBAD = .TRUE.
                    436:             IF( J.LT.N-1 ) THEN
                    437:                IF( S( J+2, J+1 ).NE.ZERO )
                    438:      $            ILABAD = .TRUE.
                    439:             END IF
                    440:          END IF
                    441:    20 CONTINUE
                    442: *
                    443:       IF( ILABAD ) THEN
                    444:          INFO = -5
                    445:       ELSE IF( ILBBAD ) THEN
                    446:          INFO = -7
                    447:       ELSE IF( COMPL .AND. LDVL.LT.N .OR. LDVL.LT.1 ) THEN
                    448:          INFO = -10
                    449:       ELSE IF( COMPR .AND. LDVR.LT.N .OR. LDVR.LT.1 ) THEN
                    450:          INFO = -12
                    451:       ELSE IF( MM.LT.IM ) THEN
                    452:          INFO = -13
                    453:       END IF
                    454:       IF( INFO.NE.0 ) THEN
                    455:          CALL XERBLA( 'DTGEVC', -INFO )
                    456:          RETURN
                    457:       END IF
                    458: *
                    459: *     Quick return if possible
                    460: *
                    461:       M = IM
                    462:       IF( N.EQ.0 )
                    463:      $   RETURN
                    464: *
                    465: *     Machine Constants
                    466: *
                    467:       SAFMIN = DLAMCH( 'Safe minimum' )
                    468:       BIG = ONE / SAFMIN
                    469:       CALL DLABAD( SAFMIN, BIG )
                    470:       ULP = DLAMCH( 'Epsilon' )*DLAMCH( 'Base' )
                    471:       SMALL = SAFMIN*N / ULP
                    472:       BIG = ONE / SMALL
                    473:       BIGNUM = ONE / ( SAFMIN*N )
                    474: *
                    475: *     Compute the 1-norm of each column of the strictly upper triangular
                    476: *     part (i.e., excluding all elements belonging to the diagonal
                    477: *     blocks) of A and B to check for possible overflow in the
                    478: *     triangular solver.
                    479: *
                    480:       ANORM = ABS( S( 1, 1 ) )
                    481:       IF( N.GT.1 )
                    482:      $   ANORM = ANORM + ABS( S( 2, 1 ) )
                    483:       BNORM = ABS( P( 1, 1 ) )
                    484:       WORK( 1 ) = ZERO
                    485:       WORK( N+1 ) = ZERO
                    486: *
                    487:       DO 50 J = 2, N
                    488:          TEMP = ZERO
                    489:          TEMP2 = ZERO
                    490:          IF( S( J, J-1 ).EQ.ZERO ) THEN
                    491:             IEND = J - 1
                    492:          ELSE
                    493:             IEND = J - 2
                    494:          END IF
                    495:          DO 30 I = 1, IEND
                    496:             TEMP = TEMP + ABS( S( I, J ) )
                    497:             TEMP2 = TEMP2 + ABS( P( I, J ) )
                    498:    30    CONTINUE
                    499:          WORK( J ) = TEMP
                    500:          WORK( N+J ) = TEMP2
                    501:          DO 40 I = IEND + 1, MIN( J+1, N )
                    502:             TEMP = TEMP + ABS( S( I, J ) )
                    503:             TEMP2 = TEMP2 + ABS( P( I, J ) )
                    504:    40    CONTINUE
                    505:          ANORM = MAX( ANORM, TEMP )
                    506:          BNORM = MAX( BNORM, TEMP2 )
                    507:    50 CONTINUE
                    508: *
                    509:       ASCALE = ONE / MAX( ANORM, SAFMIN )
                    510:       BSCALE = ONE / MAX( BNORM, SAFMIN )
                    511: *
                    512: *     Left eigenvectors
                    513: *
                    514:       IF( COMPL ) THEN
                    515:          IEIG = 0
                    516: *
                    517: *        Main loop over eigenvalues
                    518: *
                    519:          ILCPLX = .FALSE.
                    520:          DO 220 JE = 1, N
                    521: *
                    522: *           Skip this iteration if (a) HOWMNY='S' and SELECT=.FALSE., or
                    523: *           (b) this would be the second of a complex pair.
                    524: *           Check for complex eigenvalue, so as to be sure of which
                    525: *           entry(-ies) of SELECT to look at.
                    526: *
                    527:             IF( ILCPLX ) THEN
                    528:                ILCPLX = .FALSE.
                    529:                GO TO 220
                    530:             END IF
                    531:             NW = 1
                    532:             IF( JE.LT.N ) THEN
                    533:                IF( S( JE+1, JE ).NE.ZERO ) THEN
                    534:                   ILCPLX = .TRUE.
                    535:                   NW = 2
                    536:                END IF
                    537:             END IF
                    538:             IF( ILALL ) THEN
                    539:                ILCOMP = .TRUE.
                    540:             ELSE IF( ILCPLX ) THEN
                    541:                ILCOMP = SELECT( JE ) .OR. SELECT( JE+1 )
                    542:             ELSE
                    543:                ILCOMP = SELECT( JE )
                    544:             END IF
                    545:             IF( .NOT.ILCOMP )
                    546:      $         GO TO 220
                    547: *
                    548: *           Decide if (a) singular pencil, (b) real eigenvalue, or
                    549: *           (c) complex eigenvalue.
                    550: *
                    551:             IF( .NOT.ILCPLX ) THEN
                    552:                IF( ABS( S( JE, JE ) ).LE.SAFMIN .AND.
                    553:      $             ABS( P( JE, JE ) ).LE.SAFMIN ) THEN
                    554: *
                    555: *                 Singular matrix pencil -- return unit eigenvector
                    556: *
                    557:                   IEIG = IEIG + 1
                    558:                   DO 60 JR = 1, N
                    559:                      VL( JR, IEIG ) = ZERO
                    560:    60             CONTINUE
                    561:                   VL( IEIG, IEIG ) = ONE
                    562:                   GO TO 220
                    563:                END IF
                    564:             END IF
                    565: *
                    566: *           Clear vector
                    567: *
                    568:             DO 70 JR = 1, NW*N
                    569:                WORK( 2*N+JR ) = ZERO
                    570:    70       CONTINUE
                    571: *                                                 T
                    572: *           Compute coefficients in  ( a A - b B )  y = 0
                    573: *              a  is  ACOEF
                    574: *              b  is  BCOEFR + i*BCOEFI
                    575: *
                    576:             IF( .NOT.ILCPLX ) THEN
                    577: *
                    578: *              Real eigenvalue
                    579: *
                    580:                TEMP = ONE / MAX( ABS( S( JE, JE ) )*ASCALE,
                    581:      $                ABS( P( JE, JE ) )*BSCALE, SAFMIN )
                    582:                SALFAR = ( TEMP*S( JE, JE ) )*ASCALE
                    583:                SBETA = ( TEMP*P( JE, JE ) )*BSCALE
                    584:                ACOEF = SBETA*ASCALE
                    585:                BCOEFR = SALFAR*BSCALE
                    586:                BCOEFI = ZERO
                    587: *
                    588: *              Scale to avoid underflow
                    589: *
                    590:                SCALE = ONE
                    591:                LSA = ABS( SBETA ).GE.SAFMIN .AND. ABS( ACOEF ).LT.SMALL
                    592:                LSB = ABS( SALFAR ).GE.SAFMIN .AND. ABS( BCOEFR ).LT.
                    593:      $               SMALL
                    594:                IF( LSA )
                    595:      $            SCALE = ( SMALL / ABS( SBETA ) )*MIN( ANORM, BIG )
                    596:                IF( LSB )
                    597:      $            SCALE = MAX( SCALE, ( SMALL / ABS( SALFAR ) )*
                    598:      $                    MIN( BNORM, BIG ) )
                    599:                IF( LSA .OR. LSB ) THEN
                    600:                   SCALE = MIN( SCALE, ONE /
                    601:      $                    ( SAFMIN*MAX( ONE, ABS( ACOEF ),
                    602:      $                    ABS( BCOEFR ) ) ) )
                    603:                   IF( LSA ) THEN
                    604:                      ACOEF = ASCALE*( SCALE*SBETA )
                    605:                   ELSE
                    606:                      ACOEF = SCALE*ACOEF
                    607:                   END IF
                    608:                   IF( LSB ) THEN
                    609:                      BCOEFR = BSCALE*( SCALE*SALFAR )
                    610:                   ELSE
                    611:                      BCOEFR = SCALE*BCOEFR
                    612:                   END IF
                    613:                END IF
                    614:                ACOEFA = ABS( ACOEF )
                    615:                BCOEFA = ABS( BCOEFR )
                    616: *
                    617: *              First component is 1
                    618: *
                    619:                WORK( 2*N+JE ) = ONE
                    620:                XMAX = ONE
                    621:             ELSE
                    622: *
                    623: *              Complex eigenvalue
                    624: *
                    625:                CALL DLAG2( S( JE, JE ), LDS, P( JE, JE ), LDP,
                    626:      $                     SAFMIN*SAFETY, ACOEF, TEMP, BCOEFR, TEMP2,
                    627:      $                     BCOEFI )
                    628:                BCOEFI = -BCOEFI
                    629:                IF( BCOEFI.EQ.ZERO ) THEN
                    630:                   INFO = JE
                    631:                   RETURN
                    632:                END IF
                    633: *
                    634: *              Scale to avoid over/underflow
                    635: *
                    636:                ACOEFA = ABS( ACOEF )
                    637:                BCOEFA = ABS( BCOEFR ) + ABS( BCOEFI )
                    638:                SCALE = ONE
                    639:                IF( ACOEFA*ULP.LT.SAFMIN .AND. ACOEFA.GE.SAFMIN )
                    640:      $            SCALE = ( SAFMIN / ULP ) / ACOEFA
                    641:                IF( BCOEFA*ULP.LT.SAFMIN .AND. BCOEFA.GE.SAFMIN )
                    642:      $            SCALE = MAX( SCALE, ( SAFMIN / ULP ) / BCOEFA )
                    643:                IF( SAFMIN*ACOEFA.GT.ASCALE )
                    644:      $            SCALE = ASCALE / ( SAFMIN*ACOEFA )
                    645:                IF( SAFMIN*BCOEFA.GT.BSCALE )
                    646:      $            SCALE = MIN( SCALE, BSCALE / ( SAFMIN*BCOEFA ) )
                    647:                IF( SCALE.NE.ONE ) THEN
                    648:                   ACOEF = SCALE*ACOEF
                    649:                   ACOEFA = ABS( ACOEF )
                    650:                   BCOEFR = SCALE*BCOEFR
                    651:                   BCOEFI = SCALE*BCOEFI
                    652:                   BCOEFA = ABS( BCOEFR ) + ABS( BCOEFI )
                    653:                END IF
                    654: *
                    655: *              Compute first two components of eigenvector
                    656: *
                    657:                TEMP = ACOEF*S( JE+1, JE )
                    658:                TEMP2R = ACOEF*S( JE, JE ) - BCOEFR*P( JE, JE )
                    659:                TEMP2I = -BCOEFI*P( JE, JE )
                    660:                IF( ABS( TEMP ).GT.ABS( TEMP2R )+ABS( TEMP2I ) ) THEN
                    661:                   WORK( 2*N+JE ) = ONE
                    662:                   WORK( 3*N+JE ) = ZERO
                    663:                   WORK( 2*N+JE+1 ) = -TEMP2R / TEMP
                    664:                   WORK( 3*N+JE+1 ) = -TEMP2I / TEMP
                    665:                ELSE
                    666:                   WORK( 2*N+JE+1 ) = ONE
                    667:                   WORK( 3*N+JE+1 ) = ZERO
                    668:                   TEMP = ACOEF*S( JE, JE+1 )
                    669:                   WORK( 2*N+JE ) = ( BCOEFR*P( JE+1, JE+1 )-ACOEF*
                    670:      $                             S( JE+1, JE+1 ) ) / TEMP
                    671:                   WORK( 3*N+JE ) = BCOEFI*P( JE+1, JE+1 ) / TEMP
                    672:                END IF
                    673:                XMAX = MAX( ABS( WORK( 2*N+JE ) )+ABS( WORK( 3*N+JE ) ),
                    674:      $                ABS( WORK( 2*N+JE+1 ) )+ABS( WORK( 3*N+JE+1 ) ) )
                    675:             END IF
                    676: *
                    677:             DMIN = MAX( ULP*ACOEFA*ANORM, ULP*BCOEFA*BNORM, SAFMIN )
                    678: *
                    679: *                                           T
                    680: *           Triangular solve of  (a A - b B)  y = 0
                    681: *
                    682: *                                   T
                    683: *           (rowwise in  (a A - b B) , or columnwise in (a A - b B) )
                    684: *
                    685:             IL2BY2 = .FALSE.
                    686: *
                    687:             DO 160 J = JE + NW, N
                    688:                IF( IL2BY2 ) THEN
                    689:                   IL2BY2 = .FALSE.
                    690:                   GO TO 160
                    691:                END IF
                    692: *
                    693:                NA = 1
                    694:                BDIAG( 1 ) = P( J, J )
                    695:                IF( J.LT.N ) THEN
                    696:                   IF( S( J+1, J ).NE.ZERO ) THEN
                    697:                      IL2BY2 = .TRUE.
                    698:                      BDIAG( 2 ) = P( J+1, J+1 )
                    699:                      NA = 2
                    700:                   END IF
                    701:                END IF
                    702: *
                    703: *              Check whether scaling is necessary for dot products
                    704: *
                    705:                XSCALE = ONE / MAX( ONE, XMAX )
                    706:                TEMP = MAX( WORK( J ), WORK( N+J ),
                    707:      $                ACOEFA*WORK( J )+BCOEFA*WORK( N+J ) )
                    708:                IF( IL2BY2 )
                    709:      $            TEMP = MAX( TEMP, WORK( J+1 ), WORK( N+J+1 ),
                    710:      $                   ACOEFA*WORK( J+1 )+BCOEFA*WORK( N+J+1 ) )
                    711:                IF( TEMP.GT.BIGNUM*XSCALE ) THEN
                    712:                   DO 90 JW = 0, NW - 1
                    713:                      DO 80 JR = JE, J - 1
                    714:                         WORK( ( JW+2 )*N+JR ) = XSCALE*
                    715:      $                     WORK( ( JW+2 )*N+JR )
                    716:    80                CONTINUE
                    717:    90             CONTINUE
                    718:                   XMAX = XMAX*XSCALE
                    719:                END IF
                    720: *
                    721: *              Compute dot products
                    722: *
                    723: *                    j-1
                    724: *              SUM = sum  conjg( a*S(k,j) - b*P(k,j) )*x(k)
                    725: *                    k=je
                    726: *
                    727: *              To reduce the op count, this is done as
                    728: *
                    729: *              _        j-1                  _        j-1
                    730: *              a*conjg( sum  S(k,j)*x(k) ) - b*conjg( sum  P(k,j)*x(k) )
                    731: *                       k=je                          k=je
                    732: *
                    733: *              which may cause underflow problems if A or B are close
                    734: *              to underflow.  (E.g., less than SMALL.)
                    735: *
                    736: *
                    737:                DO 120 JW = 1, NW
                    738:                   DO 110 JA = 1, NA
                    739:                      SUMS( JA, JW ) = ZERO
                    740:                      SUMP( JA, JW ) = ZERO
                    741: *
                    742:                      DO 100 JR = JE, J - 1
                    743:                         SUMS( JA, JW ) = SUMS( JA, JW ) +
                    744:      $                                   S( JR, J+JA-1 )*
                    745:      $                                   WORK( ( JW+1 )*N+JR )
                    746:                         SUMP( JA, JW ) = SUMP( JA, JW ) +
                    747:      $                                   P( JR, J+JA-1 )*
                    748:      $                                   WORK( ( JW+1 )*N+JR )
                    749:   100                CONTINUE
                    750:   110             CONTINUE
                    751:   120          CONTINUE
                    752: *
                    753:                DO 130 JA = 1, NA
                    754:                   IF( ILCPLX ) THEN
                    755:                      SUM( JA, 1 ) = -ACOEF*SUMS( JA, 1 ) +
                    756:      $                              BCOEFR*SUMP( JA, 1 ) -
                    757:      $                              BCOEFI*SUMP( JA, 2 )
                    758:                      SUM( JA, 2 ) = -ACOEF*SUMS( JA, 2 ) +
                    759:      $                              BCOEFR*SUMP( JA, 2 ) +
                    760:      $                              BCOEFI*SUMP( JA, 1 )
                    761:                   ELSE
                    762:                      SUM( JA, 1 ) = -ACOEF*SUMS( JA, 1 ) +
                    763:      $                              BCOEFR*SUMP( JA, 1 )
                    764:                   END IF
                    765:   130          CONTINUE
                    766: *
                    767: *                                  T
                    768: *              Solve  ( a A - b B )  y = SUM(,)
                    769: *              with scaling and perturbation of the denominator
                    770: *
                    771:                CALL DLALN2( .TRUE., NA, NW, DMIN, ACOEF, S( J, J ), LDS,
                    772:      $                      BDIAG( 1 ), BDIAG( 2 ), SUM, 2, BCOEFR,
                    773:      $                      BCOEFI, WORK( 2*N+J ), N, SCALE, TEMP,
                    774:      $                      IINFO )
                    775:                IF( SCALE.LT.ONE ) THEN
                    776:                   DO 150 JW = 0, NW - 1
                    777:                      DO 140 JR = JE, J - 1
                    778:                         WORK( ( JW+2 )*N+JR ) = SCALE*
                    779:      $                     WORK( ( JW+2 )*N+JR )
                    780:   140                CONTINUE
                    781:   150             CONTINUE
                    782:                   XMAX = SCALE*XMAX
                    783:                END IF
                    784:                XMAX = MAX( XMAX, TEMP )
                    785:   160       CONTINUE
                    786: *
                    787: *           Copy eigenvector to VL, back transforming if
                    788: *           HOWMNY='B'.
                    789: *
                    790:             IEIG = IEIG + 1
                    791:             IF( ILBACK ) THEN
                    792:                DO 170 JW = 0, NW - 1
                    793:                   CALL DGEMV( 'N', N, N+1-JE, ONE, VL( 1, JE ), LDVL,
                    794:      $                        WORK( ( JW+2 )*N+JE ), 1, ZERO,
                    795:      $                        WORK( ( JW+4 )*N+1 ), 1 )
                    796:   170          CONTINUE
                    797:                CALL DLACPY( ' ', N, NW, WORK( 4*N+1 ), N, VL( 1, JE ),
                    798:      $                      LDVL )
                    799:                IBEG = 1
                    800:             ELSE
                    801:                CALL DLACPY( ' ', N, NW, WORK( 2*N+1 ), N, VL( 1, IEIG ),
                    802:      $                      LDVL )
                    803:                IBEG = JE
                    804:             END IF
                    805: *
                    806: *           Scale eigenvector
                    807: *
                    808:             XMAX = ZERO
                    809:             IF( ILCPLX ) THEN
                    810:                DO 180 J = IBEG, N
                    811:                   XMAX = MAX( XMAX, ABS( VL( J, IEIG ) )+
                    812:      $                   ABS( VL( J, IEIG+1 ) ) )
                    813:   180          CONTINUE
                    814:             ELSE
                    815:                DO 190 J = IBEG, N
                    816:                   XMAX = MAX( XMAX, ABS( VL( J, IEIG ) ) )
                    817:   190          CONTINUE
                    818:             END IF
                    819: *
                    820:             IF( XMAX.GT.SAFMIN ) THEN
                    821:                XSCALE = ONE / XMAX
                    822: *
                    823:                DO 210 JW = 0, NW - 1
                    824:                   DO 200 JR = IBEG, N
                    825:                      VL( JR, IEIG+JW ) = XSCALE*VL( JR, IEIG+JW )
                    826:   200             CONTINUE
                    827:   210          CONTINUE
                    828:             END IF
                    829:             IEIG = IEIG + NW - 1
                    830: *
                    831:   220    CONTINUE
                    832:       END IF
                    833: *
                    834: *     Right eigenvectors
                    835: *
                    836:       IF( COMPR ) THEN
                    837:          IEIG = IM + 1
                    838: *
                    839: *        Main loop over eigenvalues
                    840: *
                    841:          ILCPLX = .FALSE.
                    842:          DO 500 JE = N, 1, -1
                    843: *
                    844: *           Skip this iteration if (a) HOWMNY='S' and SELECT=.FALSE., or
                    845: *           (b) this would be the second of a complex pair.
                    846: *           Check for complex eigenvalue, so as to be sure of which
                    847: *           entry(-ies) of SELECT to look at -- if complex, SELECT(JE)
                    848: *           or SELECT(JE-1).
                    849: *           If this is a complex pair, the 2-by-2 diagonal block
                    850: *           corresponding to the eigenvalue is in rows/columns JE-1:JE
                    851: *
                    852:             IF( ILCPLX ) THEN
                    853:                ILCPLX = .FALSE.
                    854:                GO TO 500
                    855:             END IF
                    856:             NW = 1
                    857:             IF( JE.GT.1 ) THEN
                    858:                IF( S( JE, JE-1 ).NE.ZERO ) THEN
                    859:                   ILCPLX = .TRUE.
                    860:                   NW = 2
                    861:                END IF
                    862:             END IF
                    863:             IF( ILALL ) THEN
                    864:                ILCOMP = .TRUE.
                    865:             ELSE IF( ILCPLX ) THEN
                    866:                ILCOMP = SELECT( JE ) .OR. SELECT( JE-1 )
                    867:             ELSE
                    868:                ILCOMP = SELECT( JE )
                    869:             END IF
                    870:             IF( .NOT.ILCOMP )
                    871:      $         GO TO 500
                    872: *
                    873: *           Decide if (a) singular pencil, (b) real eigenvalue, or
                    874: *           (c) complex eigenvalue.
                    875: *
                    876:             IF( .NOT.ILCPLX ) THEN
                    877:                IF( ABS( S( JE, JE ) ).LE.SAFMIN .AND.
                    878:      $             ABS( P( JE, JE ) ).LE.SAFMIN ) THEN
                    879: *
                    880: *                 Singular matrix pencil -- unit eigenvector
                    881: *
                    882:                   IEIG = IEIG - 1
                    883:                   DO 230 JR = 1, N
                    884:                      VR( JR, IEIG ) = ZERO
                    885:   230             CONTINUE
                    886:                   VR( IEIG, IEIG ) = ONE
                    887:                   GO TO 500
                    888:                END IF
                    889:             END IF
                    890: *
                    891: *           Clear vector
                    892: *
                    893:             DO 250 JW = 0, NW - 1
                    894:                DO 240 JR = 1, N
                    895:                   WORK( ( JW+2 )*N+JR ) = ZERO
                    896:   240          CONTINUE
                    897:   250       CONTINUE
                    898: *
                    899: *           Compute coefficients in  ( a A - b B ) x = 0
                    900: *              a  is  ACOEF
                    901: *              b  is  BCOEFR + i*BCOEFI
                    902: *
                    903:             IF( .NOT.ILCPLX ) THEN
                    904: *
                    905: *              Real eigenvalue
                    906: *
                    907:                TEMP = ONE / MAX( ABS( S( JE, JE ) )*ASCALE,
                    908:      $                ABS( P( JE, JE ) )*BSCALE, SAFMIN )
                    909:                SALFAR = ( TEMP*S( JE, JE ) )*ASCALE
                    910:                SBETA = ( TEMP*P( JE, JE ) )*BSCALE
                    911:                ACOEF = SBETA*ASCALE
                    912:                BCOEFR = SALFAR*BSCALE
                    913:                BCOEFI = ZERO
                    914: *
                    915: *              Scale to avoid underflow
                    916: *
                    917:                SCALE = ONE
                    918:                LSA = ABS( SBETA ).GE.SAFMIN .AND. ABS( ACOEF ).LT.SMALL
                    919:                LSB = ABS( SALFAR ).GE.SAFMIN .AND. ABS( BCOEFR ).LT.
                    920:      $               SMALL
                    921:                IF( LSA )
                    922:      $            SCALE = ( SMALL / ABS( SBETA ) )*MIN( ANORM, BIG )
                    923:                IF( LSB )
                    924:      $            SCALE = MAX( SCALE, ( SMALL / ABS( SALFAR ) )*
                    925:      $                    MIN( BNORM, BIG ) )
                    926:                IF( LSA .OR. LSB ) THEN
                    927:                   SCALE = MIN( SCALE, ONE /
                    928:      $                    ( SAFMIN*MAX( ONE, ABS( ACOEF ),
                    929:      $                    ABS( BCOEFR ) ) ) )
                    930:                   IF( LSA ) THEN
                    931:                      ACOEF = ASCALE*( SCALE*SBETA )
                    932:                   ELSE
                    933:                      ACOEF = SCALE*ACOEF
                    934:                   END IF
                    935:                   IF( LSB ) THEN
                    936:                      BCOEFR = BSCALE*( SCALE*SALFAR )
                    937:                   ELSE
                    938:                      BCOEFR = SCALE*BCOEFR
                    939:                   END IF
                    940:                END IF
                    941:                ACOEFA = ABS( ACOEF )
                    942:                BCOEFA = ABS( BCOEFR )
                    943: *
                    944: *              First component is 1
                    945: *
                    946:                WORK( 2*N+JE ) = ONE
                    947:                XMAX = ONE
                    948: *
                    949: *              Compute contribution from column JE of A and B to sum
                    950: *              (See "Further Details", above.)
                    951: *
                    952:                DO 260 JR = 1, JE - 1
                    953:                   WORK( 2*N+JR ) = BCOEFR*P( JR, JE ) -
                    954:      $                             ACOEF*S( JR, JE )
                    955:   260          CONTINUE
                    956:             ELSE
                    957: *
                    958: *              Complex eigenvalue
                    959: *
                    960:                CALL DLAG2( S( JE-1, JE-1 ), LDS, P( JE-1, JE-1 ), LDP,
                    961:      $                     SAFMIN*SAFETY, ACOEF, TEMP, BCOEFR, TEMP2,
                    962:      $                     BCOEFI )
                    963:                IF( BCOEFI.EQ.ZERO ) THEN
                    964:                   INFO = JE - 1
                    965:                   RETURN
                    966:                END IF
                    967: *
                    968: *              Scale to avoid over/underflow
                    969: *
                    970:                ACOEFA = ABS( ACOEF )
                    971:                BCOEFA = ABS( BCOEFR ) + ABS( BCOEFI )
                    972:                SCALE = ONE
                    973:                IF( ACOEFA*ULP.LT.SAFMIN .AND. ACOEFA.GE.SAFMIN )
                    974:      $            SCALE = ( SAFMIN / ULP ) / ACOEFA
                    975:                IF( BCOEFA*ULP.LT.SAFMIN .AND. BCOEFA.GE.SAFMIN )
                    976:      $            SCALE = MAX( SCALE, ( SAFMIN / ULP ) / BCOEFA )
                    977:                IF( SAFMIN*ACOEFA.GT.ASCALE )
                    978:      $            SCALE = ASCALE / ( SAFMIN*ACOEFA )
                    979:                IF( SAFMIN*BCOEFA.GT.BSCALE )
                    980:      $            SCALE = MIN( SCALE, BSCALE / ( SAFMIN*BCOEFA ) )
                    981:                IF( SCALE.NE.ONE ) THEN
                    982:                   ACOEF = SCALE*ACOEF
                    983:                   ACOEFA = ABS( ACOEF )
                    984:                   BCOEFR = SCALE*BCOEFR
                    985:                   BCOEFI = SCALE*BCOEFI
                    986:                   BCOEFA = ABS( BCOEFR ) + ABS( BCOEFI )
                    987:                END IF
                    988: *
                    989: *              Compute first two components of eigenvector
                    990: *              and contribution to sums
                    991: *
                    992:                TEMP = ACOEF*S( JE, JE-1 )
                    993:                TEMP2R = ACOEF*S( JE, JE ) - BCOEFR*P( JE, JE )
                    994:                TEMP2I = -BCOEFI*P( JE, JE )
                    995:                IF( ABS( TEMP ).GE.ABS( TEMP2R )+ABS( TEMP2I ) ) THEN
                    996:                   WORK( 2*N+JE ) = ONE
                    997:                   WORK( 3*N+JE ) = ZERO
                    998:                   WORK( 2*N+JE-1 ) = -TEMP2R / TEMP
                    999:                   WORK( 3*N+JE-1 ) = -TEMP2I / TEMP
                   1000:                ELSE
                   1001:                   WORK( 2*N+JE-1 ) = ONE
                   1002:                   WORK( 3*N+JE-1 ) = ZERO
                   1003:                   TEMP = ACOEF*S( JE-1, JE )
                   1004:                   WORK( 2*N+JE ) = ( BCOEFR*P( JE-1, JE-1 )-ACOEF*
                   1005:      $                             S( JE-1, JE-1 ) ) / TEMP
                   1006:                   WORK( 3*N+JE ) = BCOEFI*P( JE-1, JE-1 ) / TEMP
                   1007:                END IF
                   1008: *
                   1009:                XMAX = MAX( ABS( WORK( 2*N+JE ) )+ABS( WORK( 3*N+JE ) ),
                   1010:      $                ABS( WORK( 2*N+JE-1 ) )+ABS( WORK( 3*N+JE-1 ) ) )
                   1011: *
                   1012: *              Compute contribution from columns JE and JE-1
                   1013: *              of A and B to the sums.
                   1014: *
                   1015:                CREALA = ACOEF*WORK( 2*N+JE-1 )
                   1016:                CIMAGA = ACOEF*WORK( 3*N+JE-1 )
                   1017:                CREALB = BCOEFR*WORK( 2*N+JE-1 ) -
                   1018:      $                  BCOEFI*WORK( 3*N+JE-1 )
                   1019:                CIMAGB = BCOEFI*WORK( 2*N+JE-1 ) +
                   1020:      $                  BCOEFR*WORK( 3*N+JE-1 )
                   1021:                CRE2A = ACOEF*WORK( 2*N+JE )
                   1022:                CIM2A = ACOEF*WORK( 3*N+JE )
                   1023:                CRE2B = BCOEFR*WORK( 2*N+JE ) - BCOEFI*WORK( 3*N+JE )
                   1024:                CIM2B = BCOEFI*WORK( 2*N+JE ) + BCOEFR*WORK( 3*N+JE )
                   1025:                DO 270 JR = 1, JE - 2
                   1026:                   WORK( 2*N+JR ) = -CREALA*S( JR, JE-1 ) +
                   1027:      $                             CREALB*P( JR, JE-1 ) -
                   1028:      $                             CRE2A*S( JR, JE ) + CRE2B*P( JR, JE )
                   1029:                   WORK( 3*N+JR ) = -CIMAGA*S( JR, JE-1 ) +
                   1030:      $                             CIMAGB*P( JR, JE-1 ) -
                   1031:      $                             CIM2A*S( JR, JE ) + CIM2B*P( JR, JE )
                   1032:   270          CONTINUE
                   1033:             END IF
                   1034: *
                   1035:             DMIN = MAX( ULP*ACOEFA*ANORM, ULP*BCOEFA*BNORM, SAFMIN )
                   1036: *
                   1037: *           Columnwise triangular solve of  (a A - b B)  x = 0
                   1038: *
                   1039:             IL2BY2 = .FALSE.
                   1040:             DO 370 J = JE - NW, 1, -1
                   1041: *
                   1042: *              If a 2-by-2 block, is in position j-1:j, wait until
                   1043: *              next iteration to process it (when it will be j:j+1)
                   1044: *
                   1045:                IF( .NOT.IL2BY2 .AND. J.GT.1 ) THEN
                   1046:                   IF( S( J, J-1 ).NE.ZERO ) THEN
                   1047:                      IL2BY2 = .TRUE.
                   1048:                      GO TO 370
                   1049:                   END IF
                   1050:                END IF
                   1051:                BDIAG( 1 ) = P( J, J )
                   1052:                IF( IL2BY2 ) THEN
                   1053:                   NA = 2
                   1054:                   BDIAG( 2 ) = P( J+1, J+1 )
                   1055:                ELSE
                   1056:                   NA = 1
                   1057:                END IF
                   1058: *
                   1059: *              Compute x(j) (and x(j+1), if 2-by-2 block)
                   1060: *
                   1061:                CALL DLALN2( .FALSE., NA, NW, DMIN, ACOEF, S( J, J ),
                   1062:      $                      LDS, BDIAG( 1 ), BDIAG( 2 ), WORK( 2*N+J ),
                   1063:      $                      N, BCOEFR, BCOEFI, SUM, 2, SCALE, TEMP,
                   1064:      $                      IINFO )
                   1065:                IF( SCALE.LT.ONE ) THEN
                   1066: *
                   1067:                   DO 290 JW = 0, NW - 1
                   1068:                      DO 280 JR = 1, JE
                   1069:                         WORK( ( JW+2 )*N+JR ) = SCALE*
                   1070:      $                     WORK( ( JW+2 )*N+JR )
                   1071:   280                CONTINUE
                   1072:   290             CONTINUE
                   1073:                END IF
                   1074:                XMAX = MAX( SCALE*XMAX, TEMP )
                   1075: *
                   1076:                DO 310 JW = 1, NW
                   1077:                   DO 300 JA = 1, NA
                   1078:                      WORK( ( JW+1 )*N+J+JA-1 ) = SUM( JA, JW )
                   1079:   300             CONTINUE
                   1080:   310          CONTINUE
                   1081: *
                   1082: *              w = w + x(j)*(a S(*,j) - b P(*,j) ) with scaling
                   1083: *
                   1084:                IF( J.GT.1 ) THEN
                   1085: *
                   1086: *                 Check whether scaling is necessary for sum.
                   1087: *
                   1088:                   XSCALE = ONE / MAX( ONE, XMAX )
                   1089:                   TEMP = ACOEFA*WORK( J ) + BCOEFA*WORK( N+J )
                   1090:                   IF( IL2BY2 )
                   1091:      $               TEMP = MAX( TEMP, ACOEFA*WORK( J+1 )+BCOEFA*
                   1092:      $                      WORK( N+J+1 ) )
                   1093:                   TEMP = MAX( TEMP, ACOEFA, BCOEFA )
                   1094:                   IF( TEMP.GT.BIGNUM*XSCALE ) THEN
                   1095: *
                   1096:                      DO 330 JW = 0, NW - 1
                   1097:                         DO 320 JR = 1, JE
                   1098:                            WORK( ( JW+2 )*N+JR ) = XSCALE*
                   1099:      $                        WORK( ( JW+2 )*N+JR )
                   1100:   320                   CONTINUE
                   1101:   330                CONTINUE
                   1102:                      XMAX = XMAX*XSCALE
                   1103:                   END IF
                   1104: *
                   1105: *                 Compute the contributions of the off-diagonals of
                   1106: *                 column j (and j+1, if 2-by-2 block) of A and B to the
                   1107: *                 sums.
                   1108: *
                   1109: *
                   1110:                   DO 360 JA = 1, NA
                   1111:                      IF( ILCPLX ) THEN
                   1112:                         CREALA = ACOEF*WORK( 2*N+J+JA-1 )
                   1113:                         CIMAGA = ACOEF*WORK( 3*N+J+JA-1 )
                   1114:                         CREALB = BCOEFR*WORK( 2*N+J+JA-1 ) -
                   1115:      $                           BCOEFI*WORK( 3*N+J+JA-1 )
                   1116:                         CIMAGB = BCOEFI*WORK( 2*N+J+JA-1 ) +
                   1117:      $                           BCOEFR*WORK( 3*N+J+JA-1 )
                   1118:                         DO 340 JR = 1, J - 1
                   1119:                            WORK( 2*N+JR ) = WORK( 2*N+JR ) -
                   1120:      $                                      CREALA*S( JR, J+JA-1 ) +
                   1121:      $                                      CREALB*P( JR, J+JA-1 )
                   1122:                            WORK( 3*N+JR ) = WORK( 3*N+JR ) -
                   1123:      $                                      CIMAGA*S( JR, J+JA-1 ) +
                   1124:      $                                      CIMAGB*P( JR, J+JA-1 )
                   1125:   340                   CONTINUE
                   1126:                      ELSE
                   1127:                         CREALA = ACOEF*WORK( 2*N+J+JA-1 )
                   1128:                         CREALB = BCOEFR*WORK( 2*N+J+JA-1 )
                   1129:                         DO 350 JR = 1, J - 1
                   1130:                            WORK( 2*N+JR ) = WORK( 2*N+JR ) -
                   1131:      $                                      CREALA*S( JR, J+JA-1 ) +
                   1132:      $                                      CREALB*P( JR, J+JA-1 )
                   1133:   350                   CONTINUE
                   1134:                      END IF
                   1135:   360             CONTINUE
                   1136:                END IF
                   1137: *
                   1138:                IL2BY2 = .FALSE.
                   1139:   370       CONTINUE
                   1140: *
                   1141: *           Copy eigenvector to VR, back transforming if
                   1142: *           HOWMNY='B'.
                   1143: *
                   1144:             IEIG = IEIG - NW
                   1145:             IF( ILBACK ) THEN
                   1146: *
                   1147:                DO 410 JW = 0, NW - 1
                   1148:                   DO 380 JR = 1, N
                   1149:                      WORK( ( JW+4 )*N+JR ) = WORK( ( JW+2 )*N+1 )*
                   1150:      $                                       VR( JR, 1 )
                   1151:   380             CONTINUE
                   1152: *
                   1153: *                 A series of compiler directives to defeat
                   1154: *                 vectorization for the next loop
                   1155: *
                   1156: *
                   1157:                   DO 400 JC = 2, JE
                   1158:                      DO 390 JR = 1, N
                   1159:                         WORK( ( JW+4 )*N+JR ) = WORK( ( JW+4 )*N+JR ) +
                   1160:      $                     WORK( ( JW+2 )*N+JC )*VR( JR, JC )
                   1161:   390                CONTINUE
                   1162:   400             CONTINUE
                   1163:   410          CONTINUE
                   1164: *
                   1165:                DO 430 JW = 0, NW - 1
                   1166:                   DO 420 JR = 1, N
                   1167:                      VR( JR, IEIG+JW ) = WORK( ( JW+4 )*N+JR )
                   1168:   420             CONTINUE
                   1169:   430          CONTINUE
                   1170: *
                   1171:                IEND = N
                   1172:             ELSE
                   1173:                DO 450 JW = 0, NW - 1
                   1174:                   DO 440 JR = 1, N
                   1175:                      VR( JR, IEIG+JW ) = WORK( ( JW+2 )*N+JR )
                   1176:   440             CONTINUE
                   1177:   450          CONTINUE
                   1178: *
                   1179:                IEND = JE
                   1180:             END IF
                   1181: *
                   1182: *           Scale eigenvector
                   1183: *
                   1184:             XMAX = ZERO
                   1185:             IF( ILCPLX ) THEN
                   1186:                DO 460 J = 1, IEND
                   1187:                   XMAX = MAX( XMAX, ABS( VR( J, IEIG ) )+
                   1188:      $                   ABS( VR( J, IEIG+1 ) ) )
                   1189:   460          CONTINUE
                   1190:             ELSE
                   1191:                DO 470 J = 1, IEND
                   1192:                   XMAX = MAX( XMAX, ABS( VR( J, IEIG ) ) )
                   1193:   470          CONTINUE
                   1194:             END IF
                   1195: *
                   1196:             IF( XMAX.GT.SAFMIN ) THEN
                   1197:                XSCALE = ONE / XMAX
                   1198:                DO 490 JW = 0, NW - 1
                   1199:                   DO 480 JR = 1, IEND
                   1200:                      VR( JR, IEIG+JW ) = XSCALE*VR( JR, IEIG+JW )
                   1201:   480             CONTINUE
                   1202:   490          CONTINUE
                   1203:             END IF
                   1204:   500    CONTINUE
                   1205:       END IF
                   1206: *
                   1207:       RETURN
                   1208: *
                   1209: *     End of DTGEVC
                   1210: *
                   1211:       END

CVSweb interface <joel.bertrand@systella.fr>