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