File:  [local] / rpl / lapack / lapack / dggesx.f
Revision 1.19: download - view: text, annotated - select for diffs - revision graph
Mon Aug 7 08:38:51 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> DGGESX computes the eigenvalues, the Schur form, and, optionally, the matrix of Schur vectors for GE matrices</b>
    2: *
    3: *  =========== DOCUMENTATION ===========
    4: *
    5: * Online html documentation available at
    6: *            http://www.netlib.org/lapack/explore-html/
    7: *
    8: *> \htmlonly
    9: *> Download DGGESX + dependencies
   10: *> <a href="http://www.netlib.org/cgi-bin/netlibfiles.tgz?format=tgz&filename=/lapack/lapack_routine/dggesx.f">
   11: *> [TGZ]</a>
   12: *> <a href="http://www.netlib.org/cgi-bin/netlibfiles.zip?format=zip&filename=/lapack/lapack_routine/dggesx.f">
   13: *> [ZIP]</a>
   14: *> <a href="http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/dggesx.f">
   15: *> [TXT]</a>
   16: *> \endhtmlonly
   17: *
   18: *  Definition:
   19: *  ===========
   20: *
   21: *       SUBROUTINE DGGESX( JOBVSL, JOBVSR, SORT, SELCTG, SENSE, N, A, LDA,
   22: *                          B, LDB, SDIM, ALPHAR, ALPHAI, BETA, VSL, LDVSL,
   23: *                          VSR, LDVSR, RCONDE, RCONDV, WORK, LWORK, IWORK,
   24: *                          LIWORK, BWORK, INFO )
   25: *
   26: *       .. Scalar Arguments ..
   27: *       CHARACTER          JOBVSL, JOBVSR, SENSE, SORT
   28: *       INTEGER            INFO, LDA, LDB, LDVSL, LDVSR, LIWORK, LWORK, N,
   29: *      $                   SDIM
   30: *       ..
   31: *       .. Array Arguments ..
   32: *       LOGICAL            BWORK( * )
   33: *       INTEGER            IWORK( * )
   34: *       DOUBLE PRECISION   A( LDA, * ), ALPHAI( * ), ALPHAR( * ),
   35: *      $                   B( LDB, * ), BETA( * ), RCONDE( 2 ),
   36: *      $                   RCONDV( 2 ), VSL( LDVSL, * ), VSR( LDVSR, * ),
   37: *      $                   WORK( * )
   38: *       ..
   39: *       .. Function Arguments ..
   40: *       LOGICAL            SELCTG
   41: *       EXTERNAL           SELCTG
   42: *       ..
   43: *
   44: *
   45: *> \par Purpose:
   46: *  =============
   47: *>
   48: *> \verbatim
   49: *>
   50: *> DGGESX computes for a pair of N-by-N real nonsymmetric matrices
   51: *> (A,B), the generalized eigenvalues, the real Schur form (S,T), and,
   52: *> optionally, the left and/or right matrices of Schur vectors (VSL and
   53: *> VSR).  This gives the generalized Schur factorization
   54: *>
   55: *>      (A,B) = ( (VSL) S (VSR)**T, (VSL) T (VSR)**T )
   56: *>
   57: *> Optionally, it also orders the eigenvalues so that a selected cluster
   58: *> of eigenvalues appears in the leading diagonal blocks of the upper
   59: *> quasi-triangular matrix S and the upper triangular matrix T; computes
   60: *> a reciprocal condition number for the average of the selected
   61: *> eigenvalues (RCONDE); and computes a reciprocal condition number for
   62: *> the right and left deflating subspaces corresponding to the selected
   63: *> eigenvalues (RCONDV). The leading columns of VSL and VSR then form
   64: *> an orthonormal basis for the corresponding left and right eigenspaces
   65: *> (deflating subspaces).
   66: *>
   67: *> A generalized eigenvalue for a pair of matrices (A,B) is a scalar w
   68: *> or a ratio alpha/beta = w, such that  A - w*B is singular.  It is
   69: *> usually represented as the pair (alpha,beta), as there is a
   70: *> reasonable interpretation for beta=0 or for both being zero.
   71: *>
   72: *> A pair of matrices (S,T) is in generalized real Schur form if T is
   73: *> upper triangular with non-negative diagonal and S is block upper
   74: *> triangular with 1-by-1 and 2-by-2 blocks.  1-by-1 blocks correspond
   75: *> to real generalized eigenvalues, while 2-by-2 blocks of S will be
   76: *> "standardized" by making the corresponding elements of T have the
   77: *> form:
   78: *>         [  a  0  ]
   79: *>         [  0  b  ]
   80: *>
   81: *> and the pair of corresponding 2-by-2 blocks in S and T will have a
   82: *> complex conjugate pair of generalized eigenvalues.
   83: *>
   84: *> \endverbatim
   85: *
   86: *  Arguments:
   87: *  ==========
   88: *
   89: *> \param[in] JOBVSL
   90: *> \verbatim
   91: *>          JOBVSL is CHARACTER*1
   92: *>          = 'N':  do not compute the left Schur vectors;
   93: *>          = 'V':  compute the left Schur vectors.
   94: *> \endverbatim
   95: *>
   96: *> \param[in] JOBVSR
   97: *> \verbatim
   98: *>          JOBVSR is CHARACTER*1
   99: *>          = 'N':  do not compute the right Schur vectors;
  100: *>          = 'V':  compute the right Schur vectors.
  101: *> \endverbatim
  102: *>
  103: *> \param[in] SORT
  104: *> \verbatim
  105: *>          SORT is CHARACTER*1
  106: *>          Specifies whether or not to order the eigenvalues on the
  107: *>          diagonal of the generalized Schur form.
  108: *>          = 'N':  Eigenvalues are not ordered;
  109: *>          = 'S':  Eigenvalues are ordered (see SELCTG).
  110: *> \endverbatim
  111: *>
  112: *> \param[in] SELCTG
  113: *> \verbatim
  114: *>          SELCTG is a LOGICAL FUNCTION of three DOUBLE PRECISION arguments
  115: *>          SELCTG must be declared EXTERNAL in the calling subroutine.
  116: *>          If SORT = 'N', SELCTG is not referenced.
  117: *>          If SORT = 'S', SELCTG is used to select eigenvalues to sort
  118: *>          to the top left of the Schur form.
  119: *>          An eigenvalue (ALPHAR(j)+ALPHAI(j))/BETA(j) is selected if
  120: *>          SELCTG(ALPHAR(j),ALPHAI(j),BETA(j)) is true; i.e. if either
  121: *>          one of a complex conjugate pair of eigenvalues is selected,
  122: *>          then both complex eigenvalues are selected.
  123: *>          Note that a selected complex eigenvalue may no longer satisfy
  124: *>          SELCTG(ALPHAR(j),ALPHAI(j),BETA(j)) = .TRUE. after ordering,
  125: *>          since ordering may change the value of complex eigenvalues
  126: *>          (especially if the eigenvalue is ill-conditioned), in this
  127: *>          case INFO is set to N+3.
  128: *> \endverbatim
  129: *>
  130: *> \param[in] SENSE
  131: *> \verbatim
  132: *>          SENSE is CHARACTER*1
  133: *>          Determines which reciprocal condition numbers are computed.
  134: *>          = 'N':  None are computed;
  135: *>          = 'E':  Computed for average of selected eigenvalues only;
  136: *>          = 'V':  Computed for selected deflating subspaces only;
  137: *>          = 'B':  Computed for both.
  138: *>          If SENSE = 'E', 'V', or 'B', SORT must equal 'S'.
  139: *> \endverbatim
  140: *>
  141: *> \param[in] N
  142: *> \verbatim
  143: *>          N is INTEGER
  144: *>          The order of the matrices A, B, VSL, and VSR.  N >= 0.
  145: *> \endverbatim
  146: *>
  147: *> \param[in,out] A
  148: *> \verbatim
  149: *>          A is DOUBLE PRECISION array, dimension (LDA, N)
  150: *>          On entry, the first of the pair of matrices.
  151: *>          On exit, A has been overwritten by its generalized Schur
  152: *>          form S.
  153: *> \endverbatim
  154: *>
  155: *> \param[in] LDA
  156: *> \verbatim
  157: *>          LDA is INTEGER
  158: *>          The leading dimension of A.  LDA >= max(1,N).
  159: *> \endverbatim
  160: *>
  161: *> \param[in,out] B
  162: *> \verbatim
  163: *>          B is DOUBLE PRECISION array, dimension (LDB, N)
  164: *>          On entry, the second of the pair of matrices.
  165: *>          On exit, B has been overwritten by its generalized Schur
  166: *>          form T.
  167: *> \endverbatim
  168: *>
  169: *> \param[in] LDB
  170: *> \verbatim
  171: *>          LDB is INTEGER
  172: *>          The leading dimension of B.  LDB >= max(1,N).
  173: *> \endverbatim
  174: *>
  175: *> \param[out] SDIM
  176: *> \verbatim
  177: *>          SDIM is INTEGER
  178: *>          If SORT = 'N', SDIM = 0.
  179: *>          If SORT = 'S', SDIM = number of eigenvalues (after sorting)
  180: *>          for which SELCTG is true.  (Complex conjugate pairs for which
  181: *>          SELCTG is true for either eigenvalue count as 2.)
  182: *> \endverbatim
  183: *>
  184: *> \param[out] ALPHAR
  185: *> \verbatim
  186: *>          ALPHAR is DOUBLE PRECISION array, dimension (N)
  187: *> \endverbatim
  188: *>
  189: *> \param[out] ALPHAI
  190: *> \verbatim
  191: *>          ALPHAI is DOUBLE PRECISION array, dimension (N)
  192: *> \endverbatim
  193: *>
  194: *> \param[out] BETA
  195: *> \verbatim
  196: *>          BETA is DOUBLE PRECISION array, dimension (N)
  197: *>          On exit, (ALPHAR(j) + ALPHAI(j)*i)/BETA(j), j=1,...,N, will
  198: *>          be the generalized eigenvalues.  ALPHAR(j) + ALPHAI(j)*i
  199: *>          and BETA(j),j=1,...,N  are the diagonals of the complex Schur
  200: *>          form (S,T) that would result if the 2-by-2 diagonal blocks of
  201: *>          the real Schur form of (A,B) were further reduced to
  202: *>          triangular form using 2-by-2 complex unitary transformations.
  203: *>          If ALPHAI(j) is zero, then the j-th eigenvalue is real; if
  204: *>          positive, then the j-th and (j+1)-st eigenvalues are a
  205: *>          complex conjugate pair, with ALPHAI(j+1) negative.
  206: *>
  207: *>          Note: the quotients ALPHAR(j)/BETA(j) and ALPHAI(j)/BETA(j)
  208: *>          may easily over- or underflow, and BETA(j) may even be zero.
  209: *>          Thus, the user should avoid naively computing the ratio.
  210: *>          However, ALPHAR and ALPHAI will be always less than and
  211: *>          usually comparable with norm(A) in magnitude, and BETA always
  212: *>          less than and usually comparable with norm(B).
  213: *> \endverbatim
  214: *>
  215: *> \param[out] VSL
  216: *> \verbatim
  217: *>          VSL is DOUBLE PRECISION array, dimension (LDVSL,N)
  218: *>          If JOBVSL = 'V', VSL will contain the left Schur vectors.
  219: *>          Not referenced if JOBVSL = 'N'.
  220: *> \endverbatim
  221: *>
  222: *> \param[in] LDVSL
  223: *> \verbatim
  224: *>          LDVSL is INTEGER
  225: *>          The leading dimension of the matrix VSL. LDVSL >=1, and
  226: *>          if JOBVSL = 'V', LDVSL >= N.
  227: *> \endverbatim
  228: *>
  229: *> \param[out] VSR
  230: *> \verbatim
  231: *>          VSR is DOUBLE PRECISION array, dimension (LDVSR,N)
  232: *>          If JOBVSR = 'V', VSR will contain the right Schur vectors.
  233: *>          Not referenced if JOBVSR = 'N'.
  234: *> \endverbatim
  235: *>
  236: *> \param[in] LDVSR
  237: *> \verbatim
  238: *>          LDVSR is INTEGER
  239: *>          The leading dimension of the matrix VSR. LDVSR >= 1, and
  240: *>          if JOBVSR = 'V', LDVSR >= N.
  241: *> \endverbatim
  242: *>
  243: *> \param[out] RCONDE
  244: *> \verbatim
  245: *>          RCONDE is DOUBLE PRECISION array, dimension ( 2 )
  246: *>          If SENSE = 'E' or 'B', RCONDE(1) and RCONDE(2) contain the
  247: *>          reciprocal condition numbers for the average of the selected
  248: *>          eigenvalues.
  249: *>          Not referenced if SENSE = 'N' or 'V'.
  250: *> \endverbatim
  251: *>
  252: *> \param[out] RCONDV
  253: *> \verbatim
  254: *>          RCONDV is DOUBLE PRECISION array, dimension ( 2 )
  255: *>          If SENSE = 'V' or 'B', RCONDV(1) and RCONDV(2) contain the
  256: *>          reciprocal condition numbers for the selected deflating
  257: *>          subspaces.
  258: *>          Not referenced if SENSE = 'N' or 'E'.
  259: *> \endverbatim
  260: *>
  261: *> \param[out] WORK
  262: *> \verbatim
  263: *>          WORK is DOUBLE PRECISION array, dimension (MAX(1,LWORK))
  264: *>          On exit, if INFO = 0, WORK(1) returns the optimal LWORK.
  265: *> \endverbatim
  266: *>
  267: *> \param[in] LWORK
  268: *> \verbatim
  269: *>          LWORK is INTEGER
  270: *>          The dimension of the array WORK.
  271: *>          If N = 0, LWORK >= 1, else if SENSE = 'E', 'V', or 'B',
  272: *>          LWORK >= max( 8*N, 6*N+16, 2*SDIM*(N-SDIM) ), else
  273: *>          LWORK >= max( 8*N, 6*N+16 ).
  274: *>          Note that 2*SDIM*(N-SDIM) <= N*N/2.
  275: *>          Note also that an error is only returned if
  276: *>          LWORK < max( 8*N, 6*N+16), but if SENSE = 'E' or 'V' or 'B'
  277: *>          this may not be large enough.
  278: *>
  279: *>          If LWORK = -1, then a workspace query is assumed; the routine
  280: *>          only calculates the bound on the optimal size of the WORK
  281: *>          array and the minimum size of the IWORK array, returns these
  282: *>          values as the first entries of the WORK and IWORK arrays, and
  283: *>          no error message related to LWORK or LIWORK is issued by
  284: *>          XERBLA.
  285: *> \endverbatim
  286: *>
  287: *> \param[out] IWORK
  288: *> \verbatim
  289: *>          IWORK is INTEGER array, dimension (MAX(1,LIWORK))
  290: *>          On exit, if INFO = 0, IWORK(1) returns the minimum LIWORK.
  291: *> \endverbatim
  292: *>
  293: *> \param[in] LIWORK
  294: *> \verbatim
  295: *>          LIWORK is INTEGER
  296: *>          The dimension of the array IWORK.
  297: *>          If SENSE = 'N' or N = 0, LIWORK >= 1, otherwise
  298: *>          LIWORK >= N+6.
  299: *>
  300: *>          If LIWORK = -1, then a workspace query is assumed; the
  301: *>          routine only calculates the bound on the optimal size of the
  302: *>          WORK array and the minimum size of the IWORK array, returns
  303: *>          these values as the first entries of the WORK and IWORK
  304: *>          arrays, and no error message related to LWORK or LIWORK is
  305: *>          issued by XERBLA.
  306: *> \endverbatim
  307: *>
  308: *> \param[out] BWORK
  309: *> \verbatim
  310: *>          BWORK is LOGICAL array, dimension (N)
  311: *>          Not referenced if SORT = 'N'.
  312: *> \endverbatim
  313: *>
  314: *> \param[out] INFO
  315: *> \verbatim
  316: *>          INFO is INTEGER
  317: *>          = 0:  successful exit
  318: *>          < 0:  if INFO = -i, the i-th argument had an illegal value.
  319: *>          = 1,...,N:
  320: *>                The QZ iteration failed.  (A,B) are not in Schur
  321: *>                form, but ALPHAR(j), ALPHAI(j), and BETA(j) should
  322: *>                be correct for j=INFO+1,...,N.
  323: *>          > N:  =N+1: other than QZ iteration failed in DHGEQZ
  324: *>                =N+2: after reordering, roundoff changed values of
  325: *>                      some complex eigenvalues so that leading
  326: *>                      eigenvalues in the Generalized Schur form no
  327: *>                      longer satisfy SELCTG=.TRUE.  This could also
  328: *>                      be caused due to scaling.
  329: *>                =N+3: reordering failed in DTGSEN.
  330: *> \endverbatim
  331: *
  332: *  Authors:
  333: *  ========
  334: *
  335: *> \author Univ. of Tennessee
  336: *> \author Univ. of California Berkeley
  337: *> \author Univ. of Colorado Denver
  338: *> \author NAG Ltd.
  339: *
  340: *> \ingroup doubleGEeigen
  341: *
  342: *> \par Further Details:
  343: *  =====================
  344: *>
  345: *> \verbatim
  346: *>
  347: *>  An approximate (asymptotic) bound on the average absolute error of
  348: *>  the selected eigenvalues is
  349: *>
  350: *>       EPS * norm((A, B)) / RCONDE( 1 ).
  351: *>
  352: *>  An approximate (asymptotic) bound on the maximum angular error in
  353: *>  the computed deflating subspaces is
  354: *>
  355: *>       EPS * norm((A, B)) / RCONDV( 2 ).
  356: *>
  357: *>  See LAPACK User's Guide, section 4.11 for more information.
  358: *> \endverbatim
  359: *>
  360: *  =====================================================================
  361:       SUBROUTINE DGGESX( JOBVSL, JOBVSR, SORT, SELCTG, SENSE, N, A, LDA,
  362:      $                   B, LDB, SDIM, ALPHAR, ALPHAI, BETA, VSL, LDVSL,
  363:      $                   VSR, LDVSR, RCONDE, RCONDV, WORK, LWORK, IWORK,
  364:      $                   LIWORK, BWORK, INFO )
  365: *
  366: *  -- LAPACK driver routine --
  367: *  -- LAPACK is a software package provided by Univ. of Tennessee,    --
  368: *  -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..--
  369: *
  370: *     .. Scalar Arguments ..
  371:       CHARACTER          JOBVSL, JOBVSR, SENSE, SORT
  372:       INTEGER            INFO, LDA, LDB, LDVSL, LDVSR, LIWORK, LWORK, N,
  373:      $                   SDIM
  374: *     ..
  375: *     .. Array Arguments ..
  376:       LOGICAL            BWORK( * )
  377:       INTEGER            IWORK( * )
  378:       DOUBLE PRECISION   A( LDA, * ), ALPHAI( * ), ALPHAR( * ),
  379:      $                   B( LDB, * ), BETA( * ), RCONDE( 2 ),
  380:      $                   RCONDV( 2 ), VSL( LDVSL, * ), VSR( LDVSR, * ),
  381:      $                   WORK( * )
  382: *     ..
  383: *     .. Function Arguments ..
  384:       LOGICAL            SELCTG
  385:       EXTERNAL           SELCTG
  386: *     ..
  387: *
  388: *  =====================================================================
  389: *
  390: *     .. Parameters ..
  391:       DOUBLE PRECISION   ZERO, ONE
  392:       PARAMETER          ( ZERO = 0.0D+0, ONE = 1.0D+0 )
  393: *     ..
  394: *     .. Local Scalars ..
  395:       LOGICAL            CURSL, ILASCL, ILBSCL, ILVSL, ILVSR, LASTSL,
  396:      $                   LQUERY, LST2SL, WANTSB, WANTSE, WANTSN, WANTST,
  397:      $                   WANTSV
  398:       INTEGER            I, ICOLS, IERR, IHI, IJOB, IJOBVL, IJOBVR,
  399:      $                   ILEFT, ILO, IP, IRIGHT, IROWS, ITAU, IWRK,
  400:      $                   LIWMIN, LWRK, MAXWRK, MINWRK
  401:       DOUBLE PRECISION   ANRM, ANRMTO, BIGNUM, BNRM, BNRMTO, EPS, PL,
  402:      $                   PR, SAFMAX, SAFMIN, SMLNUM
  403: *     ..
  404: *     .. Local Arrays ..
  405:       DOUBLE PRECISION   DIF( 2 )
  406: *     ..
  407: *     .. External Subroutines ..
  408:       EXTERNAL           DGEQRF, DGGBAK, DGGBAL, DGGHRD, DHGEQZ, DLABAD,
  409:      $                   DLACPY, DLASCL, DLASET, DORGQR, DORMQR, DTGSEN,
  410:      $                   XERBLA
  411: *     ..
  412: *     .. External Functions ..
  413:       LOGICAL            LSAME
  414:       INTEGER            ILAENV
  415:       DOUBLE PRECISION   DLAMCH, DLANGE
  416:       EXTERNAL           LSAME, ILAENV, DLAMCH, DLANGE
  417: *     ..
  418: *     .. Intrinsic Functions ..
  419:       INTRINSIC          ABS, MAX, SQRT
  420: *     ..
  421: *     .. Executable Statements ..
  422: *
  423: *     Decode the input arguments
  424: *
  425:       IF( LSAME( JOBVSL, 'N' ) ) THEN
  426:          IJOBVL = 1
  427:          ILVSL = .FALSE.
  428:       ELSE IF( LSAME( JOBVSL, 'V' ) ) THEN
  429:          IJOBVL = 2
  430:          ILVSL = .TRUE.
  431:       ELSE
  432:          IJOBVL = -1
  433:          ILVSL = .FALSE.
  434:       END IF
  435: *
  436:       IF( LSAME( JOBVSR, 'N' ) ) THEN
  437:          IJOBVR = 1
  438:          ILVSR = .FALSE.
  439:       ELSE IF( LSAME( JOBVSR, 'V' ) ) THEN
  440:          IJOBVR = 2
  441:          ILVSR = .TRUE.
  442:       ELSE
  443:          IJOBVR = -1
  444:          ILVSR = .FALSE.
  445:       END IF
  446: *
  447:       WANTST = LSAME( SORT, 'S' )
  448:       WANTSN = LSAME( SENSE, 'N' )
  449:       WANTSE = LSAME( SENSE, 'E' )
  450:       WANTSV = LSAME( SENSE, 'V' )
  451:       WANTSB = LSAME( SENSE, 'B' )
  452:       LQUERY = ( LWORK.EQ.-1 .OR. LIWORK.EQ.-1 )
  453:       IF( WANTSN ) THEN
  454:          IJOB = 0
  455:       ELSE IF( WANTSE ) THEN
  456:          IJOB = 1
  457:       ELSE IF( WANTSV ) THEN
  458:          IJOB = 2
  459:       ELSE IF( WANTSB ) THEN
  460:          IJOB = 4
  461:       END IF
  462: *
  463: *     Test the input arguments
  464: *
  465:       INFO = 0
  466:       IF( IJOBVL.LE.0 ) THEN
  467:          INFO = -1
  468:       ELSE IF( IJOBVR.LE.0 ) THEN
  469:          INFO = -2
  470:       ELSE IF( ( .NOT.WANTST ) .AND. ( .NOT.LSAME( SORT, 'N' ) ) ) THEN
  471:          INFO = -3
  472:       ELSE IF( .NOT.( WANTSN .OR. WANTSE .OR. WANTSV .OR. WANTSB ) .OR.
  473:      $         ( .NOT.WANTST .AND. .NOT.WANTSN ) ) THEN
  474:          INFO = -5
  475:       ELSE IF( N.LT.0 ) THEN
  476:          INFO = -6
  477:       ELSE IF( LDA.LT.MAX( 1, N ) ) THEN
  478:          INFO = -8
  479:       ELSE IF( LDB.LT.MAX( 1, N ) ) THEN
  480:          INFO = -10
  481:       ELSE IF( LDVSL.LT.1 .OR. ( ILVSL .AND. LDVSL.LT.N ) ) THEN
  482:          INFO = -16
  483:       ELSE IF( LDVSR.LT.1 .OR. ( ILVSR .AND. LDVSR.LT.N ) ) THEN
  484:          INFO = -18
  485:       END IF
  486: *
  487: *     Compute workspace
  488: *      (Note: Comments in the code beginning "Workspace:" describe the
  489: *       minimal amount of workspace needed at that point in the code,
  490: *       as well as the preferred amount for good performance.
  491: *       NB refers to the optimal block size for the immediately
  492: *       following subroutine, as returned by ILAENV.)
  493: *
  494:       IF( INFO.EQ.0 ) THEN
  495:          IF( N.GT.0) THEN
  496:             MINWRK = MAX( 8*N, 6*N + 16 )
  497:             MAXWRK = MINWRK - N +
  498:      $               N*ILAENV( 1, 'DGEQRF', ' ', N, 1, N, 0 )
  499:             MAXWRK = MAX( MAXWRK, MINWRK - N +
  500:      $               N*ILAENV( 1, 'DORMQR', ' ', N, 1, N, -1 ) )
  501:             IF( ILVSL ) THEN
  502:                MAXWRK = MAX( MAXWRK, MINWRK - N +
  503:      $                  N*ILAENV( 1, 'DORGQR', ' ', N, 1, N, -1 ) )
  504:             END IF
  505:             LWRK = MAXWRK
  506:             IF( IJOB.GE.1 )
  507:      $         LWRK = MAX( LWRK, N*N/2 )
  508:          ELSE
  509:             MINWRK = 1
  510:             MAXWRK = 1
  511:             LWRK   = 1
  512:          END IF
  513:          WORK( 1 ) = LWRK
  514:          IF( WANTSN .OR. N.EQ.0 ) THEN
  515:             LIWMIN = 1
  516:          ELSE
  517:             LIWMIN = N + 6
  518:          END IF
  519:          IWORK( 1 ) = LIWMIN
  520: *
  521:          IF( LWORK.LT.MINWRK .AND. .NOT.LQUERY ) THEN
  522:             INFO = -22
  523:          ELSE IF( LIWORK.LT.LIWMIN  .AND. .NOT.LQUERY ) THEN
  524:             INFO = -24
  525:          END IF
  526:       END IF
  527: *
  528:       IF( INFO.NE.0 ) THEN
  529:          CALL XERBLA( 'DGGESX', -INFO )
  530:          RETURN
  531:       ELSE IF (LQUERY) THEN
  532:          RETURN
  533:       END IF
  534: *
  535: *     Quick return if possible
  536: *
  537:       IF( N.EQ.0 ) THEN
  538:          SDIM = 0
  539:          RETURN
  540:       END IF
  541: *
  542: *     Get machine constants
  543: *
  544:       EPS = DLAMCH( 'P' )
  545:       SAFMIN = DLAMCH( 'S' )
  546:       SAFMAX = ONE / SAFMIN
  547:       CALL DLABAD( SAFMIN, SAFMAX )
  548:       SMLNUM = SQRT( SAFMIN ) / EPS
  549:       BIGNUM = ONE / SMLNUM
  550: *
  551: *     Scale A if max element outside range [SMLNUM,BIGNUM]
  552: *
  553:       ANRM = DLANGE( 'M', N, N, A, LDA, WORK )
  554:       ILASCL = .FALSE.
  555:       IF( ANRM.GT.ZERO .AND. ANRM.LT.SMLNUM ) THEN
  556:          ANRMTO = SMLNUM
  557:          ILASCL = .TRUE.
  558:       ELSE IF( ANRM.GT.BIGNUM ) THEN
  559:          ANRMTO = BIGNUM
  560:          ILASCL = .TRUE.
  561:       END IF
  562:       IF( ILASCL )
  563:      $   CALL DLASCL( 'G', 0, 0, ANRM, ANRMTO, N, N, A, LDA, IERR )
  564: *
  565: *     Scale B if max element outside range [SMLNUM,BIGNUM]
  566: *
  567:       BNRM = DLANGE( 'M', N, N, B, LDB, WORK )
  568:       ILBSCL = .FALSE.
  569:       IF( BNRM.GT.ZERO .AND. BNRM.LT.SMLNUM ) THEN
  570:          BNRMTO = SMLNUM
  571:          ILBSCL = .TRUE.
  572:       ELSE IF( BNRM.GT.BIGNUM ) THEN
  573:          BNRMTO = BIGNUM
  574:          ILBSCL = .TRUE.
  575:       END IF
  576:       IF( ILBSCL )
  577:      $   CALL DLASCL( 'G', 0, 0, BNRM, BNRMTO, N, N, B, LDB, IERR )
  578: *
  579: *     Permute the matrix to make it more nearly triangular
  580: *     (Workspace: need 6*N + 2*N for permutation parameters)
  581: *
  582:       ILEFT = 1
  583:       IRIGHT = N + 1
  584:       IWRK = IRIGHT + N
  585:       CALL DGGBAL( 'P', N, A, LDA, B, LDB, ILO, IHI, WORK( ILEFT ),
  586:      $             WORK( IRIGHT ), WORK( IWRK ), IERR )
  587: *
  588: *     Reduce B to triangular form (QR decomposition of B)
  589: *     (Workspace: need N, prefer N*NB)
  590: *
  591:       IROWS = IHI + 1 - ILO
  592:       ICOLS = N + 1 - ILO
  593:       ITAU = IWRK
  594:       IWRK = ITAU + IROWS
  595:       CALL DGEQRF( IROWS, ICOLS, B( ILO, ILO ), LDB, WORK( ITAU ),
  596:      $             WORK( IWRK ), LWORK+1-IWRK, IERR )
  597: *
  598: *     Apply the orthogonal transformation to matrix A
  599: *     (Workspace: need N, prefer N*NB)
  600: *
  601:       CALL DORMQR( 'L', 'T', IROWS, ICOLS, IROWS, B( ILO, ILO ), LDB,
  602:      $             WORK( ITAU ), A( ILO, ILO ), LDA, WORK( IWRK ),
  603:      $             LWORK+1-IWRK, IERR )
  604: *
  605: *     Initialize VSL
  606: *     (Workspace: need N, prefer N*NB)
  607: *
  608:       IF( ILVSL ) THEN
  609:          CALL DLASET( 'Full', N, N, ZERO, ONE, VSL, LDVSL )
  610:          IF( IROWS.GT.1 ) THEN
  611:             CALL DLACPY( 'L', IROWS-1, IROWS-1, B( ILO+1, ILO ), LDB,
  612:      $                   VSL( ILO+1, ILO ), LDVSL )
  613:          END IF
  614:          CALL DORGQR( IROWS, IROWS, IROWS, VSL( ILO, ILO ), LDVSL,
  615:      $                WORK( ITAU ), WORK( IWRK ), LWORK+1-IWRK, IERR )
  616:       END IF
  617: *
  618: *     Initialize VSR
  619: *
  620:       IF( ILVSR )
  621:      $   CALL DLASET( 'Full', N, N, ZERO, ONE, VSR, LDVSR )
  622: *
  623: *     Reduce to generalized Hessenberg form
  624: *     (Workspace: none needed)
  625: *
  626:       CALL DGGHRD( JOBVSL, JOBVSR, N, ILO, IHI, A, LDA, B, LDB, VSL,
  627:      $             LDVSL, VSR, LDVSR, IERR )
  628: *
  629:       SDIM = 0
  630: *
  631: *     Perform QZ algorithm, computing Schur vectors if desired
  632: *     (Workspace: need N)
  633: *
  634:       IWRK = ITAU
  635:       CALL DHGEQZ( 'S', JOBVSL, JOBVSR, N, ILO, IHI, A, LDA, B, LDB,
  636:      $             ALPHAR, ALPHAI, BETA, VSL, LDVSL, VSR, LDVSR,
  637:      $             WORK( IWRK ), LWORK+1-IWRK, IERR )
  638:       IF( IERR.NE.0 ) THEN
  639:          IF( IERR.GT.0 .AND. IERR.LE.N ) THEN
  640:             INFO = IERR
  641:          ELSE IF( IERR.GT.N .AND. IERR.LE.2*N ) THEN
  642:             INFO = IERR - N
  643:          ELSE
  644:             INFO = N + 1
  645:          END IF
  646:          GO TO 60
  647:       END IF
  648: *
  649: *     Sort eigenvalues ALPHA/BETA and compute the reciprocal of
  650: *     condition number(s)
  651: *     (Workspace: If IJOB >= 1, need MAX( 8*(N+1), 2*SDIM*(N-SDIM) )
  652: *                 otherwise, need 8*(N+1) )
  653: *
  654:       IF( WANTST ) THEN
  655: *
  656: *        Undo scaling on eigenvalues before SELCTGing
  657: *
  658:          IF( ILASCL ) THEN
  659:             CALL DLASCL( 'G', 0, 0, ANRMTO, ANRM, N, 1, ALPHAR, N,
  660:      $                   IERR )
  661:             CALL DLASCL( 'G', 0, 0, ANRMTO, ANRM, N, 1, ALPHAI, N,
  662:      $                   IERR )
  663:          END IF
  664:          IF( ILBSCL )
  665:      $      CALL DLASCL( 'G', 0, 0, BNRMTO, BNRM, N, 1, BETA, N, IERR )
  666: *
  667: *        Select eigenvalues
  668: *
  669:          DO 10 I = 1, N
  670:             BWORK( I ) = SELCTG( ALPHAR( I ), ALPHAI( I ), BETA( I ) )
  671:    10    CONTINUE
  672: *
  673: *        Reorder eigenvalues, transform Generalized Schur vectors, and
  674: *        compute reciprocal condition numbers
  675: *
  676:          CALL DTGSEN( IJOB, ILVSL, ILVSR, BWORK, N, A, LDA, B, LDB,
  677:      $                ALPHAR, ALPHAI, BETA, VSL, LDVSL, VSR, LDVSR,
  678:      $                SDIM, PL, PR, DIF, WORK( IWRK ), LWORK-IWRK+1,
  679:      $                IWORK, LIWORK, IERR )
  680: *
  681:          IF( IJOB.GE.1 )
  682:      $      MAXWRK = MAX( MAXWRK, 2*SDIM*( N-SDIM ) )
  683:          IF( IERR.EQ.-22 ) THEN
  684: *
  685: *            not enough real workspace
  686: *
  687:             INFO = -22
  688:          ELSE
  689:             IF( IJOB.EQ.1 .OR. IJOB.EQ.4 ) THEN
  690:                RCONDE( 1 ) = PL
  691:                RCONDE( 2 ) = PR
  692:             END IF
  693:             IF( IJOB.EQ.2 .OR. IJOB.EQ.4 ) THEN
  694:                RCONDV( 1 ) = DIF( 1 )
  695:                RCONDV( 2 ) = DIF( 2 )
  696:             END IF
  697:             IF( IERR.EQ.1 )
  698:      $         INFO = N + 3
  699:          END IF
  700: *
  701:       END IF
  702: *
  703: *     Apply permutation to VSL and VSR
  704: *     (Workspace: none needed)
  705: *
  706:       IF( ILVSL )
  707:      $   CALL DGGBAK( 'P', 'L', N, ILO, IHI, WORK( ILEFT ),
  708:      $                WORK( IRIGHT ), N, VSL, LDVSL, IERR )
  709: *
  710:       IF( ILVSR )
  711:      $   CALL DGGBAK( 'P', 'R', N, ILO, IHI, WORK( ILEFT ),
  712:      $                WORK( IRIGHT ), N, VSR, LDVSR, IERR )
  713: *
  714: *     Check if unscaling would cause over/underflow, if so, rescale
  715: *     (ALPHAR(I),ALPHAI(I),BETA(I)) so BETA(I) is on the order of
  716: *     B(I,I) and ALPHAR(I) and ALPHAI(I) are on the order of A(I,I)
  717: *
  718:       IF( ILASCL ) THEN
  719:          DO 20 I = 1, N
  720:             IF( ALPHAI( I ).NE.ZERO ) THEN
  721:                IF( ( ALPHAR( I ) / SAFMAX ).GT.( ANRMTO / ANRM ) .OR.
  722:      $             ( SAFMIN / ALPHAR( I ) ).GT.( ANRM / ANRMTO ) ) THEN
  723:                   WORK( 1 ) = ABS( A( I, I ) / ALPHAR( I ) )
  724:                   BETA( I ) = BETA( I )*WORK( 1 )
  725:                   ALPHAR( I ) = ALPHAR( I )*WORK( 1 )
  726:                   ALPHAI( I ) = ALPHAI( I )*WORK( 1 )
  727:                ELSE IF( ( ALPHAI( I ) / SAFMAX ).GT.
  728:      $                  ( ANRMTO / ANRM ) .OR.
  729:      $                  ( SAFMIN / ALPHAI( I ) ).GT.( ANRM / ANRMTO ) )
  730:      $                   THEN
  731:                   WORK( 1 ) = ABS( A( I, I+1 ) / ALPHAI( I ) )
  732:                   BETA( I ) = BETA( I )*WORK( 1 )
  733:                   ALPHAR( I ) = ALPHAR( I )*WORK( 1 )
  734:                   ALPHAI( I ) = ALPHAI( I )*WORK( 1 )
  735:                END IF
  736:             END IF
  737:    20    CONTINUE
  738:       END IF
  739: *
  740:       IF( ILBSCL ) THEN
  741:          DO 30 I = 1, N
  742:             IF( ALPHAI( I ).NE.ZERO ) THEN
  743:                IF( ( BETA( I ) / SAFMAX ).GT.( BNRMTO / BNRM ) .OR.
  744:      $             ( SAFMIN / BETA( I ) ).GT.( BNRM / BNRMTO ) ) THEN
  745:                   WORK( 1 ) = ABS( B( I, I ) / BETA( I ) )
  746:                   BETA( I ) = BETA( I )*WORK( 1 )
  747:                   ALPHAR( I ) = ALPHAR( I )*WORK( 1 )
  748:                   ALPHAI( I ) = ALPHAI( I )*WORK( 1 )
  749:                END IF
  750:             END IF
  751:    30    CONTINUE
  752:       END IF
  753: *
  754: *     Undo scaling
  755: *
  756:       IF( ILASCL ) THEN
  757:          CALL DLASCL( 'H', 0, 0, ANRMTO, ANRM, N, N, A, LDA, IERR )
  758:          CALL DLASCL( 'G', 0, 0, ANRMTO, ANRM, N, 1, ALPHAR, N, IERR )
  759:          CALL DLASCL( 'G', 0, 0, ANRMTO, ANRM, N, 1, ALPHAI, N, IERR )
  760:       END IF
  761: *
  762:       IF( ILBSCL ) THEN
  763:          CALL DLASCL( 'U', 0, 0, BNRMTO, BNRM, N, N, B, LDB, IERR )
  764:          CALL DLASCL( 'G', 0, 0, BNRMTO, BNRM, N, 1, BETA, N, IERR )
  765:       END IF
  766: *
  767:       IF( WANTST ) THEN
  768: *
  769: *        Check if reordering is correct
  770: *
  771:          LASTSL = .TRUE.
  772:          LST2SL = .TRUE.
  773:          SDIM = 0
  774:          IP = 0
  775:          DO 50 I = 1, N
  776:             CURSL = SELCTG( ALPHAR( I ), ALPHAI( I ), BETA( I ) )
  777:             IF( ALPHAI( I ).EQ.ZERO ) THEN
  778:                IF( CURSL )
  779:      $            SDIM = SDIM + 1
  780:                IP = 0
  781:                IF( CURSL .AND. .NOT.LASTSL )
  782:      $            INFO = N + 2
  783:             ELSE
  784:                IF( IP.EQ.1 ) THEN
  785: *
  786: *                 Last eigenvalue of conjugate pair
  787: *
  788:                   CURSL = CURSL .OR. LASTSL
  789:                   LASTSL = CURSL
  790:                   IF( CURSL )
  791:      $               SDIM = SDIM + 2
  792:                   IP = -1
  793:                   IF( CURSL .AND. .NOT.LST2SL )
  794:      $               INFO = N + 2
  795:                ELSE
  796: *
  797: *                 First eigenvalue of conjugate pair
  798: *
  799:                   IP = 1
  800:                END IF
  801:             END IF
  802:             LST2SL = LASTSL
  803:             LASTSL = CURSL
  804:    50    CONTINUE
  805: *
  806:       END IF
  807: *
  808:    60 CONTINUE
  809: *
  810:       WORK( 1 ) = MAXWRK
  811:       IWORK( 1 ) = LIWMIN
  812: *
  813:       RETURN
  814: *
  815: *     End of DGGESX
  816: *
  817:       END

CVSweb interface <joel.bertrand@systella.fr>