File:  [local] / rpl / lapack / lapack / dtgevc.f
Revision 1.18: download - view: text, annotated - select for diffs - revision graph
Mon Aug 7 08:39:12 2023 UTC (8 months, 3 weeks ago) by bertrand
Branches: MAIN
CVS tags: rpl-4_1_35, rpl-4_1_34, HEAD
Première mise à jour de lapack et blas.

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

CVSweb interface <joel.bertrand@systella.fr>