| @@ -0,0 +1,528 @@ | |||||
| *> \brief <b> CGEGS computes the eigenvalues, Schur form, and, optionally, the left and or/right Schur vectors of a complex matrix pair (A,B)</b> | |||||
| * | |||||
| * =========== DOCUMENTATION =========== | |||||
| * | |||||
| * Online html documentation available at | |||||
| * http://www.netlib.org/lapack/explore-html/ | |||||
| * | |||||
| *> \htmlonly | |||||
| *> Download CGEGS + dependencies | |||||
| *> <a href="http://www.netlib.org/cgi-bin/netlibfiles.tgz?format=tgz&filename=/lapack/lapack_routine/cgegs.f"> | |||||
| *> [TGZ]</a> | |||||
| *> <a href="http://www.netlib.org/cgi-bin/netlibfiles.zip?format=zip&filename=/lapack/lapack_routine/cgegs.f"> | |||||
| *> [ZIP]</a> | |||||
| *> <a href="http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/cgegs.f"> | |||||
| *> [TXT]</a> | |||||
| *> \endhtmlonly | |||||
| * | |||||
| * Definition: | |||||
| * =========== | |||||
| * | |||||
| * SUBROUTINE CGEGS( JOBVSL, JOBVSR, N, A, LDA, B, LDB, ALPHA, BETA, | |||||
| * VSL, LDVSL, VSR, LDVSR, WORK, LWORK, RWORK, | |||||
| * INFO ) | |||||
| * | |||||
| * .. Scalar Arguments .. | |||||
| * CHARACTER JOBVSL, JOBVSR | |||||
| * INTEGER INFO, LDA, LDB, LDVSL, LDVSR, LWORK, N | |||||
| * .. | |||||
| * .. Array Arguments .. | |||||
| * REAL RWORK( * ) | |||||
| * COMPLEX A( LDA, * ), ALPHA( * ), B( LDB, * ), | |||||
| * $ BETA( * ), VSL( LDVSL, * ), VSR( LDVSR, * ), | |||||
| * $ WORK( * ) | |||||
| * .. | |||||
| * | |||||
| * | |||||
| *> \par Purpose: | |||||
| * ============= | |||||
| *> | |||||
| *> \verbatim | |||||
| *> | |||||
| *> This routine is deprecated and has been replaced by routine CGGES. | |||||
| *> | |||||
| *> CGEGS computes the eigenvalues, Schur form, and, optionally, the | |||||
| *> left and or/right Schur vectors of a complex matrix pair (A,B). | |||||
| *> Given two square matrices A and B, the generalized Schur | |||||
| *> factorization has the form | |||||
| *> | |||||
| *> A = Q*S*Z**H, B = Q*T*Z**H | |||||
| *> | |||||
| *> where Q and Z are unitary matrices and S and T are upper triangular. | |||||
| *> The columns of Q are the left Schur vectors | |||||
| *> and the columns of Z are the right Schur vectors. | |||||
| *> | |||||
| *> If only the eigenvalues of (A,B) are needed, the driver routine | |||||
| *> CGEGV should be used instead. See CGEGV for a description of the | |||||
| *> eigenvalues of the generalized nonsymmetric eigenvalue problem | |||||
| *> (GNEP). | |||||
| *> \endverbatim | |||||
| * | |||||
| * Arguments: | |||||
| * ========== | |||||
| * | |||||
| *> \param[in] JOBVSL | |||||
| *> \verbatim | |||||
| *> JOBVSL is CHARACTER*1 | |||||
| *> = 'N': do not compute the left Schur vectors; | |||||
| *> = 'V': compute the left Schur vectors (returned in VSL). | |||||
| *> \endverbatim | |||||
| *> | |||||
| *> \param[in] JOBVSR | |||||
| *> \verbatim | |||||
| *> JOBVSR is CHARACTER*1 | |||||
| *> = 'N': do not compute the right Schur vectors; | |||||
| *> = 'V': compute the right Schur vectors (returned in VSR). | |||||
| *> \endverbatim | |||||
| *> | |||||
| *> \param[in] N | |||||
| *> \verbatim | |||||
| *> N is INTEGER | |||||
| *> The order of the matrices A, B, VSL, and VSR. N >= 0. | |||||
| *> \endverbatim | |||||
| *> | |||||
| *> \param[in,out] A | |||||
| *> \verbatim | |||||
| *> A is COMPLEX array, dimension (LDA, N) | |||||
| *> On entry, the matrix A. | |||||
| *> On exit, the upper triangular matrix S from the generalized | |||||
| *> Schur factorization. | |||||
| *> \endverbatim | |||||
| *> | |||||
| *> \param[in] LDA | |||||
| *> \verbatim | |||||
| *> LDA is INTEGER | |||||
| *> The leading dimension of A. LDA >= max(1,N). | |||||
| *> \endverbatim | |||||
| *> | |||||
| *> \param[in,out] B | |||||
| *> \verbatim | |||||
| *> B is COMPLEX array, dimension (LDB, N) | |||||
| *> On entry, the matrix B. | |||||
| *> On exit, the upper triangular matrix T from the generalized | |||||
| *> Schur factorization. | |||||
| *> \endverbatim | |||||
| *> | |||||
| *> \param[in] LDB | |||||
| *> \verbatim | |||||
| *> LDB is INTEGER | |||||
| *> The leading dimension of B. LDB >= max(1,N). | |||||
| *> \endverbatim | |||||
| *> | |||||
| *> \param[out] ALPHA | |||||
| *> \verbatim | |||||
| *> ALPHA is COMPLEX array, dimension (N) | |||||
| *> The complex scalars alpha that define the eigenvalues of | |||||
| *> GNEP. ALPHA(j) = S(j,j), the diagonal element of the Schur | |||||
| *> form of A. | |||||
| *> \endverbatim | |||||
| *> | |||||
| *> \param[out] BETA | |||||
| *> \verbatim | |||||
| *> BETA is COMPLEX array, dimension (N) | |||||
| *> The non-negative real scalars beta that define the | |||||
| *> eigenvalues of GNEP. BETA(j) = T(j,j), the diagonal element | |||||
| *> of the triangular factor T. | |||||
| *> | |||||
| *> Together, the quantities alpha = ALPHA(j) and beta = BETA(j) | |||||
| *> represent the j-th eigenvalue of the matrix pair (A,B), in | |||||
| *> one of the forms lambda = alpha/beta or mu = beta/alpha. | |||||
| *> Since either lambda or mu may overflow, they should not, | |||||
| *> in general, be computed. | |||||
| *> \endverbatim | |||||
| *> | |||||
| *> \param[out] VSL | |||||
| *> \verbatim | |||||
| *> VSL is COMPLEX array, dimension (LDVSL,N) | |||||
| *> If JOBVSL = 'V', the matrix of left Schur vectors Q. | |||||
| *> Not referenced if JOBVSL = 'N'. | |||||
| *> \endverbatim | |||||
| *> | |||||
| *> \param[in] LDVSL | |||||
| *> \verbatim | |||||
| *> LDVSL is INTEGER | |||||
| *> The leading dimension of the matrix VSL. LDVSL >= 1, and | |||||
| *> if JOBVSL = 'V', LDVSL >= N. | |||||
| *> \endverbatim | |||||
| *> | |||||
| *> \param[out] VSR | |||||
| *> \verbatim | |||||
| *> VSR is COMPLEX array, dimension (LDVSR,N) | |||||
| *> If JOBVSR = 'V', the matrix of right Schur vectors Z. | |||||
| *> Not referenced if JOBVSR = 'N'. | |||||
| *> \endverbatim | |||||
| *> | |||||
| *> \param[in] LDVSR | |||||
| *> \verbatim | |||||
| *> LDVSR is INTEGER | |||||
| *> The leading dimension of the matrix VSR. LDVSR >= 1, and | |||||
| *> if JOBVSR = 'V', LDVSR >= N. | |||||
| *> \endverbatim | |||||
| *> | |||||
| *> \param[out] WORK | |||||
| *> \verbatim | |||||
| *> WORK is COMPLEX array, dimension (MAX(1,LWORK)) | |||||
| *> On exit, if INFO = 0, WORK(1) returns the optimal LWORK. | |||||
| *> \endverbatim | |||||
| *> | |||||
| *> \param[in] LWORK | |||||
| *> \verbatim | |||||
| *> LWORK is INTEGER | |||||
| *> The dimension of the array WORK. LWORK >= max(1,2*N). | |||||
| *> For good performance, LWORK must generally be larger. | |||||
| *> To compute the optimal value of LWORK, call ILAENV to get | |||||
| *> blocksizes (for CGEQRF, CUNMQR, and CUNGQR.) Then compute: | |||||
| *> NB -- MAX of the blocksizes for CGEQRF, CUNMQR, and CUNGQR; | |||||
| *> the optimal LWORK is N*(NB+1). | |||||
| *> | |||||
| *> If LWORK = -1, then a workspace query is assumed; the routine | |||||
| *> only calculates the optimal size of the WORK array, returns | |||||
| *> this value as the first entry of the WORK array, and no error | |||||
| *> message related to LWORK is issued by XERBLA. | |||||
| *> \endverbatim | |||||
| *> | |||||
| *> \param[out] RWORK | |||||
| *> \verbatim | |||||
| *> RWORK is REAL array, dimension (3*N) | |||||
| *> \endverbatim | |||||
| *> | |||||
| *> \param[out] INFO | |||||
| *> \verbatim | |||||
| *> INFO is INTEGER | |||||
| *> = 0: successful exit | |||||
| *> < 0: if INFO = -i, the i-th argument had an illegal value. | |||||
| *> =1,...,N: | |||||
| *> The QZ iteration failed. (A,B) are not in Schur | |||||
| *> form, but ALPHA(j) and BETA(j) should be correct for | |||||
| *> j=INFO+1,...,N. | |||||
| *> > N: errors that usually indicate LAPACK problems: | |||||
| *> =N+1: error return from CGGBAL | |||||
| *> =N+2: error return from CGEQRF | |||||
| *> =N+3: error return from CUNMQR | |||||
| *> =N+4: error return from CUNGQR | |||||
| *> =N+5: error return from CGGHRD | |||||
| *> =N+6: error return from CHGEQZ (other than failed | |||||
| *> iteration) | |||||
| *> =N+7: error return from CGGBAK (computing VSL) | |||||
| *> =N+8: error return from CGGBAK (computing VSR) | |||||
| *> =N+9: error return from CLASCL (various places) | |||||
| *> \endverbatim | |||||
| * | |||||
| * Authors: | |||||
| * ======== | |||||
| * | |||||
| *> \author Univ. of Tennessee | |||||
| *> \author Univ. of California Berkeley | |||||
| *> \author Univ. of Colorado Denver | |||||
| *> \author NAG Ltd. | |||||
| * | |||||
| *> \ingroup complexGEeigen | |||||
| * | |||||
| * ===================================================================== | |||||
| SUBROUTINE CGEGS( JOBVSL, JOBVSR, N, A, LDA, B, LDB, ALPHA, BETA, | |||||
| $ VSL, LDVSL, VSR, LDVSR, WORK, LWORK, RWORK, | |||||
| $ INFO ) | |||||
| * | |||||
| * -- LAPACK driver routine -- | |||||
| * -- LAPACK is a software package provided by Univ. of Tennessee, -- | |||||
| * -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..-- | |||||
| * | |||||
| * .. Scalar Arguments .. | |||||
| CHARACTER JOBVSL, JOBVSR | |||||
| INTEGER INFO, LDA, LDB, LDVSL, LDVSR, LWORK, N | |||||
| * .. | |||||
| * .. Array Arguments .. | |||||
| REAL RWORK( * ) | |||||
| COMPLEX A( LDA, * ), ALPHA( * ), B( LDB, * ), | |||||
| $ BETA( * ), VSL( LDVSL, * ), VSR( LDVSR, * ), | |||||
| $ WORK( * ) | |||||
| * .. | |||||
| * | |||||
| * ===================================================================== | |||||
| * | |||||
| * .. Parameters .. | |||||
| REAL ZERO, ONE | |||||
| PARAMETER ( ZERO = 0.0E0, ONE = 1.0E0 ) | |||||
| COMPLEX CZERO, CONE | |||||
| PARAMETER ( CZERO = ( 0.0E0, 0.0E0 ), | |||||
| $ CONE = ( 1.0E0, 0.0E0 ) ) | |||||
| * .. | |||||
| * .. Local Scalars .. | |||||
| LOGICAL ILASCL, ILBSCL, ILVSL, ILVSR, LQUERY | |||||
| INTEGER ICOLS, IHI, IINFO, IJOBVL, IJOBVR, ILEFT, | |||||
| $ ILO, IRIGHT, IROWS, IRWORK, ITAU, IWORK, | |||||
| $ LOPT, LWKMIN, LWKOPT, NB, NB1, NB2, NB3 | |||||
| REAL ANRM, ANRMTO, BIGNUM, BNRM, BNRMTO, EPS, | |||||
| $ SAFMIN, SMLNUM | |||||
| * .. | |||||
| * .. External Subroutines .. | |||||
| EXTERNAL CGEQRF, CGGBAK, CGGBAL, CGGHRD, CHGEQZ, CLACPY, | |||||
| $ CLASCL, CLASET, CUNGQR, CUNMQR, XERBLA | |||||
| * .. | |||||
| * .. External Functions .. | |||||
| LOGICAL LSAME | |||||
| INTEGER ILAENV | |||||
| REAL CLANGE, SLAMCH | |||||
| EXTERNAL ILAENV, LSAME, CLANGE, SLAMCH | |||||
| * .. | |||||
| * .. Intrinsic Functions .. | |||||
| INTRINSIC INT, MAX | |||||
| * .. | |||||
| * .. Executable Statements .. | |||||
| * | |||||
| * Decode the input arguments | |||||
| * | |||||
| IF( LSAME( JOBVSL, 'N' ) ) THEN | |||||
| IJOBVL = 1 | |||||
| ILVSL = .FALSE. | |||||
| ELSE IF( LSAME( JOBVSL, 'V' ) ) THEN | |||||
| IJOBVL = 2 | |||||
| ILVSL = .TRUE. | |||||
| ELSE | |||||
| IJOBVL = -1 | |||||
| ILVSL = .FALSE. | |||||
| END IF | |||||
| * | |||||
| IF( LSAME( JOBVSR, 'N' ) ) THEN | |||||
| IJOBVR = 1 | |||||
| ILVSR = .FALSE. | |||||
| ELSE IF( LSAME( JOBVSR, 'V' ) ) THEN | |||||
| IJOBVR = 2 | |||||
| ILVSR = .TRUE. | |||||
| ELSE | |||||
| IJOBVR = -1 | |||||
| ILVSR = .FALSE. | |||||
| END IF | |||||
| * | |||||
| * Test the input arguments | |||||
| * | |||||
| LWKMIN = MAX( 2*N, 1 ) | |||||
| LWKOPT = LWKMIN | |||||
| WORK( 1 ) = LWKOPT | |||||
| LQUERY = ( LWORK.EQ.-1 ) | |||||
| INFO = 0 | |||||
| IF( IJOBVL.LE.0 ) THEN | |||||
| INFO = -1 | |||||
| ELSE IF( IJOBVR.LE.0 ) THEN | |||||
| INFO = -2 | |||||
| ELSE IF( N.LT.0 ) THEN | |||||
| INFO = -3 | |||||
| ELSE IF( LDA.LT.MAX( 1, N ) ) THEN | |||||
| INFO = -5 | |||||
| ELSE IF( LDB.LT.MAX( 1, N ) ) THEN | |||||
| INFO = -7 | |||||
| ELSE IF( LDVSL.LT.1 .OR. ( ILVSL .AND. LDVSL.LT.N ) ) THEN | |||||
| INFO = -11 | |||||
| ELSE IF( LDVSR.LT.1 .OR. ( ILVSR .AND. LDVSR.LT.N ) ) THEN | |||||
| INFO = -13 | |||||
| ELSE IF( LWORK.LT.LWKMIN .AND. .NOT.LQUERY ) THEN | |||||
| INFO = -15 | |||||
| END IF | |||||
| * | |||||
| IF( INFO.EQ.0 ) THEN | |||||
| NB1 = ILAENV( 1, 'CGEQRF', ' ', N, N, -1, -1 ) | |||||
| NB2 = ILAENV( 1, 'CUNMQR', ' ', N, N, N, -1 ) | |||||
| NB3 = ILAENV( 1, 'CUNGQR', ' ', N, N, N, -1 ) | |||||
| NB = MAX( NB1, NB2, NB3 ) | |||||
| LOPT = N*(NB+1) | |||||
| WORK( 1 ) = LOPT | |||||
| END IF | |||||
| * | |||||
| IF( INFO.NE.0 ) THEN | |||||
| CALL XERBLA( 'CGEGS ', -INFO ) | |||||
| RETURN | |||||
| ELSE IF( LQUERY ) THEN | |||||
| RETURN | |||||
| END IF | |||||
| * | |||||
| * Quick return if possible | |||||
| * | |||||
| IF( N.EQ.0 ) | |||||
| $ RETURN | |||||
| * | |||||
| * Get machine constants | |||||
| * | |||||
| EPS = SLAMCH( 'E' )*SLAMCH( 'B' ) | |||||
| SAFMIN = SLAMCH( 'S' ) | |||||
| SMLNUM = N*SAFMIN / EPS | |||||
| BIGNUM = ONE / SMLNUM | |||||
| * | |||||
| * Scale A if max element outside range [SMLNUM,BIGNUM] | |||||
| * | |||||
| ANRM = CLANGE( 'M', N, N, A, LDA, RWORK ) | |||||
| ILASCL = .FALSE. | |||||
| IF( ANRM.GT.ZERO .AND. ANRM.LT.SMLNUM ) THEN | |||||
| ANRMTO = SMLNUM | |||||
| ILASCL = .TRUE. | |||||
| ELSE IF( ANRM.GT.BIGNUM ) THEN | |||||
| ANRMTO = BIGNUM | |||||
| ILASCL = .TRUE. | |||||
| END IF | |||||
| * | |||||
| IF( ILASCL ) THEN | |||||
| CALL CLASCL( 'G', -1, -1, ANRM, ANRMTO, N, N, A, LDA, IINFO ) | |||||
| IF( IINFO.NE.0 ) THEN | |||||
| INFO = N + 9 | |||||
| RETURN | |||||
| END IF | |||||
| END IF | |||||
| * | |||||
| * Scale B if max element outside range [SMLNUM,BIGNUM] | |||||
| * | |||||
| BNRM = CLANGE( 'M', N, N, B, LDB, RWORK ) | |||||
| ILBSCL = .FALSE. | |||||
| IF( BNRM.GT.ZERO .AND. BNRM.LT.SMLNUM ) THEN | |||||
| BNRMTO = SMLNUM | |||||
| ILBSCL = .TRUE. | |||||
| ELSE IF( BNRM.GT.BIGNUM ) THEN | |||||
| BNRMTO = BIGNUM | |||||
| ILBSCL = .TRUE. | |||||
| END IF | |||||
| * | |||||
| IF( ILBSCL ) THEN | |||||
| CALL CLASCL( 'G', -1, -1, BNRM, BNRMTO, N, N, B, LDB, IINFO ) | |||||
| IF( IINFO.NE.0 ) THEN | |||||
| INFO = N + 9 | |||||
| RETURN | |||||
| END IF | |||||
| END IF | |||||
| * | |||||
| * Permute the matrix to make it more nearly triangular | |||||
| * | |||||
| ILEFT = 1 | |||||
| IRIGHT = N + 1 | |||||
| IRWORK = IRIGHT + N | |||||
| IWORK = 1 | |||||
| CALL CGGBAL( 'P', N, A, LDA, B, LDB, ILO, IHI, RWORK( ILEFT ), | |||||
| $ RWORK( IRIGHT ), RWORK( IRWORK ), IINFO ) | |||||
| IF( IINFO.NE.0 ) THEN | |||||
| INFO = N + 1 | |||||
| GO TO 10 | |||||
| END IF | |||||
| * | |||||
| * Reduce B to triangular form, and initialize VSL and/or VSR | |||||
| * | |||||
| IROWS = IHI + 1 - ILO | |||||
| ICOLS = N + 1 - ILO | |||||
| ITAU = IWORK | |||||
| IWORK = ITAU + IROWS | |||||
| CALL CGEQRF( IROWS, ICOLS, B( ILO, ILO ), LDB, WORK( ITAU ), | |||||
| $ WORK( IWORK ), LWORK+1-IWORK, IINFO ) | |||||
| IF( IINFO.GE.0 ) | |||||
| $ LWKOPT = MAX( LWKOPT, INT( WORK( IWORK ) )+IWORK-1 ) | |||||
| IF( IINFO.NE.0 ) THEN | |||||
| INFO = N + 2 | |||||
| GO TO 10 | |||||
| END IF | |||||
| * | |||||
| CALL CUNMQR( 'L', 'C', IROWS, ICOLS, IROWS, B( ILO, ILO ), LDB, | |||||
| $ WORK( ITAU ), A( ILO, ILO ), LDA, WORK( IWORK ), | |||||
| $ LWORK+1-IWORK, IINFO ) | |||||
| IF( IINFO.GE.0 ) | |||||
| $ LWKOPT = MAX( LWKOPT, INT( WORK( IWORK ) )+IWORK-1 ) | |||||
| IF( IINFO.NE.0 ) THEN | |||||
| INFO = N + 3 | |||||
| GO TO 10 | |||||
| END IF | |||||
| * | |||||
| IF( ILVSL ) THEN | |||||
| CALL CLASET( 'Full', N, N, CZERO, CONE, VSL, LDVSL ) | |||||
| CALL CLACPY( 'L', IROWS-1, IROWS-1, B( ILO+1, ILO ), LDB, | |||||
| $ VSL( ILO+1, ILO ), LDVSL ) | |||||
| CALL CUNGQR( IROWS, IROWS, IROWS, VSL( ILO, ILO ), LDVSL, | |||||
| $ WORK( ITAU ), WORK( IWORK ), LWORK+1-IWORK, | |||||
| $ IINFO ) | |||||
| IF( IINFO.GE.0 ) | |||||
| $ LWKOPT = MAX( LWKOPT, INT( WORK( IWORK ) )+IWORK-1 ) | |||||
| IF( IINFO.NE.0 ) THEN | |||||
| INFO = N + 4 | |||||
| GO TO 10 | |||||
| END IF | |||||
| END IF | |||||
| * | |||||
| IF( ILVSR ) | |||||
| $ CALL CLASET( 'Full', N, N, CZERO, CONE, VSR, LDVSR ) | |||||
| * | |||||
| * Reduce to generalized Hessenberg form | |||||
| * | |||||
| CALL CGGHRD( JOBVSL, JOBVSR, N, ILO, IHI, A, LDA, B, LDB, VSL, | |||||
| $ LDVSL, VSR, LDVSR, IINFO ) | |||||
| IF( IINFO.NE.0 ) THEN | |||||
| INFO = N + 5 | |||||
| GO TO 10 | |||||
| END IF | |||||
| * | |||||
| * Perform QZ algorithm, computing Schur vectors if desired | |||||
| * | |||||
| IWORK = ITAU | |||||
| CALL CHGEQZ( 'S', JOBVSL, JOBVSR, N, ILO, IHI, A, LDA, B, LDB, | |||||
| $ ALPHA, BETA, VSL, LDVSL, VSR, LDVSR, WORK( IWORK ), | |||||
| $ LWORK+1-IWORK, RWORK( IRWORK ), IINFO ) | |||||
| IF( IINFO.GE.0 ) | |||||
| $ LWKOPT = MAX( LWKOPT, INT( WORK( IWORK ) )+IWORK-1 ) | |||||
| IF( IINFO.NE.0 ) THEN | |||||
| IF( IINFO.GT.0 .AND. IINFO.LE.N ) THEN | |||||
| INFO = IINFO | |||||
| ELSE IF( IINFO.GT.N .AND. IINFO.LE.2*N ) THEN | |||||
| INFO = IINFO - N | |||||
| ELSE | |||||
| INFO = N + 6 | |||||
| END IF | |||||
| GO TO 10 | |||||
| END IF | |||||
| * | |||||
| * Apply permutation to VSL and VSR | |||||
| * | |||||
| IF( ILVSL ) THEN | |||||
| CALL CGGBAK( 'P', 'L', N, ILO, IHI, RWORK( ILEFT ), | |||||
| $ RWORK( IRIGHT ), N, VSL, LDVSL, IINFO ) | |||||
| IF( IINFO.NE.0 ) THEN | |||||
| INFO = N + 7 | |||||
| GO TO 10 | |||||
| END IF | |||||
| END IF | |||||
| IF( ILVSR ) THEN | |||||
| CALL CGGBAK( 'P', 'R', N, ILO, IHI, RWORK( ILEFT ), | |||||
| $ RWORK( IRIGHT ), N, VSR, LDVSR, IINFO ) | |||||
| IF( IINFO.NE.0 ) THEN | |||||
| INFO = N + 8 | |||||
| GO TO 10 | |||||
| END IF | |||||
| END IF | |||||
| * | |||||
| * Undo scaling | |||||
| * | |||||
| IF( ILASCL ) THEN | |||||
| CALL CLASCL( 'U', -1, -1, ANRMTO, ANRM, N, N, A, LDA, IINFO ) | |||||
| IF( IINFO.NE.0 ) THEN | |||||
| INFO = N + 9 | |||||
| RETURN | |||||
| END IF | |||||
| CALL CLASCL( 'G', -1, -1, ANRMTO, ANRM, N, 1, ALPHA, N, IINFO ) | |||||
| IF( IINFO.NE.0 ) THEN | |||||
| INFO = N + 9 | |||||
| RETURN | |||||
| END IF | |||||
| END IF | |||||
| * | |||||
| IF( ILBSCL ) THEN | |||||
| CALL CLASCL( 'U', -1, -1, BNRMTO, BNRM, N, N, B, LDB, IINFO ) | |||||
| IF( IINFO.NE.0 ) THEN | |||||
| INFO = N + 9 | |||||
| RETURN | |||||
| END IF | |||||
| CALL CLASCL( 'G', -1, -1, BNRMTO, BNRM, N, 1, BETA, N, IINFO ) | |||||
| IF( IINFO.NE.0 ) THEN | |||||
| INFO = N + 9 | |||||
| RETURN | |||||
| END IF | |||||
| END IF | |||||
| * | |||||
| 10 CONTINUE | |||||
| WORK( 1 ) = LWKOPT | |||||
| * | |||||
| RETURN | |||||
| * | |||||
| * End of CGEGS | |||||
| * | |||||
| END | |||||
| @@ -0,0 +1,703 @@ | |||||
| *> \brief <b> CGEGV computes the eigenvalues and, optionally, the left and/or right eigenvectors of a complex matrix pair (A,B).</b> | |||||
| * | |||||
| * =========== DOCUMENTATION =========== | |||||
| * | |||||
| * Online html documentation available at | |||||
| * http://www.netlib.org/lapack/explore-html/ | |||||
| * | |||||
| *> \htmlonly | |||||
| *> Download CGEGV + dependencies | |||||
| *> <a href="http://www.netlib.org/cgi-bin/netlibfiles.tgz?format=tgz&filename=/lapack/lapack_routine/cgegv.f"> | |||||
| *> [TGZ]</a> | |||||
| *> <a href="http://www.netlib.org/cgi-bin/netlibfiles.zip?format=zip&filename=/lapack/lapack_routine/cgegv.f"> | |||||
| *> [ZIP]</a> | |||||
| *> <a href="http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/cgegv.f"> | |||||
| *> [TXT]</a> | |||||
| *> \endhtmlonly | |||||
| * | |||||
| * Definition: | |||||
| * =========== | |||||
| * | |||||
| * SUBROUTINE CGEGV( JOBVL, JOBVR, N, A, LDA, B, LDB, ALPHA, BETA, | |||||
| * VL, LDVL, VR, LDVR, WORK, LWORK, RWORK, INFO ) | |||||
| * | |||||
| * .. Scalar Arguments .. | |||||
| * CHARACTER JOBVL, JOBVR | |||||
| * INTEGER INFO, LDA, LDB, LDVL, LDVR, LWORK, N | |||||
| * .. | |||||
| * .. Array Arguments .. | |||||
| * REAL RWORK( * ) | |||||
| * COMPLEX A( LDA, * ), ALPHA( * ), B( LDB, * ), | |||||
| * $ BETA( * ), VL( LDVL, * ), VR( LDVR, * ), | |||||
| * $ WORK( * ) | |||||
| * .. | |||||
| * | |||||
| * | |||||
| *> \par Purpose: | |||||
| * ============= | |||||
| *> | |||||
| *> \verbatim | |||||
| *> | |||||
| *> This routine is deprecated and has been replaced by routine CGGEV. | |||||
| *> | |||||
| *> CGEGV computes the eigenvalues and, optionally, the left and/or right | |||||
| *> eigenvectors of a complex matrix pair (A,B). | |||||
| *> Given two square matrices A and B, | |||||
| *> the generalized nonsymmetric eigenvalue problem (GNEP) is to find the | |||||
| *> eigenvalues lambda and corresponding (non-zero) eigenvectors x such | |||||
| *> that | |||||
| *> A*x = lambda*B*x. | |||||
| *> | |||||
| *> An alternate form is to find the eigenvalues mu and corresponding | |||||
| *> eigenvectors y such that | |||||
| *> mu*A*y = B*y. | |||||
| *> | |||||
| *> These two forms are equivalent with mu = 1/lambda and x = y if | |||||
| *> neither lambda nor mu is zero. In order to deal with the case that | |||||
| *> lambda or mu is zero or small, two values alpha and beta are returned | |||||
| *> for each eigenvalue, such that lambda = alpha/beta and | |||||
| *> mu = beta/alpha. | |||||
| *> | |||||
| *> The vectors x and y in the above equations are right eigenvectors of | |||||
| *> the matrix pair (A,B). Vectors u and v satisfying | |||||
| *> u**H*A = lambda*u**H*B or mu*v**H*A = v**H*B | |||||
| *> are left eigenvectors of (A,B). | |||||
| *> | |||||
| *> Note: this routine performs "full balancing" on A and B | |||||
| *> \endverbatim | |||||
| * | |||||
| * Arguments: | |||||
| * ========== | |||||
| * | |||||
| *> \param[in] JOBVL | |||||
| *> \verbatim | |||||
| *> JOBVL is CHARACTER*1 | |||||
| *> = 'N': do not compute the left generalized eigenvectors; | |||||
| *> = 'V': compute the left generalized eigenvectors (returned | |||||
| *> in VL). | |||||
| *> \endverbatim | |||||
| *> | |||||
| *> \param[in] JOBVR | |||||
| *> \verbatim | |||||
| *> JOBVR is CHARACTER*1 | |||||
| *> = 'N': do not compute the right generalized eigenvectors; | |||||
| *> = 'V': compute the right generalized eigenvectors (returned | |||||
| *> in VR). | |||||
| *> \endverbatim | |||||
| *> | |||||
| *> \param[in] N | |||||
| *> \verbatim | |||||
| *> N is INTEGER | |||||
| *> The order of the matrices A, B, VL, and VR. N >= 0. | |||||
| *> \endverbatim | |||||
| *> | |||||
| *> \param[in,out] A | |||||
| *> \verbatim | |||||
| *> A is COMPLEX array, dimension (LDA, N) | |||||
| *> On entry, the matrix A. | |||||
| *> If JOBVL = 'V' or JOBVR = 'V', then on exit A | |||||
| *> contains the Schur form of A from the generalized Schur | |||||
| *> factorization of the pair (A,B) after balancing. If no | |||||
| *> eigenvectors were computed, then only the diagonal elements | |||||
| *> of the Schur form will be correct. See CGGHRD and CHGEQZ | |||||
| *> for details. | |||||
| *> \endverbatim | |||||
| *> | |||||
| *> \param[in] LDA | |||||
| *> \verbatim | |||||
| *> LDA is INTEGER | |||||
| *> The leading dimension of A. LDA >= max(1,N). | |||||
| *> \endverbatim | |||||
| *> | |||||
| *> \param[in,out] B | |||||
| *> \verbatim | |||||
| *> B is COMPLEX array, dimension (LDB, N) | |||||
| *> On entry, the matrix B. | |||||
| *> If JOBVL = 'V' or JOBVR = 'V', then on exit B contains the | |||||
| *> upper triangular matrix obtained from B in the generalized | |||||
| *> Schur factorization of the pair (A,B) after balancing. | |||||
| *> If no eigenvectors were computed, then only the diagonal | |||||
| *> elements of B will be correct. See CGGHRD and CHGEQZ for | |||||
| *> details. | |||||
| *> \endverbatim | |||||
| *> | |||||
| *> \param[in] LDB | |||||
| *> \verbatim | |||||
| *> LDB is INTEGER | |||||
| *> The leading dimension of B. LDB >= max(1,N). | |||||
| *> \endverbatim | |||||
| *> | |||||
| *> \param[out] ALPHA | |||||
| *> \verbatim | |||||
| *> ALPHA is COMPLEX array, dimension (N) | |||||
| *> The complex scalars alpha that define the eigenvalues of | |||||
| *> GNEP. | |||||
| *> \endverbatim | |||||
| *> | |||||
| *> \param[out] BETA | |||||
| *> \verbatim | |||||
| *> BETA is COMPLEX array, dimension (N) | |||||
| *> The complex scalars beta that define the eigenvalues of GNEP. | |||||
| *> | |||||
| *> Together, the quantities alpha = ALPHA(j) and beta = BETA(j) | |||||
| *> represent the j-th eigenvalue of the matrix pair (A,B), in | |||||
| *> one of the forms lambda = alpha/beta or mu = beta/alpha. | |||||
| *> Since either lambda or mu may overflow, they should not, | |||||
| *> in general, be computed. | |||||
| *> \endverbatim | |||||
| *> | |||||
| *> \param[out] VL | |||||
| *> \verbatim | |||||
| *> VL is COMPLEX array, dimension (LDVL,N) | |||||
| *> If JOBVL = 'V', the left eigenvectors u(j) are stored | |||||
| *> in the columns of VL, in the same order as their eigenvalues. | |||||
| *> Each eigenvector is scaled so that its largest component has | |||||
| *> abs(real part) + abs(imag. part) = 1, except for eigenvectors | |||||
| *> corresponding to an eigenvalue with alpha = beta = 0, which | |||||
| *> are set to zero. | |||||
| *> Not referenced if JOBVL = 'N'. | |||||
| *> \endverbatim | |||||
| *> | |||||
| *> \param[in] LDVL | |||||
| *> \verbatim | |||||
| *> LDVL is INTEGER | |||||
| *> The leading dimension of the matrix VL. LDVL >= 1, and | |||||
| *> if JOBVL = 'V', LDVL >= N. | |||||
| *> \endverbatim | |||||
| *> | |||||
| *> \param[out] VR | |||||
| *> \verbatim | |||||
| *> VR is COMPLEX array, dimension (LDVR,N) | |||||
| *> If JOBVR = 'V', the right eigenvectors x(j) are stored | |||||
| *> in the columns of VR, in the same order as their eigenvalues. | |||||
| *> Each eigenvector is scaled so that its largest component has | |||||
| *> abs(real part) + abs(imag. part) = 1, except for eigenvectors | |||||
| *> corresponding to an eigenvalue with alpha = beta = 0, which | |||||
| *> are set to zero. | |||||
| *> Not referenced if JOBVR = 'N'. | |||||
| *> \endverbatim | |||||
| *> | |||||
| *> \param[in] LDVR | |||||
| *> \verbatim | |||||
| *> LDVR is INTEGER | |||||
| *> The leading dimension of the matrix VR. LDVR >= 1, and | |||||
| *> if JOBVR = 'V', LDVR >= N. | |||||
| *> \endverbatim | |||||
| *> | |||||
| *> \param[out] WORK | |||||
| *> \verbatim | |||||
| *> WORK is COMPLEX array, dimension (MAX(1,LWORK)) | |||||
| *> On exit, if INFO = 0, WORK(1) returns the optimal LWORK. | |||||
| *> \endverbatim | |||||
| *> | |||||
| *> \param[in] LWORK | |||||
| *> \verbatim | |||||
| *> LWORK is INTEGER | |||||
| *> The dimension of the array WORK. LWORK >= max(1,2*N). | |||||
| *> For good performance, LWORK must generally be larger. | |||||
| *> To compute the optimal value of LWORK, call ILAENV to get | |||||
| *> blocksizes (for CGEQRF, CUNMQR, and CUNGQR.) Then compute: | |||||
| *> NB -- MAX of the blocksizes for CGEQRF, CUNMQR, and CUNGQR; | |||||
| *> The optimal LWORK is MAX( 2*N, N*(NB+1) ). | |||||
| *> | |||||
| *> If LWORK = -1, then a workspace query is assumed; the routine | |||||
| *> only calculates the optimal size of the WORK array, returns | |||||
| *> this value as the first entry of the WORK array, and no error | |||||
| *> message related to LWORK is issued by XERBLA. | |||||
| *> \endverbatim | |||||
| *> | |||||
| *> \param[out] RWORK | |||||
| *> \verbatim | |||||
| *> RWORK is REAL array, dimension (8*N) | |||||
| *> \endverbatim | |||||
| *> | |||||
| *> \param[out] INFO | |||||
| *> \verbatim | |||||
| *> INFO is INTEGER | |||||
| *> = 0: successful exit | |||||
| *> < 0: if INFO = -i, the i-th argument had an illegal value. | |||||
| *> =1,...,N: | |||||
| *> The QZ iteration failed. No eigenvectors have been | |||||
| *> calculated, but ALPHA(j) and BETA(j) should be | |||||
| *> correct for j=INFO+1,...,N. | |||||
| *> > N: errors that usually indicate LAPACK problems: | |||||
| *> =N+1: error return from CGGBAL | |||||
| *> =N+2: error return from CGEQRF | |||||
| *> =N+3: error return from CUNMQR | |||||
| *> =N+4: error return from CUNGQR | |||||
| *> =N+5: error return from CGGHRD | |||||
| *> =N+6: error return from CHGEQZ (other than failed | |||||
| *> iteration) | |||||
| *> =N+7: error return from CTGEVC | |||||
| *> =N+8: error return from CGGBAK (computing VL) | |||||
| *> =N+9: error return from CGGBAK (computing VR) | |||||
| *> =N+10: error return from CLASCL (various calls) | |||||
| *> \endverbatim | |||||
| * | |||||
| * Authors: | |||||
| * ======== | |||||
| * | |||||
| *> \author Univ. of Tennessee | |||||
| *> \author Univ. of California Berkeley | |||||
| *> \author Univ. of Colorado Denver | |||||
| *> \author NAG Ltd. | |||||
| * | |||||
| *> \ingroup complexGEeigen | |||||
| * | |||||
| *> \par Further Details: | |||||
| * ===================== | |||||
| *> | |||||
| *> \verbatim | |||||
| *> | |||||
| *> Balancing | |||||
| *> --------- | |||||
| *> | |||||
| *> This driver calls CGGBAL to both permute and scale rows and columns | |||||
| *> of A and B. The permutations PL and PR are chosen so that PL*A*PR | |||||
| *> and PL*B*R will be upper triangular except for the diagonal blocks | |||||
| *> A(i:j,i:j) and B(i:j,i:j), with i and j as close together as | |||||
| *> possible. The diagonal scaling matrices DL and DR are chosen so | |||||
| *> that the pair DL*PL*A*PR*DR, DL*PL*B*PR*DR have elements close to | |||||
| *> one (except for the elements that start out zero.) | |||||
| *> | |||||
| *> After the eigenvalues and eigenvectors of the balanced matrices | |||||
| *> have been computed, CGGBAK transforms the eigenvectors back to what | |||||
| *> they would have been (in perfect arithmetic) if they had not been | |||||
| *> balanced. | |||||
| *> | |||||
| *> Contents of A and B on Exit | |||||
| *> -------- -- - --- - -- ---- | |||||
| *> | |||||
| *> If any eigenvectors are computed (either JOBVL='V' or JOBVR='V' or | |||||
| *> both), then on exit the arrays A and B will contain the complex Schur | |||||
| *> form[*] of the "balanced" versions of A and B. If no eigenvectors | |||||
| *> are computed, then only the diagonal blocks will be correct. | |||||
| *> | |||||
| *> [*] In other words, upper triangular form. | |||||
| *> \endverbatim | |||||
| *> | |||||
| * ===================================================================== | |||||
| SUBROUTINE CGEGV( JOBVL, JOBVR, N, A, LDA, B, LDB, ALPHA, BETA, | |||||
| $ VL, LDVL, VR, LDVR, WORK, LWORK, RWORK, INFO ) | |||||
| * | |||||
| * -- LAPACK driver routine -- | |||||
| * -- LAPACK is a software package provided by Univ. of Tennessee, -- | |||||
| * -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..-- | |||||
| * | |||||
| * .. Scalar Arguments .. | |||||
| CHARACTER JOBVL, JOBVR | |||||
| INTEGER INFO, LDA, LDB, LDVL, LDVR, LWORK, N | |||||
| * .. | |||||
| * .. Array Arguments .. | |||||
| REAL RWORK( * ) | |||||
| COMPLEX A( LDA, * ), ALPHA( * ), B( LDB, * ), | |||||
| $ BETA( * ), VL( LDVL, * ), VR( LDVR, * ), | |||||
| $ WORK( * ) | |||||
| * .. | |||||
| * | |||||
| * ===================================================================== | |||||
| * | |||||
| * .. Parameters .. | |||||
| REAL ZERO, ONE | |||||
| PARAMETER ( ZERO = 0.0E0, ONE = 1.0E0 ) | |||||
| COMPLEX CZERO, CONE | |||||
| PARAMETER ( CZERO = ( 0.0E0, 0.0E0 ), | |||||
| $ CONE = ( 1.0E0, 0.0E0 ) ) | |||||
| * .. | |||||
| * .. Local Scalars .. | |||||
| LOGICAL ILIMIT, ILV, ILVL, ILVR, LQUERY | |||||
| CHARACTER CHTEMP | |||||
| INTEGER ICOLS, IHI, IINFO, IJOBVL, IJOBVR, ILEFT, ILO, | |||||
| $ IN, IRIGHT, IROWS, IRWORK, ITAU, IWORK, JC, JR, | |||||
| $ LOPT, LWKMIN, LWKOPT, NB, NB1, NB2, NB3 | |||||
| REAL ABSAI, ABSAR, ABSB, ANRM, ANRM1, ANRM2, BNRM, | |||||
| $ BNRM1, BNRM2, EPS, SAFMAX, SAFMIN, SALFAI, | |||||
| $ SALFAR, SBETA, SCALE, TEMP | |||||
| COMPLEX X | |||||
| * .. | |||||
| * .. Local Arrays .. | |||||
| LOGICAL LDUMMA( 1 ) | |||||
| * .. | |||||
| * .. External Subroutines .. | |||||
| EXTERNAL CGEQRF, CGGBAK, CGGBAL, CGGHRD, CHGEQZ, CLACPY, | |||||
| $ CLASCL, CLASET, CTGEVC, CUNGQR, CUNMQR, XERBLA | |||||
| * .. | |||||
| * .. External Functions .. | |||||
| LOGICAL LSAME | |||||
| INTEGER ILAENV | |||||
| REAL CLANGE, SLAMCH | |||||
| EXTERNAL ILAENV, LSAME, CLANGE, SLAMCH | |||||
| * .. | |||||
| * .. Intrinsic Functions .. | |||||
| INTRINSIC ABS, AIMAG, CMPLX, INT, MAX, REAL | |||||
| * .. | |||||
| * .. Statement Functions .. | |||||
| REAL ABS1 | |||||
| * .. | |||||
| * .. Statement Function definitions .. | |||||
| ABS1( X ) = ABS( REAL( X ) ) + ABS( AIMAG( X ) ) | |||||
| * .. | |||||
| * .. Executable Statements .. | |||||
| * | |||||
| * Decode the input arguments | |||||
| * | |||||
| IF( LSAME( JOBVL, 'N' ) ) THEN | |||||
| IJOBVL = 1 | |||||
| ILVL = .FALSE. | |||||
| ELSE IF( LSAME( JOBVL, 'V' ) ) THEN | |||||
| IJOBVL = 2 | |||||
| ILVL = .TRUE. | |||||
| ELSE | |||||
| IJOBVL = -1 | |||||
| ILVL = .FALSE. | |||||
| END IF | |||||
| * | |||||
| IF( LSAME( JOBVR, 'N' ) ) THEN | |||||
| IJOBVR = 1 | |||||
| ILVR = .FALSE. | |||||
| ELSE IF( LSAME( JOBVR, 'V' ) ) THEN | |||||
| IJOBVR = 2 | |||||
| ILVR = .TRUE. | |||||
| ELSE | |||||
| IJOBVR = -1 | |||||
| ILVR = .FALSE. | |||||
| END IF | |||||
| ILV = ILVL .OR. ILVR | |||||
| * | |||||
| * Test the input arguments | |||||
| * | |||||
| LWKMIN = MAX( 2*N, 1 ) | |||||
| LWKOPT = LWKMIN | |||||
| WORK( 1 ) = LWKOPT | |||||
| LQUERY = ( LWORK.EQ.-1 ) | |||||
| INFO = 0 | |||||
| IF( IJOBVL.LE.0 ) THEN | |||||
| INFO = -1 | |||||
| ELSE IF( IJOBVR.LE.0 ) THEN | |||||
| INFO = -2 | |||||
| ELSE IF( N.LT.0 ) THEN | |||||
| INFO = -3 | |||||
| ELSE IF( LDA.LT.MAX( 1, N ) ) THEN | |||||
| INFO = -5 | |||||
| ELSE IF( LDB.LT.MAX( 1, N ) ) THEN | |||||
| INFO = -7 | |||||
| ELSE IF( LDVL.LT.1 .OR. ( ILVL .AND. LDVL.LT.N ) ) THEN | |||||
| INFO = -11 | |||||
| ELSE IF( LDVR.LT.1 .OR. ( ILVR .AND. LDVR.LT.N ) ) THEN | |||||
| INFO = -13 | |||||
| ELSE IF( LWORK.LT.LWKMIN .AND. .NOT.LQUERY ) THEN | |||||
| INFO = -15 | |||||
| END IF | |||||
| * | |||||
| IF( INFO.EQ.0 ) THEN | |||||
| NB1 = ILAENV( 1, 'CGEQRF', ' ', N, N, -1, -1 ) | |||||
| NB2 = ILAENV( 1, 'CUNMQR', ' ', N, N, N, -1 ) | |||||
| NB3 = ILAENV( 1, 'CUNGQR', ' ', N, N, N, -1 ) | |||||
| NB = MAX( NB1, NB2, NB3 ) | |||||
| LOPT = MAX( 2*N, N*(NB+1) ) | |||||
| WORK( 1 ) = LOPT | |||||
| END IF | |||||
| * | |||||
| IF( INFO.NE.0 ) THEN | |||||
| CALL XERBLA( 'CGEGV ', -INFO ) | |||||
| RETURN | |||||
| ELSE IF( LQUERY ) THEN | |||||
| RETURN | |||||
| END IF | |||||
| * | |||||
| * Quick return if possible | |||||
| * | |||||
| IF( N.EQ.0 ) | |||||
| $ RETURN | |||||
| * | |||||
| * Get machine constants | |||||
| * | |||||
| EPS = SLAMCH( 'E' )*SLAMCH( 'B' ) | |||||
| SAFMIN = SLAMCH( 'S' ) | |||||
| SAFMIN = SAFMIN + SAFMIN | |||||
| SAFMAX = ONE / SAFMIN | |||||
| * | |||||
| * Scale A | |||||
| * | |||||
| ANRM = CLANGE( 'M', N, N, A, LDA, RWORK ) | |||||
| ANRM1 = ANRM | |||||
| ANRM2 = ONE | |||||
| IF( ANRM.LT.ONE ) THEN | |||||
| IF( SAFMAX*ANRM.LT.ONE ) THEN | |||||
| ANRM1 = SAFMIN | |||||
| ANRM2 = SAFMAX*ANRM | |||||
| END IF | |||||
| END IF | |||||
| * | |||||
| IF( ANRM.GT.ZERO ) THEN | |||||
| CALL CLASCL( 'G', -1, -1, ANRM, ONE, N, N, A, LDA, IINFO ) | |||||
| IF( IINFO.NE.0 ) THEN | |||||
| INFO = N + 10 | |||||
| RETURN | |||||
| END IF | |||||
| END IF | |||||
| * | |||||
| * Scale B | |||||
| * | |||||
| BNRM = CLANGE( 'M', N, N, B, LDB, RWORK ) | |||||
| BNRM1 = BNRM | |||||
| BNRM2 = ONE | |||||
| IF( BNRM.LT.ONE ) THEN | |||||
| IF( SAFMAX*BNRM.LT.ONE ) THEN | |||||
| BNRM1 = SAFMIN | |||||
| BNRM2 = SAFMAX*BNRM | |||||
| END IF | |||||
| END IF | |||||
| * | |||||
| IF( BNRM.GT.ZERO ) THEN | |||||
| CALL CLASCL( 'G', -1, -1, BNRM, ONE, N, N, B, LDB, IINFO ) | |||||
| IF( IINFO.NE.0 ) THEN | |||||
| INFO = N + 10 | |||||
| RETURN | |||||
| END IF | |||||
| END IF | |||||
| * | |||||
| * Permute the matrix to make it more nearly triangular | |||||
| * Also "balance" the matrix. | |||||
| * | |||||
| ILEFT = 1 | |||||
| IRIGHT = N + 1 | |||||
| IRWORK = IRIGHT + N | |||||
| CALL CGGBAL( 'P', N, A, LDA, B, LDB, ILO, IHI, RWORK( ILEFT ), | |||||
| $ RWORK( IRIGHT ), RWORK( IRWORK ), IINFO ) | |||||
| IF( IINFO.NE.0 ) THEN | |||||
| INFO = N + 1 | |||||
| GO TO 80 | |||||
| END IF | |||||
| * | |||||
| * Reduce B to triangular form, and initialize VL and/or VR | |||||
| * | |||||
| IROWS = IHI + 1 - ILO | |||||
| IF( ILV ) THEN | |||||
| ICOLS = N + 1 - ILO | |||||
| ELSE | |||||
| ICOLS = IROWS | |||||
| END IF | |||||
| ITAU = 1 | |||||
| IWORK = ITAU + IROWS | |||||
| CALL CGEQRF( IROWS, ICOLS, B( ILO, ILO ), LDB, WORK( ITAU ), | |||||
| $ WORK( IWORK ), LWORK+1-IWORK, IINFO ) | |||||
| IF( IINFO.GE.0 ) | |||||
| $ LWKOPT = MAX( LWKOPT, INT( WORK( IWORK ) )+IWORK-1 ) | |||||
| IF( IINFO.NE.0 ) THEN | |||||
| INFO = N + 2 | |||||
| GO TO 80 | |||||
| END IF | |||||
| * | |||||
| CALL CUNMQR( 'L', 'C', IROWS, ICOLS, IROWS, B( ILO, ILO ), LDB, | |||||
| $ WORK( ITAU ), A( ILO, ILO ), LDA, WORK( IWORK ), | |||||
| $ LWORK+1-IWORK, IINFO ) | |||||
| IF( IINFO.GE.0 ) | |||||
| $ LWKOPT = MAX( LWKOPT, INT( WORK( IWORK ) )+IWORK-1 ) | |||||
| IF( IINFO.NE.0 ) THEN | |||||
| INFO = N + 3 | |||||
| GO TO 80 | |||||
| END IF | |||||
| * | |||||
| IF( ILVL ) THEN | |||||
| CALL CLASET( 'Full', N, N, CZERO, CONE, VL, LDVL ) | |||||
| CALL CLACPY( 'L', IROWS-1, IROWS-1, B( ILO+1, ILO ), LDB, | |||||
| $ VL( ILO+1, ILO ), LDVL ) | |||||
| CALL CUNGQR( IROWS, IROWS, IROWS, VL( ILO, ILO ), LDVL, | |||||
| $ WORK( ITAU ), WORK( IWORK ), LWORK+1-IWORK, | |||||
| $ IINFO ) | |||||
| IF( IINFO.GE.0 ) | |||||
| $ LWKOPT = MAX( LWKOPT, INT( WORK( IWORK ) )+IWORK-1 ) | |||||
| IF( IINFO.NE.0 ) THEN | |||||
| INFO = N + 4 | |||||
| GO TO 80 | |||||
| END IF | |||||
| END IF | |||||
| * | |||||
| IF( ILVR ) | |||||
| $ CALL CLASET( 'Full', N, N, CZERO, CONE, VR, LDVR ) | |||||
| * | |||||
| * Reduce to generalized Hessenberg form | |||||
| * | |||||
| IF( ILV ) THEN | |||||
| * | |||||
| * Eigenvectors requested -- work on whole matrix. | |||||
| * | |||||
| CALL CGGHRD( JOBVL, JOBVR, N, ILO, IHI, A, LDA, B, LDB, VL, | |||||
| $ LDVL, VR, LDVR, IINFO ) | |||||
| ELSE | |||||
| CALL CGGHRD( 'N', 'N', IROWS, 1, IROWS, A( ILO, ILO ), LDA, | |||||
| $ B( ILO, ILO ), LDB, VL, LDVL, VR, LDVR, IINFO ) | |||||
| END IF | |||||
| IF( IINFO.NE.0 ) THEN | |||||
| INFO = N + 5 | |||||
| GO TO 80 | |||||
| END IF | |||||
| * | |||||
| * Perform QZ algorithm | |||||
| * | |||||
| IWORK = ITAU | |||||
| IF( ILV ) THEN | |||||
| CHTEMP = 'S' | |||||
| ELSE | |||||
| CHTEMP = 'E' | |||||
| END IF | |||||
| CALL CHGEQZ( CHTEMP, JOBVL, JOBVR, N, ILO, IHI, A, LDA, B, LDB, | |||||
| $ ALPHA, BETA, VL, LDVL, VR, LDVR, WORK( IWORK ), | |||||
| $ LWORK+1-IWORK, RWORK( IRWORK ), IINFO ) | |||||
| IF( IINFO.GE.0 ) | |||||
| $ LWKOPT = MAX( LWKOPT, INT( WORK( IWORK ) )+IWORK-1 ) | |||||
| IF( IINFO.NE.0 ) THEN | |||||
| IF( IINFO.GT.0 .AND. IINFO.LE.N ) THEN | |||||
| INFO = IINFO | |||||
| ELSE IF( IINFO.GT.N .AND. IINFO.LE.2*N ) THEN | |||||
| INFO = IINFO - N | |||||
| ELSE | |||||
| INFO = N + 6 | |||||
| END IF | |||||
| GO TO 80 | |||||
| END IF | |||||
| * | |||||
| IF( ILV ) THEN | |||||
| * | |||||
| * Compute Eigenvectors | |||||
| * | |||||
| IF( ILVL ) THEN | |||||
| IF( ILVR ) THEN | |||||
| CHTEMP = 'B' | |||||
| ELSE | |||||
| CHTEMP = 'L' | |||||
| END IF | |||||
| ELSE | |||||
| CHTEMP = 'R' | |||||
| END IF | |||||
| * | |||||
| CALL CTGEVC( CHTEMP, 'B', LDUMMA, N, A, LDA, B, LDB, VL, LDVL, | |||||
| $ VR, LDVR, N, IN, WORK( IWORK ), RWORK( IRWORK ), | |||||
| $ IINFO ) | |||||
| IF( IINFO.NE.0 ) THEN | |||||
| INFO = N + 7 | |||||
| GO TO 80 | |||||
| END IF | |||||
| * | |||||
| * Undo balancing on VL and VR, rescale | |||||
| * | |||||
| IF( ILVL ) THEN | |||||
| CALL CGGBAK( 'P', 'L', N, ILO, IHI, RWORK( ILEFT ), | |||||
| $ RWORK( IRIGHT ), N, VL, LDVL, IINFO ) | |||||
| IF( IINFO.NE.0 ) THEN | |||||
| INFO = N + 8 | |||||
| GO TO 80 | |||||
| END IF | |||||
| DO 30 JC = 1, N | |||||
| TEMP = ZERO | |||||
| DO 10 JR = 1, N | |||||
| TEMP = MAX( TEMP, ABS1( VL( JR, JC ) ) ) | |||||
| 10 CONTINUE | |||||
| IF( TEMP.LT.SAFMIN ) | |||||
| $ GO TO 30 | |||||
| TEMP = ONE / TEMP | |||||
| DO 20 JR = 1, N | |||||
| VL( JR, JC ) = VL( JR, JC )*TEMP | |||||
| 20 CONTINUE | |||||
| 30 CONTINUE | |||||
| END IF | |||||
| IF( ILVR ) THEN | |||||
| CALL CGGBAK( 'P', 'R', N, ILO, IHI, RWORK( ILEFT ), | |||||
| $ RWORK( IRIGHT ), N, VR, LDVR, IINFO ) | |||||
| IF( IINFO.NE.0 ) THEN | |||||
| INFO = N + 9 | |||||
| GO TO 80 | |||||
| END IF | |||||
| DO 60 JC = 1, N | |||||
| TEMP = ZERO | |||||
| DO 40 JR = 1, N | |||||
| TEMP = MAX( TEMP, ABS1( VR( JR, JC ) ) ) | |||||
| 40 CONTINUE | |||||
| IF( TEMP.LT.SAFMIN ) | |||||
| $ GO TO 60 | |||||
| TEMP = ONE / TEMP | |||||
| DO 50 JR = 1, N | |||||
| VR( JR, JC ) = VR( JR, JC )*TEMP | |||||
| 50 CONTINUE | |||||
| 60 CONTINUE | |||||
| END IF | |||||
| * | |||||
| * End of eigenvector calculation | |||||
| * | |||||
| END IF | |||||
| * | |||||
| * Undo scaling in alpha, beta | |||||
| * | |||||
| * Note: this does not give the alpha and beta for the unscaled | |||||
| * problem. | |||||
| * | |||||
| * Un-scaling is limited to avoid underflow in alpha and beta | |||||
| * if they are significant. | |||||
| * | |||||
| DO 70 JC = 1, N | |||||
| ABSAR = ABS( REAL( ALPHA( JC ) ) ) | |||||
| ABSAI = ABS( AIMAG( ALPHA( JC ) ) ) | |||||
| ABSB = ABS( REAL( BETA( JC ) ) ) | |||||
| SALFAR = ANRM*REAL( ALPHA( JC ) ) | |||||
| SALFAI = ANRM*AIMAG( ALPHA( JC ) ) | |||||
| SBETA = BNRM*REAL( BETA( JC ) ) | |||||
| ILIMIT = .FALSE. | |||||
| SCALE = ONE | |||||
| * | |||||
| * Check for significant underflow in imaginary part of ALPHA | |||||
| * | |||||
| IF( ABS( SALFAI ).LT.SAFMIN .AND. ABSAI.GE. | |||||
| $ MAX( SAFMIN, EPS*ABSAR, EPS*ABSB ) ) THEN | |||||
| ILIMIT = .TRUE. | |||||
| SCALE = ( SAFMIN / ANRM1 ) / MAX( SAFMIN, ANRM2*ABSAI ) | |||||
| END IF | |||||
| * | |||||
| * Check for significant underflow in real part of ALPHA | |||||
| * | |||||
| IF( ABS( SALFAR ).LT.SAFMIN .AND. ABSAR.GE. | |||||
| $ MAX( SAFMIN, EPS*ABSAI, EPS*ABSB ) ) THEN | |||||
| ILIMIT = .TRUE. | |||||
| SCALE = MAX( SCALE, ( SAFMIN / ANRM1 ) / | |||||
| $ MAX( SAFMIN, ANRM2*ABSAR ) ) | |||||
| END IF | |||||
| * | |||||
| * Check for significant underflow in BETA | |||||
| * | |||||
| IF( ABS( SBETA ).LT.SAFMIN .AND. ABSB.GE. | |||||
| $ MAX( SAFMIN, EPS*ABSAR, EPS*ABSAI ) ) THEN | |||||
| ILIMIT = .TRUE. | |||||
| SCALE = MAX( SCALE, ( SAFMIN / BNRM1 ) / | |||||
| $ MAX( SAFMIN, BNRM2*ABSB ) ) | |||||
| END IF | |||||
| * | |||||
| * Check for possible overflow when limiting scaling | |||||
| * | |||||
| IF( ILIMIT ) THEN | |||||
| TEMP = ( SCALE*SAFMIN )*MAX( ABS( SALFAR ), ABS( SALFAI ), | |||||
| $ ABS( SBETA ) ) | |||||
| IF( TEMP.GT.ONE ) | |||||
| $ SCALE = SCALE / TEMP | |||||
| IF( SCALE.LT.ONE ) | |||||
| $ ILIMIT = .FALSE. | |||||
| END IF | |||||
| * | |||||
| * Recompute un-scaled ALPHA, BETA if necessary. | |||||
| * | |||||
| IF( ILIMIT ) THEN | |||||
| SALFAR = ( SCALE*REAL( ALPHA( JC ) ) )*ANRM | |||||
| SALFAI = ( SCALE*AIMAG( ALPHA( JC ) ) )*ANRM | |||||
| SBETA = ( SCALE*BETA( JC ) )*BNRM | |||||
| END IF | |||||
| ALPHA( JC ) = CMPLX( SALFAR, SALFAI ) | |||||
| BETA( JC ) = SBETA | |||||
| 70 CONTINUE | |||||
| * | |||||
| 80 CONTINUE | |||||
| WORK( 1 ) = LWKOPT | |||||
| * | |||||
| RETURN | |||||
| * | |||||
| * End of CGEGV | |||||
| * | |||||
| END | |||||
| @@ -0,0 +1,538 @@ | |||||
| *> \brief <b> DGEGS computes the eigenvalues, real Schur form, and, optionally, the left and/or right Schur vectors of a real matrix pair (A,B)</b> | |||||
| * | |||||
| * =========== DOCUMENTATION =========== | |||||
| * | |||||
| * Online html documentation available at | |||||
| * http://www.netlib.org/lapack/explore-html/ | |||||
| * | |||||
| *> \htmlonly | |||||
| *> Download DGEGS + dependencies | |||||
| *> <a href="http://www.netlib.org/cgi-bin/netlibfiles.tgz?format=tgz&filename=/lapack/lapack_routine/dgegs.f"> | |||||
| *> [TGZ]</a> | |||||
| *> <a href="http://www.netlib.org/cgi-bin/netlibfiles.zip?format=zip&filename=/lapack/lapack_routine/dgegs.f"> | |||||
| *> [ZIP]</a> | |||||
| *> <a href="http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/dgegs.f"> | |||||
| *> [TXT]</a> | |||||
| *> \endhtmlonly | |||||
| * | |||||
| * Definition: | |||||
| * =========== | |||||
| * | |||||
| * SUBROUTINE DGEGS( JOBVSL, JOBVSR, N, A, LDA, B, LDB, ALPHAR, | |||||
| * ALPHAI, BETA, VSL, LDVSL, VSR, LDVSR, WORK, | |||||
| * LWORK, INFO ) | |||||
| * | |||||
| * .. Scalar Arguments .. | |||||
| * CHARACTER JOBVSL, JOBVSR | |||||
| * INTEGER INFO, LDA, LDB, LDVSL, LDVSR, LWORK, N | |||||
| * .. | |||||
| * .. Array Arguments .. | |||||
| * DOUBLE PRECISION A( LDA, * ), ALPHAI( * ), ALPHAR( * ), | |||||
| * $ B( LDB, * ), BETA( * ), VSL( LDVSL, * ), | |||||
| * $ VSR( LDVSR, * ), WORK( * ) | |||||
| * .. | |||||
| * | |||||
| * | |||||
| *> \par Purpose: | |||||
| * ============= | |||||
| *> | |||||
| *> \verbatim | |||||
| *> | |||||
| *> This routine is deprecated and has been replaced by routine DGGES. | |||||
| *> | |||||
| *> DGEGS computes the eigenvalues, real Schur form, and, optionally, | |||||
| *> left and or/right Schur vectors of a real matrix pair (A,B). | |||||
| *> Given two square matrices A and B, the generalized real Schur | |||||
| *> factorization has the form | |||||
| *> | |||||
| *> A = Q*S*Z**T, B = Q*T*Z**T | |||||
| *> | |||||
| *> where Q and Z are orthogonal matrices, T is upper triangular, and S | |||||
| *> is an upper quasi-triangular matrix with 1-by-1 and 2-by-2 diagonal | |||||
| *> blocks, the 2-by-2 blocks corresponding to complex conjugate pairs | |||||
| *> of eigenvalues of (A,B). The columns of Q are the left Schur vectors | |||||
| *> and the columns of Z are the right Schur vectors. | |||||
| *> | |||||
| *> If only the eigenvalues of (A,B) are needed, the driver routine | |||||
| *> DGEGV should be used instead. See DGEGV for a description of the | |||||
| *> eigenvalues of the generalized nonsymmetric eigenvalue problem | |||||
| *> (GNEP). | |||||
| *> \endverbatim | |||||
| * | |||||
| * Arguments: | |||||
| * ========== | |||||
| * | |||||
| *> \param[in] JOBVSL | |||||
| *> \verbatim | |||||
| *> JOBVSL is CHARACTER*1 | |||||
| *> = 'N': do not compute the left Schur vectors; | |||||
| *> = 'V': compute the left Schur vectors (returned in VSL). | |||||
| *> \endverbatim | |||||
| *> | |||||
| *> \param[in] JOBVSR | |||||
| *> \verbatim | |||||
| *> JOBVSR is CHARACTER*1 | |||||
| *> = 'N': do not compute the right Schur vectors; | |||||
| *> = 'V': compute the right Schur vectors (returned in VSR). | |||||
| *> \endverbatim | |||||
| *> | |||||
| *> \param[in] N | |||||
| *> \verbatim | |||||
| *> N is INTEGER | |||||
| *> The order of the matrices A, B, VSL, and VSR. N >= 0. | |||||
| *> \endverbatim | |||||
| *> | |||||
| *> \param[in,out] A | |||||
| *> \verbatim | |||||
| *> A is DOUBLE PRECISION array, dimension (LDA, N) | |||||
| *> On entry, the matrix A. | |||||
| *> On exit, the upper quasi-triangular matrix S from the | |||||
| *> generalized real Schur factorization. | |||||
| *> \endverbatim | |||||
| *> | |||||
| *> \param[in] LDA | |||||
| *> \verbatim | |||||
| *> LDA is INTEGER | |||||
| *> The leading dimension of A. LDA >= max(1,N). | |||||
| *> \endverbatim | |||||
| *> | |||||
| *> \param[in,out] B | |||||
| *> \verbatim | |||||
| *> B is DOUBLE PRECISION array, dimension (LDB, N) | |||||
| *> On entry, the matrix B. | |||||
| *> On exit, the upper triangular matrix T from the generalized | |||||
| *> real Schur factorization. | |||||
| *> \endverbatim | |||||
| *> | |||||
| *> \param[in] LDB | |||||
| *> \verbatim | |||||
| *> LDB is INTEGER | |||||
| *> The leading dimension of B. LDB >= max(1,N). | |||||
| *> \endverbatim | |||||
| *> | |||||
| *> \param[out] ALPHAR | |||||
| *> \verbatim | |||||
| *> ALPHAR is DOUBLE PRECISION array, dimension (N) | |||||
| *> The real parts of each scalar alpha defining an eigenvalue | |||||
| *> of GNEP. | |||||
| *> \endverbatim | |||||
| *> | |||||
| *> \param[out] ALPHAI | |||||
| *> \verbatim | |||||
| *> ALPHAI is DOUBLE PRECISION array, dimension (N) | |||||
| *> The imaginary parts of each scalar alpha defining an | |||||
| *> eigenvalue of GNEP. If ALPHAI(j) is zero, then the j-th | |||||
| *> eigenvalue is real; if positive, then the j-th and (j+1)-st | |||||
| *> eigenvalues are a complex conjugate pair, with | |||||
| *> ALPHAI(j+1) = -ALPHAI(j). | |||||
| *> \endverbatim | |||||
| *> | |||||
| *> \param[out] BETA | |||||
| *> \verbatim | |||||
| *> BETA is DOUBLE PRECISION array, dimension (N) | |||||
| *> The scalars beta that define the eigenvalues of GNEP. | |||||
| *> Together, the quantities alpha = (ALPHAR(j),ALPHAI(j)) and | |||||
| *> beta = BETA(j) represent the j-th eigenvalue of the matrix | |||||
| *> pair (A,B), in one of the forms lambda = alpha/beta or | |||||
| *> mu = beta/alpha. Since either lambda or mu may overflow, | |||||
| *> they should not, in general, be computed. | |||||
| *> \endverbatim | |||||
| *> | |||||
| *> \param[out] VSL | |||||
| *> \verbatim | |||||
| *> VSL is DOUBLE PRECISION array, dimension (LDVSL,N) | |||||
| *> If JOBVSL = 'V', the matrix of left Schur vectors Q. | |||||
| *> Not referenced if JOBVSL = 'N'. | |||||
| *> \endverbatim | |||||
| *> | |||||
| *> \param[in] LDVSL | |||||
| *> \verbatim | |||||
| *> LDVSL is INTEGER | |||||
| *> The leading dimension of the matrix VSL. LDVSL >=1, and | |||||
| *> if JOBVSL = 'V', LDVSL >= N. | |||||
| *> \endverbatim | |||||
| *> | |||||
| *> \param[out] VSR | |||||
| *> \verbatim | |||||
| *> VSR is DOUBLE PRECISION array, dimension (LDVSR,N) | |||||
| *> If JOBVSR = 'V', the matrix of right Schur vectors Z. | |||||
| *> Not referenced if JOBVSR = 'N'. | |||||
| *> \endverbatim | |||||
| *> | |||||
| *> \param[in] LDVSR | |||||
| *> \verbatim | |||||
| *> LDVSR is INTEGER | |||||
| *> The leading dimension of the matrix VSR. LDVSR >= 1, and | |||||
| *> if JOBVSR = 'V', LDVSR >= N. | |||||
| *> \endverbatim | |||||
| *> | |||||
| *> \param[out] WORK | |||||
| *> \verbatim | |||||
| *> WORK is DOUBLE PRECISION array, dimension (MAX(1,LWORK)) | |||||
| *> On exit, if INFO = 0, WORK(1) returns the optimal LWORK. | |||||
| *> \endverbatim | |||||
| *> | |||||
| *> \param[in] LWORK | |||||
| *> \verbatim | |||||
| *> LWORK is INTEGER | |||||
| *> The dimension of the array WORK. LWORK >= max(1,4*N). | |||||
| *> For good performance, LWORK must generally be larger. | |||||
| *> To compute the optimal value of LWORK, call ILAENV to get | |||||
| *> blocksizes (for DGEQRF, DORMQR, and DORGQR.) Then compute: | |||||
| *> NB -- MAX of the blocksizes for DGEQRF, DORMQR, and DORGQR | |||||
| *> The optimal LWORK is 2*N + N*(NB+1). | |||||
| *> | |||||
| *> If LWORK = -1, then a workspace query is assumed; the routine | |||||
| *> only calculates the optimal size of the WORK array, returns | |||||
| *> this value as the first entry of the WORK array, and no error | |||||
| *> message related to LWORK is issued by XERBLA. | |||||
| *> \endverbatim | |||||
| *> | |||||
| *> \param[out] INFO | |||||
| *> \verbatim | |||||
| *> INFO is INTEGER | |||||
| *> = 0: successful exit | |||||
| *> < 0: if INFO = -i, the i-th argument had an illegal value. | |||||
| *> = 1,...,N: | |||||
| *> The QZ iteration failed. (A,B) are not in Schur | |||||
| *> form, but ALPHAR(j), ALPHAI(j), and BETA(j) should | |||||
| *> be correct for j=INFO+1,...,N. | |||||
| *> > N: errors that usually indicate LAPACK problems: | |||||
| *> =N+1: error return from DGGBAL | |||||
| *> =N+2: error return from DGEQRF | |||||
| *> =N+3: error return from DORMQR | |||||
| *> =N+4: error return from DORGQR | |||||
| *> =N+5: error return from DGGHRD | |||||
| *> =N+6: error return from DHGEQZ (other than failed | |||||
| *> iteration) | |||||
| *> =N+7: error return from DGGBAK (computing VSL) | |||||
| *> =N+8: error return from DGGBAK (computing VSR) | |||||
| *> =N+9: error return from DLASCL (various places) | |||||
| *> \endverbatim | |||||
| * | |||||
| * Authors: | |||||
| * ======== | |||||
| * | |||||
| *> \author Univ. of Tennessee | |||||
| *> \author Univ. of California Berkeley | |||||
| *> \author Univ. of Colorado Denver | |||||
| *> \author NAG Ltd. | |||||
| * | |||||
| *> \ingroup doubleGEeigen | |||||
| * | |||||
| * ===================================================================== | |||||
| SUBROUTINE DGEGS( JOBVSL, JOBVSR, N, A, LDA, B, LDB, ALPHAR, | |||||
| $ ALPHAI, BETA, VSL, LDVSL, VSR, LDVSR, WORK, | |||||
| $ LWORK, INFO ) | |||||
| * | |||||
| * -- LAPACK driver routine -- | |||||
| * -- LAPACK is a software package provided by Univ. of Tennessee, -- | |||||
| * -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..-- | |||||
| * | |||||
| * .. Scalar Arguments .. | |||||
| CHARACTER JOBVSL, JOBVSR | |||||
| INTEGER INFO, LDA, LDB, LDVSL, LDVSR, LWORK, N | |||||
| * .. | |||||
| * .. Array Arguments .. | |||||
| DOUBLE PRECISION A( LDA, * ), ALPHAI( * ), ALPHAR( * ), | |||||
| $ B( LDB, * ), BETA( * ), VSL( LDVSL, * ), | |||||
| $ VSR( LDVSR, * ), WORK( * ) | |||||
| * .. | |||||
| * | |||||
| * ===================================================================== | |||||
| * | |||||
| * .. Parameters .. | |||||
| DOUBLE PRECISION ZERO, ONE | |||||
| PARAMETER ( ZERO = 0.0D0, ONE = 1.0D0 ) | |||||
| * .. | |||||
| * .. Local Scalars .. | |||||
| LOGICAL ILASCL, ILBSCL, ILVSL, ILVSR, LQUERY | |||||
| INTEGER ICOLS, IHI, IINFO, IJOBVL, IJOBVR, ILEFT, ILO, | |||||
| $ IRIGHT, IROWS, ITAU, IWORK, LOPT, LWKMIN, | |||||
| $ LWKOPT, NB, NB1, NB2, NB3 | |||||
| DOUBLE PRECISION ANRM, ANRMTO, BIGNUM, BNRM, BNRMTO, EPS, | |||||
| $ SAFMIN, SMLNUM | |||||
| * .. | |||||
| * .. External Subroutines .. | |||||
| EXTERNAL DGEQRF, DGGBAK, DGGBAL, DGGHRD, DHGEQZ, DLACPY, | |||||
| $ DLASCL, DLASET, DORGQR, DORMQR, XERBLA | |||||
| * .. | |||||
| * .. External Functions .. | |||||
| LOGICAL LSAME | |||||
| INTEGER ILAENV | |||||
| DOUBLE PRECISION DLAMCH, DLANGE | |||||
| EXTERNAL LSAME, ILAENV, DLAMCH, DLANGE | |||||
| * .. | |||||
| * .. Intrinsic Functions .. | |||||
| INTRINSIC INT, MAX | |||||
| * .. | |||||
| * .. Executable Statements .. | |||||
| * | |||||
| * Decode the input arguments | |||||
| * | |||||
| IF( LSAME( JOBVSL, 'N' ) ) THEN | |||||
| IJOBVL = 1 | |||||
| ILVSL = .FALSE. | |||||
| ELSE IF( LSAME( JOBVSL, 'V' ) ) THEN | |||||
| IJOBVL = 2 | |||||
| ILVSL = .TRUE. | |||||
| ELSE | |||||
| IJOBVL = -1 | |||||
| ILVSL = .FALSE. | |||||
| END IF | |||||
| * | |||||
| IF( LSAME( JOBVSR, 'N' ) ) THEN | |||||
| IJOBVR = 1 | |||||
| ILVSR = .FALSE. | |||||
| ELSE IF( LSAME( JOBVSR, 'V' ) ) THEN | |||||
| IJOBVR = 2 | |||||
| ILVSR = .TRUE. | |||||
| ELSE | |||||
| IJOBVR = -1 | |||||
| ILVSR = .FALSE. | |||||
| END IF | |||||
| * | |||||
| * Test the input arguments | |||||
| * | |||||
| LWKMIN = MAX( 4*N, 1 ) | |||||
| LWKOPT = LWKMIN | |||||
| WORK( 1 ) = LWKOPT | |||||
| LQUERY = ( LWORK.EQ.-1 ) | |||||
| INFO = 0 | |||||
| IF( IJOBVL.LE.0 ) THEN | |||||
| INFO = -1 | |||||
| ELSE IF( IJOBVR.LE.0 ) THEN | |||||
| INFO = -2 | |||||
| ELSE IF( N.LT.0 ) THEN | |||||
| INFO = -3 | |||||
| ELSE IF( LDA.LT.MAX( 1, N ) ) THEN | |||||
| INFO = -5 | |||||
| ELSE IF( LDB.LT.MAX( 1, N ) ) THEN | |||||
| INFO = -7 | |||||
| ELSE IF( LDVSL.LT.1 .OR. ( ILVSL .AND. LDVSL.LT.N ) ) THEN | |||||
| INFO = -12 | |||||
| ELSE IF( LDVSR.LT.1 .OR. ( ILVSR .AND. LDVSR.LT.N ) ) THEN | |||||
| INFO = -14 | |||||
| ELSE IF( LWORK.LT.LWKMIN .AND. .NOT.LQUERY ) THEN | |||||
| INFO = -16 | |||||
| END IF | |||||
| * | |||||
| IF( INFO.EQ.0 ) THEN | |||||
| NB1 = ILAENV( 1, 'DGEQRF', ' ', N, N, -1, -1 ) | |||||
| NB2 = ILAENV( 1, 'DORMQR', ' ', N, N, N, -1 ) | |||||
| NB3 = ILAENV( 1, 'DORGQR', ' ', N, N, N, -1 ) | |||||
| NB = MAX( NB1, NB2, NB3 ) | |||||
| LOPT = 2*N + N*( NB+1 ) | |||||
| WORK( 1 ) = LOPT | |||||
| END IF | |||||
| * | |||||
| IF( INFO.NE.0 ) THEN | |||||
| CALL XERBLA( 'DGEGS ', -INFO ) | |||||
| RETURN | |||||
| ELSE IF( LQUERY ) THEN | |||||
| RETURN | |||||
| END IF | |||||
| * | |||||
| * Quick return if possible | |||||
| * | |||||
| IF( N.EQ.0 ) | |||||
| $ RETURN | |||||
| * | |||||
| * Get machine constants | |||||
| * | |||||
| EPS = DLAMCH( 'E' )*DLAMCH( 'B' ) | |||||
| SAFMIN = DLAMCH( 'S' ) | |||||
| SMLNUM = N*SAFMIN / EPS | |||||
| BIGNUM = ONE / SMLNUM | |||||
| * | |||||
| * Scale A if max element outside range [SMLNUM,BIGNUM] | |||||
| * | |||||
| ANRM = DLANGE( 'M', N, N, A, LDA, WORK ) | |||||
| ILASCL = .FALSE. | |||||
| IF( ANRM.GT.ZERO .AND. ANRM.LT.SMLNUM ) THEN | |||||
| ANRMTO = SMLNUM | |||||
| ILASCL = .TRUE. | |||||
| ELSE IF( ANRM.GT.BIGNUM ) THEN | |||||
| ANRMTO = BIGNUM | |||||
| ILASCL = .TRUE. | |||||
| END IF | |||||
| * | |||||
| IF( ILASCL ) THEN | |||||
| CALL DLASCL( 'G', -1, -1, ANRM, ANRMTO, N, N, A, LDA, IINFO ) | |||||
| IF( IINFO.NE.0 ) THEN | |||||
| INFO = N + 9 | |||||
| RETURN | |||||
| END IF | |||||
| END IF | |||||
| * | |||||
| * Scale B if max element outside range [SMLNUM,BIGNUM] | |||||
| * | |||||
| BNRM = DLANGE( 'M', N, N, B, LDB, WORK ) | |||||
| ILBSCL = .FALSE. | |||||
| IF( BNRM.GT.ZERO .AND. BNRM.LT.SMLNUM ) THEN | |||||
| BNRMTO = SMLNUM | |||||
| ILBSCL = .TRUE. | |||||
| ELSE IF( BNRM.GT.BIGNUM ) THEN | |||||
| BNRMTO = BIGNUM | |||||
| ILBSCL = .TRUE. | |||||
| END IF | |||||
| * | |||||
| IF( ILBSCL ) THEN | |||||
| CALL DLASCL( 'G', -1, -1, BNRM, BNRMTO, N, N, B, LDB, IINFO ) | |||||
| IF( IINFO.NE.0 ) THEN | |||||
| INFO = N + 9 | |||||
| RETURN | |||||
| END IF | |||||
| END IF | |||||
| * | |||||
| * Permute the matrix to make it more nearly triangular | |||||
| * Workspace layout: (2*N words -- "work..." not actually used) | |||||
| * left_permutation, right_permutation, work... | |||||
| * | |||||
| ILEFT = 1 | |||||
| IRIGHT = N + 1 | |||||
| IWORK = IRIGHT + N | |||||
| CALL DGGBAL( 'P', N, A, LDA, B, LDB, ILO, IHI, WORK( ILEFT ), | |||||
| $ WORK( IRIGHT ), WORK( IWORK ), IINFO ) | |||||
| IF( IINFO.NE.0 ) THEN | |||||
| INFO = N + 1 | |||||
| GO TO 10 | |||||
| END IF | |||||
| * | |||||
| * Reduce B to triangular form, and initialize VSL and/or VSR | |||||
| * Workspace layout: ("work..." must have at least N words) | |||||
| * left_permutation, right_permutation, tau, work... | |||||
| * | |||||
| IROWS = IHI + 1 - ILO | |||||
| ICOLS = N + 1 - ILO | |||||
| ITAU = IWORK | |||||
| IWORK = ITAU + IROWS | |||||
| CALL DGEQRF( IROWS, ICOLS, B( ILO, ILO ), LDB, WORK( ITAU ), | |||||
| $ WORK( IWORK ), LWORK+1-IWORK, IINFO ) | |||||
| IF( IINFO.GE.0 ) | |||||
| $ LWKOPT = MAX( LWKOPT, INT( WORK( IWORK ) )+IWORK-1 ) | |||||
| IF( IINFO.NE.0 ) THEN | |||||
| INFO = N + 2 | |||||
| GO TO 10 | |||||
| END IF | |||||
| * | |||||
| CALL DORMQR( 'L', 'T', IROWS, ICOLS, IROWS, B( ILO, ILO ), LDB, | |||||
| $ WORK( ITAU ), A( ILO, ILO ), LDA, WORK( IWORK ), | |||||
| $ LWORK+1-IWORK, IINFO ) | |||||
| IF( IINFO.GE.0 ) | |||||
| $ LWKOPT = MAX( LWKOPT, INT( WORK( IWORK ) )+IWORK-1 ) | |||||
| IF( IINFO.NE.0 ) THEN | |||||
| INFO = N + 3 | |||||
| GO TO 10 | |||||
| END IF | |||||
| * | |||||
| IF( ILVSL ) THEN | |||||
| CALL DLASET( 'Full', N, N, ZERO, ONE, VSL, LDVSL ) | |||||
| CALL DLACPY( 'L', IROWS-1, IROWS-1, B( ILO+1, ILO ), LDB, | |||||
| $ VSL( ILO+1, ILO ), LDVSL ) | |||||
| CALL DORGQR( IROWS, IROWS, IROWS, VSL( ILO, ILO ), LDVSL, | |||||
| $ WORK( ITAU ), WORK( IWORK ), LWORK+1-IWORK, | |||||
| $ IINFO ) | |||||
| IF( IINFO.GE.0 ) | |||||
| $ LWKOPT = MAX( LWKOPT, INT( WORK( IWORK ) )+IWORK-1 ) | |||||
| IF( IINFO.NE.0 ) THEN | |||||
| INFO = N + 4 | |||||
| GO TO 10 | |||||
| END IF | |||||
| END IF | |||||
| * | |||||
| IF( ILVSR ) | |||||
| $ CALL DLASET( 'Full', N, N, ZERO, ONE, VSR, LDVSR ) | |||||
| * | |||||
| * Reduce to generalized Hessenberg form | |||||
| * | |||||
| CALL DGGHRD( JOBVSL, JOBVSR, N, ILO, IHI, A, LDA, B, LDB, VSL, | |||||
| $ LDVSL, VSR, LDVSR, IINFO ) | |||||
| IF( IINFO.NE.0 ) THEN | |||||
| INFO = N + 5 | |||||
| GO TO 10 | |||||
| END IF | |||||
| * | |||||
| * Perform QZ algorithm, computing Schur vectors if desired | |||||
| * Workspace layout: ("work..." must have at least 1 word) | |||||
| * left_permutation, right_permutation, work... | |||||
| * | |||||
| IWORK = ITAU | |||||
| CALL DHGEQZ( 'S', JOBVSL, JOBVSR, N, ILO, IHI, A, LDA, B, LDB, | |||||
| $ ALPHAR, ALPHAI, BETA, VSL, LDVSL, VSR, LDVSR, | |||||
| $ WORK( IWORK ), LWORK+1-IWORK, IINFO ) | |||||
| IF( IINFO.GE.0 ) | |||||
| $ LWKOPT = MAX( LWKOPT, INT( WORK( IWORK ) )+IWORK-1 ) | |||||
| IF( IINFO.NE.0 ) THEN | |||||
| IF( IINFO.GT.0 .AND. IINFO.LE.N ) THEN | |||||
| INFO = IINFO | |||||
| ELSE IF( IINFO.GT.N .AND. IINFO.LE.2*N ) THEN | |||||
| INFO = IINFO - N | |||||
| ELSE | |||||
| INFO = N + 6 | |||||
| END IF | |||||
| GO TO 10 | |||||
| END IF | |||||
| * | |||||
| * Apply permutation to VSL and VSR | |||||
| * | |||||
| IF( ILVSL ) THEN | |||||
| CALL DGGBAK( 'P', 'L', N, ILO, IHI, WORK( ILEFT ), | |||||
| $ WORK( IRIGHT ), N, VSL, LDVSL, IINFO ) | |||||
| IF( IINFO.NE.0 ) THEN | |||||
| INFO = N + 7 | |||||
| GO TO 10 | |||||
| END IF | |||||
| END IF | |||||
| IF( ILVSR ) THEN | |||||
| CALL DGGBAK( 'P', 'R', N, ILO, IHI, WORK( ILEFT ), | |||||
| $ WORK( IRIGHT ), N, VSR, LDVSR, IINFO ) | |||||
| IF( IINFO.NE.0 ) THEN | |||||
| INFO = N + 8 | |||||
| GO TO 10 | |||||
| END IF | |||||
| END IF | |||||
| * | |||||
| * Undo scaling | |||||
| * | |||||
| IF( ILASCL ) THEN | |||||
| CALL DLASCL( 'H', -1, -1, ANRMTO, ANRM, N, N, A, LDA, IINFO ) | |||||
| IF( IINFO.NE.0 ) THEN | |||||
| INFO = N + 9 | |||||
| RETURN | |||||
| END IF | |||||
| CALL DLASCL( 'G', -1, -1, ANRMTO, ANRM, N, 1, ALPHAR, N, | |||||
| $ IINFO ) | |||||
| IF( IINFO.NE.0 ) THEN | |||||
| INFO = N + 9 | |||||
| RETURN | |||||
| END IF | |||||
| CALL DLASCL( 'G', -1, -1, ANRMTO, ANRM, N, 1, ALPHAI, N, | |||||
| $ IINFO ) | |||||
| IF( IINFO.NE.0 ) THEN | |||||
| INFO = N + 9 | |||||
| RETURN | |||||
| END IF | |||||
| END IF | |||||
| * | |||||
| IF( ILBSCL ) THEN | |||||
| CALL DLASCL( 'U', -1, -1, BNRMTO, BNRM, N, N, B, LDB, IINFO ) | |||||
| IF( IINFO.NE.0 ) THEN | |||||
| INFO = N + 9 | |||||
| RETURN | |||||
| END IF | |||||
| CALL DLASCL( 'G', -1, -1, BNRMTO, BNRM, N, 1, BETA, N, IINFO ) | |||||
| IF( IINFO.NE.0 ) THEN | |||||
| INFO = N + 9 | |||||
| RETURN | |||||
| END IF | |||||
| END IF | |||||
| * | |||||
| 10 CONTINUE | |||||
| WORK( 1 ) = LWKOPT | |||||
| * | |||||
| RETURN | |||||
| * | |||||
| * End of DGEGS | |||||
| * | |||||
| END | |||||
| @@ -0,0 +1,766 @@ | |||||
| *> \brief <b> DGEGV computes the eigenvalues and, optionally, the left and/or right eigenvectors of a real matrix pair (A,B).</b> | |||||
| * | |||||
| * =========== DOCUMENTATION =========== | |||||
| * | |||||
| * Online html documentation available at | |||||
| * http://www.netlib.org/lapack/explore-html/ | |||||
| * | |||||
| *> \htmlonly | |||||
| *> Download DGEGV + dependencies | |||||
| *> <a href="http://www.netlib.org/cgi-bin/netlibfiles.tgz?format=tgz&filename=/lapack/lapack_routine/dgegv.f"> | |||||
| *> [TGZ]</a> | |||||
| *> <a href="http://www.netlib.org/cgi-bin/netlibfiles.zip?format=zip&filename=/lapack/lapack_routine/dgegv.f"> | |||||
| *> [ZIP]</a> | |||||
| *> <a href="http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/dgegv.f"> | |||||
| *> [TXT]</a> | |||||
| *> \endhtmlonly | |||||
| * | |||||
| * Definition: | |||||
| * =========== | |||||
| * | |||||
| * SUBROUTINE DGEGV( JOBVL, JOBVR, N, A, LDA, B, LDB, ALPHAR, ALPHAI, | |||||
| * BETA, VL, LDVL, VR, LDVR, WORK, LWORK, INFO ) | |||||
| * | |||||
| * .. Scalar Arguments .. | |||||
| * CHARACTER JOBVL, JOBVR | |||||
| * INTEGER INFO, LDA, LDB, LDVL, LDVR, LWORK, N | |||||
| * .. | |||||
| * .. Array Arguments .. | |||||
| * DOUBLE PRECISION A( LDA, * ), ALPHAI( * ), ALPHAR( * ), | |||||
| * $ B( LDB, * ), BETA( * ), VL( LDVL, * ), | |||||
| * $ VR( LDVR, * ), WORK( * ) | |||||
| * .. | |||||
| * | |||||
| * | |||||
| *> \par Purpose: | |||||
| * ============= | |||||
| *> | |||||
| *> \verbatim | |||||
| *> | |||||
| *> This routine is deprecated and has been replaced by routine DGGEV. | |||||
| *> | |||||
| *> DGEGV computes the eigenvalues and, optionally, the left and/or right | |||||
| *> eigenvectors of a real matrix pair (A,B). | |||||
| *> Given two square matrices A and B, | |||||
| *> the generalized nonsymmetric eigenvalue problem (GNEP) is to find the | |||||
| *> eigenvalues lambda and corresponding (non-zero) eigenvectors x such | |||||
| *> that | |||||
| *> | |||||
| *> A*x = lambda*B*x. | |||||
| *> | |||||
| *> An alternate form is to find the eigenvalues mu and corresponding | |||||
| *> eigenvectors y such that | |||||
| *> | |||||
| *> mu*A*y = B*y. | |||||
| *> | |||||
| *> These two forms are equivalent with mu = 1/lambda and x = y if | |||||
| *> neither lambda nor mu is zero. In order to deal with the case that | |||||
| *> lambda or mu is zero or small, two values alpha and beta are returned | |||||
| *> for each eigenvalue, such that lambda = alpha/beta and | |||||
| *> mu = beta/alpha. | |||||
| *> | |||||
| *> The vectors x and y in the above equations are right eigenvectors of | |||||
| *> the matrix pair (A,B). Vectors u and v satisfying | |||||
| *> | |||||
| *> u**H*A = lambda*u**H*B or mu*v**H*A = v**H*B | |||||
| *> | |||||
| *> are left eigenvectors of (A,B). | |||||
| *> | |||||
| *> Note: this routine performs "full balancing" on A and B | |||||
| *> \endverbatim | |||||
| * | |||||
| * Arguments: | |||||
| * ========== | |||||
| * | |||||
| *> \param[in] JOBVL | |||||
| *> \verbatim | |||||
| *> JOBVL is CHARACTER*1 | |||||
| *> = 'N': do not compute the left generalized eigenvectors; | |||||
| *> = 'V': compute the left generalized eigenvectors (returned | |||||
| *> in VL). | |||||
| *> \endverbatim | |||||
| *> | |||||
| *> \param[in] JOBVR | |||||
| *> \verbatim | |||||
| *> JOBVR is CHARACTER*1 | |||||
| *> = 'N': do not compute the right generalized eigenvectors; | |||||
| *> = 'V': compute the right generalized eigenvectors (returned | |||||
| *> in VR). | |||||
| *> \endverbatim | |||||
| *> | |||||
| *> \param[in] N | |||||
| *> \verbatim | |||||
| *> N is INTEGER | |||||
| *> The order of the matrices A, B, VL, and VR. N >= 0. | |||||
| *> \endverbatim | |||||
| *> | |||||
| *> \param[in,out] A | |||||
| *> \verbatim | |||||
| *> A is DOUBLE PRECISION array, dimension (LDA, N) | |||||
| *> On entry, the matrix A. | |||||
| *> If JOBVL = 'V' or JOBVR = 'V', then on exit A | |||||
| *> contains the real Schur form of A from the generalized Schur | |||||
| *> factorization of the pair (A,B) after balancing. | |||||
| *> If no eigenvectors were computed, then only the diagonal | |||||
| *> blocks from the Schur form will be correct. See DGGHRD and | |||||
| *> DHGEQZ for details. | |||||
| *> \endverbatim | |||||
| *> | |||||
| *> \param[in] LDA | |||||
| *> \verbatim | |||||
| *> LDA is INTEGER | |||||
| *> The leading dimension of A. LDA >= max(1,N). | |||||
| *> \endverbatim | |||||
| *> | |||||
| *> \param[in,out] B | |||||
| *> \verbatim | |||||
| *> B is DOUBLE PRECISION array, dimension (LDB, N) | |||||
| *> On entry, the matrix B. | |||||
| *> If JOBVL = 'V' or JOBVR = 'V', then on exit B contains the | |||||
| *> upper triangular matrix obtained from B in the generalized | |||||
| *> Schur factorization of the pair (A,B) after balancing. | |||||
| *> If no eigenvectors were computed, then only those elements of | |||||
| *> B corresponding to the diagonal blocks from the Schur form of | |||||
| *> A will be correct. See DGGHRD and DHGEQZ for details. | |||||
| *> \endverbatim | |||||
| *> | |||||
| *> \param[in] LDB | |||||
| *> \verbatim | |||||
| *> LDB is INTEGER | |||||
| *> The leading dimension of B. LDB >= max(1,N). | |||||
| *> \endverbatim | |||||
| *> | |||||
| *> \param[out] ALPHAR | |||||
| *> \verbatim | |||||
| *> ALPHAR is DOUBLE PRECISION array, dimension (N) | |||||
| *> The real parts of each scalar alpha defining an eigenvalue of | |||||
| *> GNEP. | |||||
| *> \endverbatim | |||||
| *> | |||||
| *> \param[out] ALPHAI | |||||
| *> \verbatim | |||||
| *> ALPHAI is DOUBLE PRECISION array, dimension (N) | |||||
| *> The imaginary parts of each scalar alpha defining an | |||||
| *> eigenvalue of GNEP. If ALPHAI(j) is zero, then the j-th | |||||
| *> eigenvalue is real; if positive, then the j-th and | |||||
| *> (j+1)-st eigenvalues are a complex conjugate pair, with | |||||
| *> ALPHAI(j+1) = -ALPHAI(j). | |||||
| *> \endverbatim | |||||
| *> | |||||
| *> \param[out] BETA | |||||
| *> \verbatim | |||||
| *> BETA is DOUBLE PRECISION array, dimension (N) | |||||
| *> The scalars beta that define the eigenvalues of GNEP. | |||||
| *> | |||||
| *> Together, the quantities alpha = (ALPHAR(j),ALPHAI(j)) and | |||||
| *> beta = BETA(j) represent the j-th eigenvalue of the matrix | |||||
| *> pair (A,B), in one of the forms lambda = alpha/beta or | |||||
| *> mu = beta/alpha. Since either lambda or mu may overflow, | |||||
| *> they should not, in general, be computed. | |||||
| *> \endverbatim | |||||
| *> | |||||
| *> \param[out] VL | |||||
| *> \verbatim | |||||
| *> VL is DOUBLE PRECISION array, dimension (LDVL,N) | |||||
| *> If JOBVL = 'V', the left eigenvectors u(j) are stored | |||||
| *> in the columns of VL, in the same order as their eigenvalues. | |||||
| *> If the j-th eigenvalue is real, then u(j) = VL(:,j). | |||||
| *> If the j-th and (j+1)-st eigenvalues form a complex conjugate | |||||
| *> pair, then | |||||
| *> u(j) = VL(:,j) + i*VL(:,j+1) | |||||
| *> and | |||||
| *> u(j+1) = VL(:,j) - i*VL(:,j+1). | |||||
| *> | |||||
| *> Each eigenvector is scaled so that its largest component has | |||||
| *> abs(real part) + abs(imag. part) = 1, except for eigenvectors | |||||
| *> corresponding to an eigenvalue with alpha = beta = 0, which | |||||
| *> are set to zero. | |||||
| *> Not referenced if JOBVL = 'N'. | |||||
| *> \endverbatim | |||||
| *> | |||||
| *> \param[in] LDVL | |||||
| *> \verbatim | |||||
| *> LDVL is INTEGER | |||||
| *> The leading dimension of the matrix VL. LDVL >= 1, and | |||||
| *> if JOBVL = 'V', LDVL >= N. | |||||
| *> \endverbatim | |||||
| *> | |||||
| *> \param[out] VR | |||||
| *> \verbatim | |||||
| *> VR is DOUBLE PRECISION array, dimension (LDVR,N) | |||||
| *> If JOBVR = 'V', the right eigenvectors x(j) are stored | |||||
| *> in the columns of VR, in the same order as their eigenvalues. | |||||
| *> If the j-th eigenvalue is real, then x(j) = VR(:,j). | |||||
| *> If the j-th and (j+1)-st eigenvalues form a complex conjugate | |||||
| *> pair, then | |||||
| *> x(j) = VR(:,j) + i*VR(:,j+1) | |||||
| *> and | |||||
| *> x(j+1) = VR(:,j) - i*VR(:,j+1). | |||||
| *> | |||||
| *> Each eigenvector is scaled so that its largest component has | |||||
| *> abs(real part) + abs(imag. part) = 1, except for eigenvalues | |||||
| *> corresponding to an eigenvalue with alpha = beta = 0, which | |||||
| *> are set to zero. | |||||
| *> Not referenced if JOBVR = 'N'. | |||||
| *> \endverbatim | |||||
| *> | |||||
| *> \param[in] LDVR | |||||
| *> \verbatim | |||||
| *> LDVR is INTEGER | |||||
| *> The leading dimension of the matrix VR. LDVR >= 1, and | |||||
| *> if JOBVR = 'V', LDVR >= N. | |||||
| *> \endverbatim | |||||
| *> | |||||
| *> \param[out] WORK | |||||
| *> \verbatim | |||||
| *> WORK is DOUBLE PRECISION array, dimension (MAX(1,LWORK)) | |||||
| *> On exit, if INFO = 0, WORK(1) returns the optimal LWORK. | |||||
| *> \endverbatim | |||||
| *> | |||||
| *> \param[in] LWORK | |||||
| *> \verbatim | |||||
| *> LWORK is INTEGER | |||||
| *> The dimension of the array WORK. LWORK >= max(1,8*N). | |||||
| *> For good performance, LWORK must generally be larger. | |||||
| *> To compute the optimal value of LWORK, call ILAENV to get | |||||
| *> blocksizes (for DGEQRF, DORMQR, and DORGQR.) Then compute: | |||||
| *> NB -- MAX of the blocksizes for DGEQRF, DORMQR, and DORGQR; | |||||
| *> The optimal LWORK is: | |||||
| *> 2*N + MAX( 6*N, N*(NB+1) ). | |||||
| *> | |||||
| *> If LWORK = -1, then a workspace query is assumed; the routine | |||||
| *> only calculates the optimal size of the WORK array, returns | |||||
| *> this value as the first entry of the WORK array, and no error | |||||
| *> message related to LWORK is issued by XERBLA. | |||||
| *> \endverbatim | |||||
| *> | |||||
| *> \param[out] INFO | |||||
| *> \verbatim | |||||
| *> INFO is INTEGER | |||||
| *> = 0: successful exit | |||||
| *> < 0: if INFO = -i, the i-th argument had an illegal value. | |||||
| *> = 1,...,N: | |||||
| *> The QZ iteration failed. No eigenvectors have been | |||||
| *> calculated, but ALPHAR(j), ALPHAI(j), and BETA(j) | |||||
| *> should be correct for j=INFO+1,...,N. | |||||
| *> > N: errors that usually indicate LAPACK problems: | |||||
| *> =N+1: error return from DGGBAL | |||||
| *> =N+2: error return from DGEQRF | |||||
| *> =N+3: error return from DORMQR | |||||
| *> =N+4: error return from DORGQR | |||||
| *> =N+5: error return from DGGHRD | |||||
| *> =N+6: error return from DHGEQZ (other than failed | |||||
| *> iteration) | |||||
| *> =N+7: error return from DTGEVC | |||||
| *> =N+8: error return from DGGBAK (computing VL) | |||||
| *> =N+9: error return from DGGBAK (computing VR) | |||||
| *> =N+10: error return from DLASCL (various calls) | |||||
| *> \endverbatim | |||||
| * | |||||
| * Authors: | |||||
| * ======== | |||||
| * | |||||
| *> \author Univ. of Tennessee | |||||
| *> \author Univ. of California Berkeley | |||||
| *> \author Univ. of Colorado Denver | |||||
| *> \author NAG Ltd. | |||||
| * | |||||
| *> \ingroup doubleGEeigen | |||||
| * | |||||
| *> \par Further Details: | |||||
| * ===================== | |||||
| *> | |||||
| *> \verbatim | |||||
| *> | |||||
| *> Balancing | |||||
| *> --------- | |||||
| *> | |||||
| *> This driver calls DGGBAL to both permute and scale rows and columns | |||||
| *> of A and B. The permutations PL and PR are chosen so that PL*A*PR | |||||
| *> and PL*B*R will be upper triangular except for the diagonal blocks | |||||
| *> A(i:j,i:j) and B(i:j,i:j), with i and j as close together as | |||||
| *> possible. The diagonal scaling matrices DL and DR are chosen so | |||||
| *> that the pair DL*PL*A*PR*DR, DL*PL*B*PR*DR have elements close to | |||||
| *> one (except for the elements that start out zero.) | |||||
| *> | |||||
| *> After the eigenvalues and eigenvectors of the balanced matrices | |||||
| *> have been computed, DGGBAK transforms the eigenvectors back to what | |||||
| *> they would have been (in perfect arithmetic) if they had not been | |||||
| *> balanced. | |||||
| *> | |||||
| *> Contents of A and B on Exit | |||||
| *> -------- -- - --- - -- ---- | |||||
| *> | |||||
| *> If any eigenvectors are computed (either JOBVL='V' or JOBVR='V' or | |||||
| *> both), then on exit the arrays A and B will contain the real Schur | |||||
| *> form[*] of the "balanced" versions of A and B. If no eigenvectors | |||||
| *> are computed, then only the diagonal blocks will be correct. | |||||
| *> | |||||
| *> [*] See DHGEQZ, DGEGS, or read the book "Matrix Computations", | |||||
| *> by Golub & van Loan, pub. by Johns Hopkins U. Press. | |||||
| *> \endverbatim | |||||
| *> | |||||
| * ===================================================================== | |||||
| SUBROUTINE DGEGV( JOBVL, JOBVR, N, A, LDA, B, LDB, ALPHAR, ALPHAI, | |||||
| $ BETA, VL, LDVL, VR, LDVR, WORK, LWORK, INFO ) | |||||
| * | |||||
| * -- LAPACK driver routine -- | |||||
| * -- LAPACK is a software package provided by Univ. of Tennessee, -- | |||||
| * -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..-- | |||||
| * | |||||
| * .. Scalar Arguments .. | |||||
| CHARACTER JOBVL, JOBVR | |||||
| INTEGER INFO, LDA, LDB, LDVL, LDVR, LWORK, N | |||||
| * .. | |||||
| * .. Array Arguments .. | |||||
| DOUBLE PRECISION A( LDA, * ), ALPHAI( * ), ALPHAR( * ), | |||||
| $ B( LDB, * ), BETA( * ), VL( LDVL, * ), | |||||
| $ VR( LDVR, * ), WORK( * ) | |||||
| * .. | |||||
| * | |||||
| * ===================================================================== | |||||
| * | |||||
| * .. Parameters .. | |||||
| DOUBLE PRECISION ZERO, ONE | |||||
| PARAMETER ( ZERO = 0.0D0, ONE = 1.0D0 ) | |||||
| * .. | |||||
| * .. Local Scalars .. | |||||
| LOGICAL ILIMIT, ILV, ILVL, ILVR, LQUERY | |||||
| CHARACTER CHTEMP | |||||
| INTEGER ICOLS, IHI, IINFO, IJOBVL, IJOBVR, ILEFT, ILO, | |||||
| $ IN, IRIGHT, IROWS, ITAU, IWORK, JC, JR, LOPT, | |||||
| $ LWKMIN, LWKOPT, NB, NB1, NB2, NB3 | |||||
| DOUBLE PRECISION ABSAI, ABSAR, ABSB, ANRM, ANRM1, ANRM2, BNRM, | |||||
| $ BNRM1, BNRM2, EPS, ONEPLS, SAFMAX, SAFMIN, | |||||
| $ SALFAI, SALFAR, SBETA, SCALE, TEMP | |||||
| * .. | |||||
| * .. Local Arrays .. | |||||
| LOGICAL LDUMMA( 1 ) | |||||
| * .. | |||||
| * .. External Subroutines .. | |||||
| EXTERNAL DGEQRF, DGGBAK, DGGBAL, DGGHRD, DHGEQZ, DLACPY, | |||||
| $ DLASCL, DLASET, DORGQR, DORMQR, DTGEVC, XERBLA | |||||
| * .. | |||||
| * .. External Functions .. | |||||
| LOGICAL LSAME | |||||
| INTEGER ILAENV | |||||
| DOUBLE PRECISION DLAMCH, DLANGE | |||||
| EXTERNAL LSAME, ILAENV, DLAMCH, DLANGE | |||||
| * .. | |||||
| * .. Intrinsic Functions .. | |||||
| INTRINSIC ABS, INT, MAX | |||||
| * .. | |||||
| * .. Executable Statements .. | |||||
| * | |||||
| * Decode the input arguments | |||||
| * | |||||
| IF( LSAME( JOBVL, 'N' ) ) THEN | |||||
| IJOBVL = 1 | |||||
| ILVL = .FALSE. | |||||
| ELSE IF( LSAME( JOBVL, 'V' ) ) THEN | |||||
| IJOBVL = 2 | |||||
| ILVL = .TRUE. | |||||
| ELSE | |||||
| IJOBVL = -1 | |||||
| ILVL = .FALSE. | |||||
| END IF | |||||
| * | |||||
| IF( LSAME( JOBVR, 'N' ) ) THEN | |||||
| IJOBVR = 1 | |||||
| ILVR = .FALSE. | |||||
| ELSE IF( LSAME( JOBVR, 'V' ) ) THEN | |||||
| IJOBVR = 2 | |||||
| ILVR = .TRUE. | |||||
| ELSE | |||||
| IJOBVR = -1 | |||||
| ILVR = .FALSE. | |||||
| END IF | |||||
| ILV = ILVL .OR. ILVR | |||||
| * | |||||
| * Test the input arguments | |||||
| * | |||||
| LWKMIN = MAX( 8*N, 1 ) | |||||
| LWKOPT = LWKMIN | |||||
| WORK( 1 ) = LWKOPT | |||||
| LQUERY = ( LWORK.EQ.-1 ) | |||||
| INFO = 0 | |||||
| IF( IJOBVL.LE.0 ) THEN | |||||
| INFO = -1 | |||||
| ELSE IF( IJOBVR.LE.0 ) THEN | |||||
| INFO = -2 | |||||
| ELSE IF( N.LT.0 ) THEN | |||||
| INFO = -3 | |||||
| ELSE IF( LDA.LT.MAX( 1, N ) ) THEN | |||||
| INFO = -5 | |||||
| ELSE IF( LDB.LT.MAX( 1, N ) ) THEN | |||||
| INFO = -7 | |||||
| ELSE IF( LDVL.LT.1 .OR. ( ILVL .AND. LDVL.LT.N ) ) THEN | |||||
| INFO = -12 | |||||
| ELSE IF( LDVR.LT.1 .OR. ( ILVR .AND. LDVR.LT.N ) ) THEN | |||||
| INFO = -14 | |||||
| ELSE IF( LWORK.LT.LWKMIN .AND. .NOT.LQUERY ) THEN | |||||
| INFO = -16 | |||||
| END IF | |||||
| * | |||||
| IF( INFO.EQ.0 ) THEN | |||||
| NB1 = ILAENV( 1, 'DGEQRF', ' ', N, N, -1, -1 ) | |||||
| NB2 = ILAENV( 1, 'DORMQR', ' ', N, N, N, -1 ) | |||||
| NB3 = ILAENV( 1, 'DORGQR', ' ', N, N, N, -1 ) | |||||
| NB = MAX( NB1, NB2, NB3 ) | |||||
| LOPT = 2*N + MAX( 6*N, N*( NB+1 ) ) | |||||
| WORK( 1 ) = LOPT | |||||
| END IF | |||||
| * | |||||
| IF( INFO.NE.0 ) THEN | |||||
| CALL XERBLA( 'DGEGV ', -INFO ) | |||||
| RETURN | |||||
| ELSE IF( LQUERY ) THEN | |||||
| RETURN | |||||
| END IF | |||||
| * | |||||
| * Quick return if possible | |||||
| * | |||||
| IF( N.EQ.0 ) | |||||
| $ RETURN | |||||
| * | |||||
| * Get machine constants | |||||
| * | |||||
| EPS = DLAMCH( 'E' )*DLAMCH( 'B' ) | |||||
| SAFMIN = DLAMCH( 'S' ) | |||||
| SAFMIN = SAFMIN + SAFMIN | |||||
| SAFMAX = ONE / SAFMIN | |||||
| ONEPLS = ONE + ( 4*EPS ) | |||||
| * | |||||
| * Scale A | |||||
| * | |||||
| ANRM = DLANGE( 'M', N, N, A, LDA, WORK ) | |||||
| ANRM1 = ANRM | |||||
| ANRM2 = ONE | |||||
| IF( ANRM.LT.ONE ) THEN | |||||
| IF( SAFMAX*ANRM.LT.ONE ) THEN | |||||
| ANRM1 = SAFMIN | |||||
| ANRM2 = SAFMAX*ANRM | |||||
| END IF | |||||
| END IF | |||||
| * | |||||
| IF( ANRM.GT.ZERO ) THEN | |||||
| CALL DLASCL( 'G', -1, -1, ANRM, ONE, N, N, A, LDA, IINFO ) | |||||
| IF( IINFO.NE.0 ) THEN | |||||
| INFO = N + 10 | |||||
| RETURN | |||||
| END IF | |||||
| END IF | |||||
| * | |||||
| * Scale B | |||||
| * | |||||
| BNRM = DLANGE( 'M', N, N, B, LDB, WORK ) | |||||
| BNRM1 = BNRM | |||||
| BNRM2 = ONE | |||||
| IF( BNRM.LT.ONE ) THEN | |||||
| IF( SAFMAX*BNRM.LT.ONE ) THEN | |||||
| BNRM1 = SAFMIN | |||||
| BNRM2 = SAFMAX*BNRM | |||||
| END IF | |||||
| END IF | |||||
| * | |||||
| IF( BNRM.GT.ZERO ) THEN | |||||
| CALL DLASCL( 'G', -1, -1, BNRM, ONE, N, N, B, LDB, IINFO ) | |||||
| IF( IINFO.NE.0 ) THEN | |||||
| INFO = N + 10 | |||||
| RETURN | |||||
| END IF | |||||
| END IF | |||||
| * | |||||
| * Permute the matrix to make it more nearly triangular | |||||
| * Workspace layout: (8*N words -- "work" requires 6*N words) | |||||
| * left_permutation, right_permutation, work... | |||||
| * | |||||
| ILEFT = 1 | |||||
| IRIGHT = N + 1 | |||||
| IWORK = IRIGHT + N | |||||
| CALL DGGBAL( 'P', N, A, LDA, B, LDB, ILO, IHI, WORK( ILEFT ), | |||||
| $ WORK( IRIGHT ), WORK( IWORK ), IINFO ) | |||||
| IF( IINFO.NE.0 ) THEN | |||||
| INFO = N + 1 | |||||
| GO TO 120 | |||||
| END IF | |||||
| * | |||||
| * Reduce B to triangular form, and initialize VL and/or VR | |||||
| * Workspace layout: ("work..." must have at least N words) | |||||
| * left_permutation, right_permutation, tau, work... | |||||
| * | |||||
| IROWS = IHI + 1 - ILO | |||||
| IF( ILV ) THEN | |||||
| ICOLS = N + 1 - ILO | |||||
| ELSE | |||||
| ICOLS = IROWS | |||||
| END IF | |||||
| ITAU = IWORK | |||||
| IWORK = ITAU + IROWS | |||||
| CALL DGEQRF( IROWS, ICOLS, B( ILO, ILO ), LDB, WORK( ITAU ), | |||||
| $ WORK( IWORK ), LWORK+1-IWORK, IINFO ) | |||||
| IF( IINFO.GE.0 ) | |||||
| $ LWKOPT = MAX( LWKOPT, INT( WORK( IWORK ) )+IWORK-1 ) | |||||
| IF( IINFO.NE.0 ) THEN | |||||
| INFO = N + 2 | |||||
| GO TO 120 | |||||
| END IF | |||||
| * | |||||
| CALL DORMQR( 'L', 'T', IROWS, ICOLS, IROWS, B( ILO, ILO ), LDB, | |||||
| $ WORK( ITAU ), A( ILO, ILO ), LDA, WORK( IWORK ), | |||||
| $ LWORK+1-IWORK, IINFO ) | |||||
| IF( IINFO.GE.0 ) | |||||
| $ LWKOPT = MAX( LWKOPT, INT( WORK( IWORK ) )+IWORK-1 ) | |||||
| IF( IINFO.NE.0 ) THEN | |||||
| INFO = N + 3 | |||||
| GO TO 120 | |||||
| END IF | |||||
| * | |||||
| IF( ILVL ) THEN | |||||
| CALL DLASET( 'Full', N, N, ZERO, ONE, VL, LDVL ) | |||||
| CALL DLACPY( 'L', IROWS-1, IROWS-1, B( ILO+1, ILO ), LDB, | |||||
| $ VL( ILO+1, ILO ), LDVL ) | |||||
| CALL DORGQR( IROWS, IROWS, IROWS, VL( ILO, ILO ), LDVL, | |||||
| $ WORK( ITAU ), WORK( IWORK ), LWORK+1-IWORK, | |||||
| $ IINFO ) | |||||
| IF( IINFO.GE.0 ) | |||||
| $ LWKOPT = MAX( LWKOPT, INT( WORK( IWORK ) )+IWORK-1 ) | |||||
| IF( IINFO.NE.0 ) THEN | |||||
| INFO = N + 4 | |||||
| GO TO 120 | |||||
| END IF | |||||
| END IF | |||||
| * | |||||
| IF( ILVR ) | |||||
| $ CALL DLASET( 'Full', N, N, ZERO, ONE, VR, LDVR ) | |||||
| * | |||||
| * Reduce to generalized Hessenberg form | |||||
| * | |||||
| IF( ILV ) THEN | |||||
| * | |||||
| * Eigenvectors requested -- work on whole matrix. | |||||
| * | |||||
| CALL DGGHRD( JOBVL, JOBVR, N, ILO, IHI, A, LDA, B, LDB, VL, | |||||
| $ LDVL, VR, LDVR, IINFO ) | |||||
| ELSE | |||||
| CALL DGGHRD( 'N', 'N', IROWS, 1, IROWS, A( ILO, ILO ), LDA, | |||||
| $ B( ILO, ILO ), LDB, VL, LDVL, VR, LDVR, IINFO ) | |||||
| END IF | |||||
| IF( IINFO.NE.0 ) THEN | |||||
| INFO = N + 5 | |||||
| GO TO 120 | |||||
| END IF | |||||
| * | |||||
| * Perform QZ algorithm | |||||
| * Workspace layout: ("work..." must have at least 1 word) | |||||
| * left_permutation, right_permutation, work... | |||||
| * | |||||
| IWORK = ITAU | |||||
| IF( ILV ) THEN | |||||
| CHTEMP = 'S' | |||||
| ELSE | |||||
| CHTEMP = 'E' | |||||
| END IF | |||||
| CALL DHGEQZ( CHTEMP, JOBVL, JOBVR, N, ILO, IHI, A, LDA, B, LDB, | |||||
| $ ALPHAR, ALPHAI, BETA, VL, LDVL, VR, LDVR, | |||||
| $ WORK( IWORK ), LWORK+1-IWORK, IINFO ) | |||||
| IF( IINFO.GE.0 ) | |||||
| $ LWKOPT = MAX( LWKOPT, INT( WORK( IWORK ) )+IWORK-1 ) | |||||
| IF( IINFO.NE.0 ) THEN | |||||
| IF( IINFO.GT.0 .AND. IINFO.LE.N ) THEN | |||||
| INFO = IINFO | |||||
| ELSE IF( IINFO.GT.N .AND. IINFO.LE.2*N ) THEN | |||||
| INFO = IINFO - N | |||||
| ELSE | |||||
| INFO = N + 6 | |||||
| END IF | |||||
| GO TO 120 | |||||
| END IF | |||||
| * | |||||
| IF( ILV ) THEN | |||||
| * | |||||
| * Compute Eigenvectors (DTGEVC requires 6*N words of workspace) | |||||
| * | |||||
| IF( ILVL ) THEN | |||||
| IF( ILVR ) THEN | |||||
| CHTEMP = 'B' | |||||
| ELSE | |||||
| CHTEMP = 'L' | |||||
| END IF | |||||
| ELSE | |||||
| CHTEMP = 'R' | |||||
| END IF | |||||
| * | |||||
| CALL DTGEVC( CHTEMP, 'B', LDUMMA, N, A, LDA, B, LDB, VL, LDVL, | |||||
| $ VR, LDVR, N, IN, WORK( IWORK ), IINFO ) | |||||
| IF( IINFO.NE.0 ) THEN | |||||
| INFO = N + 7 | |||||
| GO TO 120 | |||||
| END IF | |||||
| * | |||||
| * Undo balancing on VL and VR, rescale | |||||
| * | |||||
| IF( ILVL ) THEN | |||||
| CALL DGGBAK( 'P', 'L', N, ILO, IHI, WORK( ILEFT ), | |||||
| $ WORK( IRIGHT ), N, VL, LDVL, IINFO ) | |||||
| IF( IINFO.NE.0 ) THEN | |||||
| INFO = N + 8 | |||||
| GO TO 120 | |||||
| END IF | |||||
| DO 50 JC = 1, N | |||||
| IF( ALPHAI( JC ).LT.ZERO ) | |||||
| $ GO TO 50 | |||||
| TEMP = ZERO | |||||
| IF( ALPHAI( JC ).EQ.ZERO ) THEN | |||||
| DO 10 JR = 1, N | |||||
| TEMP = MAX( TEMP, ABS( VL( JR, JC ) ) ) | |||||
| 10 CONTINUE | |||||
| ELSE | |||||
| DO 20 JR = 1, N | |||||
| TEMP = MAX( TEMP, ABS( VL( JR, JC ) )+ | |||||
| $ ABS( VL( JR, JC+1 ) ) ) | |||||
| 20 CONTINUE | |||||
| END IF | |||||
| IF( TEMP.LT.SAFMIN ) | |||||
| $ GO TO 50 | |||||
| TEMP = ONE / TEMP | |||||
| IF( ALPHAI( JC ).EQ.ZERO ) THEN | |||||
| DO 30 JR = 1, N | |||||
| VL( JR, JC ) = VL( JR, JC )*TEMP | |||||
| 30 CONTINUE | |||||
| ELSE | |||||
| DO 40 JR = 1, N | |||||
| VL( JR, JC ) = VL( JR, JC )*TEMP | |||||
| VL( JR, JC+1 ) = VL( JR, JC+1 )*TEMP | |||||
| 40 CONTINUE | |||||
| END IF | |||||
| 50 CONTINUE | |||||
| END IF | |||||
| IF( ILVR ) THEN | |||||
| CALL DGGBAK( 'P', 'R', N, ILO, IHI, WORK( ILEFT ), | |||||
| $ WORK( IRIGHT ), N, VR, LDVR, IINFO ) | |||||
| IF( IINFO.NE.0 ) THEN | |||||
| INFO = N + 9 | |||||
| GO TO 120 | |||||
| END IF | |||||
| DO 100 JC = 1, N | |||||
| IF( ALPHAI( JC ).LT.ZERO ) | |||||
| $ GO TO 100 | |||||
| TEMP = ZERO | |||||
| IF( ALPHAI( JC ).EQ.ZERO ) THEN | |||||
| DO 60 JR = 1, N | |||||
| TEMP = MAX( TEMP, ABS( VR( JR, JC ) ) ) | |||||
| 60 CONTINUE | |||||
| ELSE | |||||
| DO 70 JR = 1, N | |||||
| TEMP = MAX( TEMP, ABS( VR( JR, JC ) )+ | |||||
| $ ABS( VR( JR, JC+1 ) ) ) | |||||
| 70 CONTINUE | |||||
| END IF | |||||
| IF( TEMP.LT.SAFMIN ) | |||||
| $ GO TO 100 | |||||
| TEMP = ONE / TEMP | |||||
| IF( ALPHAI( JC ).EQ.ZERO ) THEN | |||||
| DO 80 JR = 1, N | |||||
| VR( JR, JC ) = VR( JR, JC )*TEMP | |||||
| 80 CONTINUE | |||||
| ELSE | |||||
| DO 90 JR = 1, N | |||||
| VR( JR, JC ) = VR( JR, JC )*TEMP | |||||
| VR( JR, JC+1 ) = VR( JR, JC+1 )*TEMP | |||||
| 90 CONTINUE | |||||
| END IF | |||||
| 100 CONTINUE | |||||
| END IF | |||||
| * | |||||
| * End of eigenvector calculation | |||||
| * | |||||
| END IF | |||||
| * | |||||
| * Undo scaling in alpha, beta | |||||
| * | |||||
| * Note: this does not give the alpha and beta for the unscaled | |||||
| * problem. | |||||
| * | |||||
| * Un-scaling is limited to avoid underflow in alpha and beta | |||||
| * if they are significant. | |||||
| * | |||||
| DO 110 JC = 1, N | |||||
| ABSAR = ABS( ALPHAR( JC ) ) | |||||
| ABSAI = ABS( ALPHAI( JC ) ) | |||||
| ABSB = ABS( BETA( JC ) ) | |||||
| SALFAR = ANRM*ALPHAR( JC ) | |||||
| SALFAI = ANRM*ALPHAI( JC ) | |||||
| SBETA = BNRM*BETA( JC ) | |||||
| ILIMIT = .FALSE. | |||||
| SCALE = ONE | |||||
| * | |||||
| * Check for significant underflow in ALPHAI | |||||
| * | |||||
| IF( ABS( SALFAI ).LT.SAFMIN .AND. ABSAI.GE. | |||||
| $ MAX( SAFMIN, EPS*ABSAR, EPS*ABSB ) ) THEN | |||||
| ILIMIT = .TRUE. | |||||
| SCALE = ( ONEPLS*SAFMIN / ANRM1 ) / | |||||
| $ MAX( ONEPLS*SAFMIN, ANRM2*ABSAI ) | |||||
| * | |||||
| ELSE IF( SALFAI.EQ.ZERO ) THEN | |||||
| * | |||||
| * If insignificant underflow in ALPHAI, then make the | |||||
| * conjugate eigenvalue real. | |||||
| * | |||||
| IF( ALPHAI( JC ).LT.ZERO .AND. JC.GT.1 ) THEN | |||||
| ALPHAI( JC-1 ) = ZERO | |||||
| ELSE IF( ALPHAI( JC ).GT.ZERO .AND. JC.LT.N ) THEN | |||||
| ALPHAI( JC+1 ) = ZERO | |||||
| END IF | |||||
| END IF | |||||
| * | |||||
| * Check for significant underflow in ALPHAR | |||||
| * | |||||
| IF( ABS( SALFAR ).LT.SAFMIN .AND. ABSAR.GE. | |||||
| $ MAX( SAFMIN, EPS*ABSAI, EPS*ABSB ) ) THEN | |||||
| ILIMIT = .TRUE. | |||||
| SCALE = MAX( SCALE, ( ONEPLS*SAFMIN / ANRM1 ) / | |||||
| $ MAX( ONEPLS*SAFMIN, ANRM2*ABSAR ) ) | |||||
| END IF | |||||
| * | |||||
| * Check for significant underflow in BETA | |||||
| * | |||||
| IF( ABS( SBETA ).LT.SAFMIN .AND. ABSB.GE. | |||||
| $ MAX( SAFMIN, EPS*ABSAR, EPS*ABSAI ) ) THEN | |||||
| ILIMIT = .TRUE. | |||||
| SCALE = MAX( SCALE, ( ONEPLS*SAFMIN / BNRM1 ) / | |||||
| $ MAX( ONEPLS*SAFMIN, BNRM2*ABSB ) ) | |||||
| END IF | |||||
| * | |||||
| * Check for possible overflow when limiting scaling | |||||
| * | |||||
| IF( ILIMIT ) THEN | |||||
| TEMP = ( SCALE*SAFMIN )*MAX( ABS( SALFAR ), ABS( SALFAI ), | |||||
| $ ABS( SBETA ) ) | |||||
| IF( TEMP.GT.ONE ) | |||||
| $ SCALE = SCALE / TEMP | |||||
| IF( SCALE.LT.ONE ) | |||||
| $ ILIMIT = .FALSE. | |||||
| END IF | |||||
| * | |||||
| * Recompute un-scaled ALPHAR, ALPHAI, BETA if necessary. | |||||
| * | |||||
| IF( ILIMIT ) THEN | |||||
| SALFAR = ( SCALE*ALPHAR( JC ) )*ANRM | |||||
| SALFAI = ( SCALE*ALPHAI( JC ) )*ANRM | |||||
| SBETA = ( SCALE*BETA( JC ) )*BNRM | |||||
| END IF | |||||
| ALPHAR( JC ) = SALFAR | |||||
| ALPHAI( JC ) = SALFAI | |||||
| BETA( JC ) = SBETA | |||||
| 110 CONTINUE | |||||
| * | |||||
| 120 CONTINUE | |||||
| WORK( 1 ) = LWKOPT | |||||
| * | |||||
| RETURN | |||||
| * | |||||
| * End of DGEGV | |||||
| * | |||||
| END | |||||
| @@ -0,0 +1,538 @@ | |||||
| *> \brief <b> SGEGS computes the eigenvalues, real Schur form, and, optionally, the left and/or right Schur vectors of a real matrix pair (A,B)</b> | |||||
| * | |||||
| * =========== DOCUMENTATION =========== | |||||
| * | |||||
| * Online html documentation available at | |||||
| * http://www.netlib.org/lapack/explore-html/ | |||||
| * | |||||
| *> \htmlonly | |||||
| *> Download SGEGS + dependencies | |||||
| *> <a href="http://www.netlib.org/cgi-bin/netlibfiles.tgz?format=tgz&filename=/lapack/lapack_routine/sgegs.f"> | |||||
| *> [TGZ]</a> | |||||
| *> <a href="http://www.netlib.org/cgi-bin/netlibfiles.zip?format=zip&filename=/lapack/lapack_routine/sgegs.f"> | |||||
| *> [ZIP]</a> | |||||
| *> <a href="http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/sgegs.f"> | |||||
| *> [TXT]</a> | |||||
| *> \endhtmlonly | |||||
| * | |||||
| * Definition: | |||||
| * =========== | |||||
| * | |||||
| * SUBROUTINE SGEGS( JOBVSL, JOBVSR, N, A, LDA, B, LDB, ALPHAR, | |||||
| * ALPHAI, BETA, VSL, LDVSL, VSR, LDVSR, WORK, | |||||
| * LWORK, INFO ) | |||||
| * | |||||
| * .. Scalar Arguments .. | |||||
| * CHARACTER JOBVSL, JOBVSR | |||||
| * INTEGER INFO, LDA, LDB, LDVSL, LDVSR, LWORK, N | |||||
| * .. | |||||
| * .. Array Arguments .. | |||||
| * REAL A( LDA, * ), ALPHAI( * ), ALPHAR( * ), | |||||
| * $ B( LDB, * ), BETA( * ), VSL( LDVSL, * ), | |||||
| * $ VSR( LDVSR, * ), WORK( * ) | |||||
| * .. | |||||
| * | |||||
| * | |||||
| *> \par Purpose: | |||||
| * ============= | |||||
| *> | |||||
| *> \verbatim | |||||
| *> | |||||
| *> This routine is deprecated and has been replaced by routine SGGES. | |||||
| *> | |||||
| *> SGEGS computes the eigenvalues, real Schur form, and, optionally, | |||||
| *> left and or/right Schur vectors of a real matrix pair (A,B). | |||||
| *> Given two square matrices A and B, the generalized real Schur | |||||
| *> factorization has the form | |||||
| *> | |||||
| *> A = Q*S*Z**T, B = Q*T*Z**T | |||||
| *> | |||||
| *> where Q and Z are orthogonal matrices, T is upper triangular, and S | |||||
| *> is an upper quasi-triangular matrix with 1-by-1 and 2-by-2 diagonal | |||||
| *> blocks, the 2-by-2 blocks corresponding to complex conjugate pairs | |||||
| *> of eigenvalues of (A,B). The columns of Q are the left Schur vectors | |||||
| *> and the columns of Z are the right Schur vectors. | |||||
| *> | |||||
| *> If only the eigenvalues of (A,B) are needed, the driver routine | |||||
| *> SGEGV should be used instead. See SGEGV for a description of the | |||||
| *> eigenvalues of the generalized nonsymmetric eigenvalue problem | |||||
| *> (GNEP). | |||||
| *> \endverbatim | |||||
| * | |||||
| * Arguments: | |||||
| * ========== | |||||
| * | |||||
| *> \param[in] JOBVSL | |||||
| *> \verbatim | |||||
| *> JOBVSL is CHARACTER*1 | |||||
| *> = 'N': do not compute the left Schur vectors; | |||||
| *> = 'V': compute the left Schur vectors (returned in VSL). | |||||
| *> \endverbatim | |||||
| *> | |||||
| *> \param[in] JOBVSR | |||||
| *> \verbatim | |||||
| *> JOBVSR is CHARACTER*1 | |||||
| *> = 'N': do not compute the right Schur vectors; | |||||
| *> = 'V': compute the right Schur vectors (returned in VSR). | |||||
| *> \endverbatim | |||||
| *> | |||||
| *> \param[in] N | |||||
| *> \verbatim | |||||
| *> N is INTEGER | |||||
| *> The order of the matrices A, B, VSL, and VSR. N >= 0. | |||||
| *> \endverbatim | |||||
| *> | |||||
| *> \param[in,out] A | |||||
| *> \verbatim | |||||
| *> A is REAL array, dimension (LDA, N) | |||||
| *> On entry, the matrix A. | |||||
| *> On exit, the upper quasi-triangular matrix S from the | |||||
| *> generalized real Schur factorization. | |||||
| *> \endverbatim | |||||
| *> | |||||
| *> \param[in] LDA | |||||
| *> \verbatim | |||||
| *> LDA is INTEGER | |||||
| *> The leading dimension of A. LDA >= max(1,N). | |||||
| *> \endverbatim | |||||
| *> | |||||
| *> \param[in,out] B | |||||
| *> \verbatim | |||||
| *> B is REAL array, dimension (LDB, N) | |||||
| *> On entry, the matrix B. | |||||
| *> On exit, the upper triangular matrix T from the generalized | |||||
| *> real Schur factorization. | |||||
| *> \endverbatim | |||||
| *> | |||||
| *> \param[in] LDB | |||||
| *> \verbatim | |||||
| *> LDB is INTEGER | |||||
| *> The leading dimension of B. LDB >= max(1,N). | |||||
| *> \endverbatim | |||||
| *> | |||||
| *> \param[out] ALPHAR | |||||
| *> \verbatim | |||||
| *> ALPHAR is REAL array, dimension (N) | |||||
| *> The real parts of each scalar alpha defining an eigenvalue | |||||
| *> of GNEP. | |||||
| *> \endverbatim | |||||
| *> | |||||
| *> \param[out] ALPHAI | |||||
| *> \verbatim | |||||
| *> ALPHAI is REAL array, dimension (N) | |||||
| *> The imaginary parts of each scalar alpha defining an | |||||
| *> eigenvalue of GNEP. If ALPHAI(j) is zero, then the j-th | |||||
| *> eigenvalue is real; if positive, then the j-th and (j+1)-st | |||||
| *> eigenvalues are a complex conjugate pair, with | |||||
| *> ALPHAI(j+1) = -ALPHAI(j). | |||||
| *> \endverbatim | |||||
| *> | |||||
| *> \param[out] BETA | |||||
| *> \verbatim | |||||
| *> BETA is REAL array, dimension (N) | |||||
| *> The scalars beta that define the eigenvalues of GNEP. | |||||
| *> Together, the quantities alpha = (ALPHAR(j),ALPHAI(j)) and | |||||
| *> beta = BETA(j) represent the j-th eigenvalue of the matrix | |||||
| *> pair (A,B), in one of the forms lambda = alpha/beta or | |||||
| *> mu = beta/alpha. Since either lambda or mu may overflow, | |||||
| *> they should not, in general, be computed. | |||||
| *> \endverbatim | |||||
| *> | |||||
| *> \param[out] VSL | |||||
| *> \verbatim | |||||
| *> VSL is REAL array, dimension (LDVSL,N) | |||||
| *> If JOBVSL = 'V', the matrix of left Schur vectors Q. | |||||
| *> Not referenced if JOBVSL = 'N'. | |||||
| *> \endverbatim | |||||
| *> | |||||
| *> \param[in] LDVSL | |||||
| *> \verbatim | |||||
| *> LDVSL is INTEGER | |||||
| *> The leading dimension of the matrix VSL. LDVSL >=1, and | |||||
| *> if JOBVSL = 'V', LDVSL >= N. | |||||
| *> \endverbatim | |||||
| *> | |||||
| *> \param[out] VSR | |||||
| *> \verbatim | |||||
| *> VSR is REAL array, dimension (LDVSR,N) | |||||
| *> If JOBVSR = 'V', the matrix of right Schur vectors Z. | |||||
| *> Not referenced if JOBVSR = 'N'. | |||||
| *> \endverbatim | |||||
| *> | |||||
| *> \param[in] LDVSR | |||||
| *> \verbatim | |||||
| *> LDVSR is INTEGER | |||||
| *> The leading dimension of the matrix VSR. LDVSR >= 1, and | |||||
| *> if JOBVSR = 'V', LDVSR >= N. | |||||
| *> \endverbatim | |||||
| *> | |||||
| *> \param[out] WORK | |||||
| *> \verbatim | |||||
| *> WORK is REAL array, dimension (MAX(1,LWORK)) | |||||
| *> On exit, if INFO = 0, WORK(1) returns the optimal LWORK. | |||||
| *> \endverbatim | |||||
| *> | |||||
| *> \param[in] LWORK | |||||
| *> \verbatim | |||||
| *> LWORK is INTEGER | |||||
| *> The dimension of the array WORK. LWORK >= max(1,4*N). | |||||
| *> For good performance, LWORK must generally be larger. | |||||
| *> To compute the optimal value of LWORK, call ILAENV to get | |||||
| *> blocksizes (for SGEQRF, SORMQR, and SORGQR.) Then compute: | |||||
| *> NB -- MAX of the blocksizes for SGEQRF, SORMQR, and SORGQR | |||||
| *> The optimal LWORK is 2*N + N*(NB+1). | |||||
| *> | |||||
| *> If LWORK = -1, then a workspace query is assumed; the routine | |||||
| *> only calculates the optimal size of the WORK array, returns | |||||
| *> this value as the first entry of the WORK array, and no error | |||||
| *> message related to LWORK is issued by XERBLA. | |||||
| *> \endverbatim | |||||
| *> | |||||
| *> \param[out] INFO | |||||
| *> \verbatim | |||||
| *> INFO is INTEGER | |||||
| *> = 0: successful exit | |||||
| *> < 0: if INFO = -i, the i-th argument had an illegal value. | |||||
| *> = 1,...,N: | |||||
| *> The QZ iteration failed. (A,B) are not in Schur | |||||
| *> form, but ALPHAR(j), ALPHAI(j), and BETA(j) should | |||||
| *> be correct for j=INFO+1,...,N. | |||||
| *> > N: errors that usually indicate LAPACK problems: | |||||
| *> =N+1: error return from SGGBAL | |||||
| *> =N+2: error return from SGEQRF | |||||
| *> =N+3: error return from SORMQR | |||||
| *> =N+4: error return from SORGQR | |||||
| *> =N+5: error return from SGGHRD | |||||
| *> =N+6: error return from SHGEQZ (other than failed | |||||
| *> iteration) | |||||
| *> =N+7: error return from SGGBAK (computing VSL) | |||||
| *> =N+8: error return from SGGBAK (computing VSR) | |||||
| *> =N+9: error return from SLASCL (various places) | |||||
| *> \endverbatim | |||||
| * | |||||
| * Authors: | |||||
| * ======== | |||||
| * | |||||
| *> \author Univ. of Tennessee | |||||
| *> \author Univ. of California Berkeley | |||||
| *> \author Univ. of Colorado Denver | |||||
| *> \author NAG Ltd. | |||||
| * | |||||
| *> \ingroup realGEeigen | |||||
| * | |||||
| * ===================================================================== | |||||
| SUBROUTINE SGEGS( JOBVSL, JOBVSR, N, A, LDA, B, LDB, ALPHAR, | |||||
| $ ALPHAI, BETA, VSL, LDVSL, VSR, LDVSR, WORK, | |||||
| $ LWORK, INFO ) | |||||
| * | |||||
| * -- LAPACK driver routine -- | |||||
| * -- LAPACK is a software package provided by Univ. of Tennessee, -- | |||||
| * -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..-- | |||||
| * | |||||
| * .. Scalar Arguments .. | |||||
| CHARACTER JOBVSL, JOBVSR | |||||
| INTEGER INFO, LDA, LDB, LDVSL, LDVSR, LWORK, N | |||||
| * .. | |||||
| * .. Array Arguments .. | |||||
| REAL A( LDA, * ), ALPHAI( * ), ALPHAR( * ), | |||||
| $ B( LDB, * ), BETA( * ), VSL( LDVSL, * ), | |||||
| $ VSR( LDVSR, * ), WORK( * ) | |||||
| * .. | |||||
| * | |||||
| * ===================================================================== | |||||
| * | |||||
| * .. Parameters .. | |||||
| REAL ZERO, ONE | |||||
| PARAMETER ( ZERO = 0.0E0, ONE = 1.0E0 ) | |||||
| * .. | |||||
| * .. Local Scalars .. | |||||
| LOGICAL ILASCL, ILBSCL, ILVSL, ILVSR, LQUERY | |||||
| INTEGER ICOLS, IHI, IINFO, IJOBVL, IJOBVR, ILEFT, | |||||
| $ ILO, IRIGHT, IROWS, ITAU, IWORK, LOPT, LWKMIN, | |||||
| $ LWKOPT, NB, NB1, NB2, NB3 | |||||
| REAL ANRM, ANRMTO, BIGNUM, BNRM, BNRMTO, EPS, | |||||
| $ SAFMIN, SMLNUM | |||||
| * .. | |||||
| * .. External Subroutines .. | |||||
| EXTERNAL SGEQRF, SGGBAK, SGGBAL, SGGHRD, SHGEQZ, SLACPY, | |||||
| $ SLASCL, SLASET, SORGQR, SORMQR, XERBLA | |||||
| * .. | |||||
| * .. External Functions .. | |||||
| LOGICAL LSAME | |||||
| INTEGER ILAENV | |||||
| REAL SLAMCH, SLANGE | |||||
| EXTERNAL ILAENV, LSAME, SLAMCH, SLANGE | |||||
| * .. | |||||
| * .. Intrinsic Functions .. | |||||
| INTRINSIC INT, MAX | |||||
| * .. | |||||
| * .. Executable Statements .. | |||||
| * | |||||
| * Decode the input arguments | |||||
| * | |||||
| IF( LSAME( JOBVSL, 'N' ) ) THEN | |||||
| IJOBVL = 1 | |||||
| ILVSL = .FALSE. | |||||
| ELSE IF( LSAME( JOBVSL, 'V' ) ) THEN | |||||
| IJOBVL = 2 | |||||
| ILVSL = .TRUE. | |||||
| ELSE | |||||
| IJOBVL = -1 | |||||
| ILVSL = .FALSE. | |||||
| END IF | |||||
| * | |||||
| IF( LSAME( JOBVSR, 'N' ) ) THEN | |||||
| IJOBVR = 1 | |||||
| ILVSR = .FALSE. | |||||
| ELSE IF( LSAME( JOBVSR, 'V' ) ) THEN | |||||
| IJOBVR = 2 | |||||
| ILVSR = .TRUE. | |||||
| ELSE | |||||
| IJOBVR = -1 | |||||
| ILVSR = .FALSE. | |||||
| END IF | |||||
| * | |||||
| * Test the input arguments | |||||
| * | |||||
| LWKMIN = MAX( 4*N, 1 ) | |||||
| LWKOPT = LWKMIN | |||||
| WORK( 1 ) = LWKOPT | |||||
| LQUERY = ( LWORK.EQ.-1 ) | |||||
| INFO = 0 | |||||
| IF( IJOBVL.LE.0 ) THEN | |||||
| INFO = -1 | |||||
| ELSE IF( IJOBVR.LE.0 ) THEN | |||||
| INFO = -2 | |||||
| ELSE IF( N.LT.0 ) THEN | |||||
| INFO = -3 | |||||
| ELSE IF( LDA.LT.MAX( 1, N ) ) THEN | |||||
| INFO = -5 | |||||
| ELSE IF( LDB.LT.MAX( 1, N ) ) THEN | |||||
| INFO = -7 | |||||
| ELSE IF( LDVSL.LT.1 .OR. ( ILVSL .AND. LDVSL.LT.N ) ) THEN | |||||
| INFO = -12 | |||||
| ELSE IF( LDVSR.LT.1 .OR. ( ILVSR .AND. LDVSR.LT.N ) ) THEN | |||||
| INFO = -14 | |||||
| ELSE IF( LWORK.LT.LWKMIN .AND. .NOT.LQUERY ) THEN | |||||
| INFO = -16 | |||||
| END IF | |||||
| * | |||||
| IF( INFO.EQ.0 ) THEN | |||||
| NB1 = ILAENV( 1, 'SGEQRF', ' ', N, N, -1, -1 ) | |||||
| NB2 = ILAENV( 1, 'SORMQR', ' ', N, N, N, -1 ) | |||||
| NB3 = ILAENV( 1, 'SORGQR', ' ', N, N, N, -1 ) | |||||
| NB = MAX( NB1, NB2, NB3 ) | |||||
| LOPT = 2*N+N*(NB+1) | |||||
| WORK( 1 ) = LOPT | |||||
| END IF | |||||
| * | |||||
| IF( INFO.NE.0 ) THEN | |||||
| CALL XERBLA( 'SGEGS ', -INFO ) | |||||
| RETURN | |||||
| ELSE IF( LQUERY ) THEN | |||||
| RETURN | |||||
| END IF | |||||
| * | |||||
| * Quick return if possible | |||||
| * | |||||
| IF( N.EQ.0 ) | |||||
| $ RETURN | |||||
| * | |||||
| * Get machine constants | |||||
| * | |||||
| EPS = SLAMCH( 'E' )*SLAMCH( 'B' ) | |||||
| SAFMIN = SLAMCH( 'S' ) | |||||
| SMLNUM = N*SAFMIN / EPS | |||||
| BIGNUM = ONE / SMLNUM | |||||
| * | |||||
| * Scale A if max element outside range [SMLNUM,BIGNUM] | |||||
| * | |||||
| ANRM = SLANGE( 'M', N, N, A, LDA, WORK ) | |||||
| ILASCL = .FALSE. | |||||
| IF( ANRM.GT.ZERO .AND. ANRM.LT.SMLNUM ) THEN | |||||
| ANRMTO = SMLNUM | |||||
| ILASCL = .TRUE. | |||||
| ELSE IF( ANRM.GT.BIGNUM ) THEN | |||||
| ANRMTO = BIGNUM | |||||
| ILASCL = .TRUE. | |||||
| END IF | |||||
| * | |||||
| IF( ILASCL ) THEN | |||||
| CALL SLASCL( 'G', -1, -1, ANRM, ANRMTO, N, N, A, LDA, IINFO ) | |||||
| IF( IINFO.NE.0 ) THEN | |||||
| INFO = N + 9 | |||||
| RETURN | |||||
| END IF | |||||
| END IF | |||||
| * | |||||
| * Scale B if max element outside range [SMLNUM,BIGNUM] | |||||
| * | |||||
| BNRM = SLANGE( 'M', N, N, B, LDB, WORK ) | |||||
| ILBSCL = .FALSE. | |||||
| IF( BNRM.GT.ZERO .AND. BNRM.LT.SMLNUM ) THEN | |||||
| BNRMTO = SMLNUM | |||||
| ILBSCL = .TRUE. | |||||
| ELSE IF( BNRM.GT.BIGNUM ) THEN | |||||
| BNRMTO = BIGNUM | |||||
| ILBSCL = .TRUE. | |||||
| END IF | |||||
| * | |||||
| IF( ILBSCL ) THEN | |||||
| CALL SLASCL( 'G', -1, -1, BNRM, BNRMTO, N, N, B, LDB, IINFO ) | |||||
| IF( IINFO.NE.0 ) THEN | |||||
| INFO = N + 9 | |||||
| RETURN | |||||
| END IF | |||||
| END IF | |||||
| * | |||||
| * Permute the matrix to make it more nearly triangular | |||||
| * Workspace layout: (2*N words -- "work..." not actually used) | |||||
| * left_permutation, right_permutation, work... | |||||
| * | |||||
| ILEFT = 1 | |||||
| IRIGHT = N + 1 | |||||
| IWORK = IRIGHT + N | |||||
| CALL SGGBAL( 'P', N, A, LDA, B, LDB, ILO, IHI, WORK( ILEFT ), | |||||
| $ WORK( IRIGHT ), WORK( IWORK ), IINFO ) | |||||
| IF( IINFO.NE.0 ) THEN | |||||
| INFO = N + 1 | |||||
| GO TO 10 | |||||
| END IF | |||||
| * | |||||
| * Reduce B to triangular form, and initialize VSL and/or VSR | |||||
| * Workspace layout: ("work..." must have at least N words) | |||||
| * left_permutation, right_permutation, tau, work... | |||||
| * | |||||
| IROWS = IHI + 1 - ILO | |||||
| ICOLS = N + 1 - ILO | |||||
| ITAU = IWORK | |||||
| IWORK = ITAU + IROWS | |||||
| CALL SGEQRF( IROWS, ICOLS, B( ILO, ILO ), LDB, WORK( ITAU ), | |||||
| $ WORK( IWORK ), LWORK+1-IWORK, IINFO ) | |||||
| IF( IINFO.GE.0 ) | |||||
| $ LWKOPT = MAX( LWKOPT, INT( WORK( IWORK ) )+IWORK-1 ) | |||||
| IF( IINFO.NE.0 ) THEN | |||||
| INFO = N + 2 | |||||
| GO TO 10 | |||||
| END IF | |||||
| * | |||||
| CALL SORMQR( 'L', 'T', IROWS, ICOLS, IROWS, B( ILO, ILO ), LDB, | |||||
| $ WORK( ITAU ), A( ILO, ILO ), LDA, WORK( IWORK ), | |||||
| $ LWORK+1-IWORK, IINFO ) | |||||
| IF( IINFO.GE.0 ) | |||||
| $ LWKOPT = MAX( LWKOPT, INT( WORK( IWORK ) )+IWORK-1 ) | |||||
| IF( IINFO.NE.0 ) THEN | |||||
| INFO = N + 3 | |||||
| GO TO 10 | |||||
| END IF | |||||
| * | |||||
| IF( ILVSL ) THEN | |||||
| CALL SLASET( 'Full', N, N, ZERO, ONE, VSL, LDVSL ) | |||||
| CALL SLACPY( 'L', IROWS-1, IROWS-1, B( ILO+1, ILO ), LDB, | |||||
| $ VSL( ILO+1, ILO ), LDVSL ) | |||||
| CALL SORGQR( IROWS, IROWS, IROWS, VSL( ILO, ILO ), LDVSL, | |||||
| $ WORK( ITAU ), WORK( IWORK ), LWORK+1-IWORK, | |||||
| $ IINFO ) | |||||
| IF( IINFO.GE.0 ) | |||||
| $ LWKOPT = MAX( LWKOPT, INT( WORK( IWORK ) )+IWORK-1 ) | |||||
| IF( IINFO.NE.0 ) THEN | |||||
| INFO = N + 4 | |||||
| GO TO 10 | |||||
| END IF | |||||
| END IF | |||||
| * | |||||
| IF( ILVSR ) | |||||
| $ CALL SLASET( 'Full', N, N, ZERO, ONE, VSR, LDVSR ) | |||||
| * | |||||
| * Reduce to generalized Hessenberg form | |||||
| * | |||||
| CALL SGGHRD( JOBVSL, JOBVSR, N, ILO, IHI, A, LDA, B, LDB, VSL, | |||||
| $ LDVSL, VSR, LDVSR, IINFO ) | |||||
| IF( IINFO.NE.0 ) THEN | |||||
| INFO = N + 5 | |||||
| GO TO 10 | |||||
| END IF | |||||
| * | |||||
| * Perform QZ algorithm, computing Schur vectors if desired | |||||
| * Workspace layout: ("work..." must have at least 1 word) | |||||
| * left_permutation, right_permutation, work... | |||||
| * | |||||
| IWORK = ITAU | |||||
| CALL SHGEQZ( 'S', JOBVSL, JOBVSR, N, ILO, IHI, A, LDA, B, LDB, | |||||
| $ ALPHAR, ALPHAI, BETA, VSL, LDVSL, VSR, LDVSR, | |||||
| $ WORK( IWORK ), LWORK+1-IWORK, IINFO ) | |||||
| IF( IINFO.GE.0 ) | |||||
| $ LWKOPT = MAX( LWKOPT, INT( WORK( IWORK ) )+IWORK-1 ) | |||||
| IF( IINFO.NE.0 ) THEN | |||||
| IF( IINFO.GT.0 .AND. IINFO.LE.N ) THEN | |||||
| INFO = IINFO | |||||
| ELSE IF( IINFO.GT.N .AND. IINFO.LE.2*N ) THEN | |||||
| INFO = IINFO - N | |||||
| ELSE | |||||
| INFO = N + 6 | |||||
| END IF | |||||
| GO TO 10 | |||||
| END IF | |||||
| * | |||||
| * Apply permutation to VSL and VSR | |||||
| * | |||||
| IF( ILVSL ) THEN | |||||
| CALL SGGBAK( 'P', 'L', N, ILO, IHI, WORK( ILEFT ), | |||||
| $ WORK( IRIGHT ), N, VSL, LDVSL, IINFO ) | |||||
| IF( IINFO.NE.0 ) THEN | |||||
| INFO = N + 7 | |||||
| GO TO 10 | |||||
| END IF | |||||
| END IF | |||||
| IF( ILVSR ) THEN | |||||
| CALL SGGBAK( 'P', 'R', N, ILO, IHI, WORK( ILEFT ), | |||||
| $ WORK( IRIGHT ), N, VSR, LDVSR, IINFO ) | |||||
| IF( IINFO.NE.0 ) THEN | |||||
| INFO = N + 8 | |||||
| GO TO 10 | |||||
| END IF | |||||
| END IF | |||||
| * | |||||
| * Undo scaling | |||||
| * | |||||
| IF( ILASCL ) THEN | |||||
| CALL SLASCL( 'H', -1, -1, ANRMTO, ANRM, N, N, A, LDA, IINFO ) | |||||
| IF( IINFO.NE.0 ) THEN | |||||
| INFO = N + 9 | |||||
| RETURN | |||||
| END IF | |||||
| CALL SLASCL( 'G', -1, -1, ANRMTO, ANRM, N, 1, ALPHAR, N, | |||||
| $ IINFO ) | |||||
| IF( IINFO.NE.0 ) THEN | |||||
| INFO = N + 9 | |||||
| RETURN | |||||
| END IF | |||||
| CALL SLASCL( 'G', -1, -1, ANRMTO, ANRM, N, 1, ALPHAI, N, | |||||
| $ IINFO ) | |||||
| IF( IINFO.NE.0 ) THEN | |||||
| INFO = N + 9 | |||||
| RETURN | |||||
| END IF | |||||
| END IF | |||||
| * | |||||
| IF( ILBSCL ) THEN | |||||
| CALL SLASCL( 'U', -1, -1, BNRMTO, BNRM, N, N, B, LDB, IINFO ) | |||||
| IF( IINFO.NE.0 ) THEN | |||||
| INFO = N + 9 | |||||
| RETURN | |||||
| END IF | |||||
| CALL SLASCL( 'G', -1, -1, BNRMTO, BNRM, N, 1, BETA, N, IINFO ) | |||||
| IF( IINFO.NE.0 ) THEN | |||||
| INFO = N + 9 | |||||
| RETURN | |||||
| END IF | |||||
| END IF | |||||
| * | |||||
| 10 CONTINUE | |||||
| WORK( 1 ) = LWKOPT | |||||
| * | |||||
| RETURN | |||||
| * | |||||
| * End of SGEGS | |||||
| * | |||||
| END | |||||
| @@ -0,0 +1,766 @@ | |||||
| *> \brief <b> SGEGV computes the eigenvalues and, optionally, the left and/or right eigenvectors of a real matrix pair (A,B).</b> | |||||
| * | |||||
| * =========== DOCUMENTATION =========== | |||||
| * | |||||
| * Online html documentation available at | |||||
| * http://www.netlib.org/lapack/explore-html/ | |||||
| * | |||||
| *> \htmlonly | |||||
| *> Download SGEGV + dependencies | |||||
| *> <a href="http://www.netlib.org/cgi-bin/netlibfiles.tgz?format=tgz&filename=/lapack/lapack_routine/sgegv.f"> | |||||
| *> [TGZ]</a> | |||||
| *> <a href="http://www.netlib.org/cgi-bin/netlibfiles.zip?format=zip&filename=/lapack/lapack_routine/sgegv.f"> | |||||
| *> [ZIP]</a> | |||||
| *> <a href="http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/sgegv.f"> | |||||
| *> [TXT]</a> | |||||
| *> \endhtmlonly | |||||
| * | |||||
| * Definition: | |||||
| * =========== | |||||
| * | |||||
| * SUBROUTINE SGEGV( JOBVL, JOBVR, N, A, LDA, B, LDB, ALPHAR, ALPHAI, | |||||
| * BETA, VL, LDVL, VR, LDVR, WORK, LWORK, INFO ) | |||||
| * | |||||
| * .. Scalar Arguments .. | |||||
| * CHARACTER JOBVL, JOBVR | |||||
| * INTEGER INFO, LDA, LDB, LDVL, LDVR, LWORK, N | |||||
| * .. | |||||
| * .. Array Arguments .. | |||||
| * REAL A( LDA, * ), ALPHAI( * ), ALPHAR( * ), | |||||
| * $ B( LDB, * ), BETA( * ), VL( LDVL, * ), | |||||
| * $ VR( LDVR, * ), WORK( * ) | |||||
| * .. | |||||
| * | |||||
| * | |||||
| *> \par Purpose: | |||||
| * ============= | |||||
| *> | |||||
| *> \verbatim | |||||
| *> | |||||
| *> This routine is deprecated and has been replaced by routine SGGEV. | |||||
| *> | |||||
| *> SGEGV computes the eigenvalues and, optionally, the left and/or right | |||||
| *> eigenvectors of a real matrix pair (A,B). | |||||
| *> Given two square matrices A and B, | |||||
| *> the generalized nonsymmetric eigenvalue problem (GNEP) is to find the | |||||
| *> eigenvalues lambda and corresponding (non-zero) eigenvectors x such | |||||
| *> that | |||||
| *> | |||||
| *> A*x = lambda*B*x. | |||||
| *> | |||||
| *> An alternate form is to find the eigenvalues mu and corresponding | |||||
| *> eigenvectors y such that | |||||
| *> | |||||
| *> mu*A*y = B*y. | |||||
| *> | |||||
| *> These two forms are equivalent with mu = 1/lambda and x = y if | |||||
| *> neither lambda nor mu is zero. In order to deal with the case that | |||||
| *> lambda or mu is zero or small, two values alpha and beta are returned | |||||
| *> for each eigenvalue, such that lambda = alpha/beta and | |||||
| *> mu = beta/alpha. | |||||
| *> | |||||
| *> The vectors x and y in the above equations are right eigenvectors of | |||||
| *> the matrix pair (A,B). Vectors u and v satisfying | |||||
| *> | |||||
| *> u**H*A = lambda*u**H*B or mu*v**H*A = v**H*B | |||||
| *> | |||||
| *> are left eigenvectors of (A,B). | |||||
| *> | |||||
| *> Note: this routine performs "full balancing" on A and B | |||||
| *> \endverbatim | |||||
| * | |||||
| * Arguments: | |||||
| * ========== | |||||
| * | |||||
| *> \param[in] JOBVL | |||||
| *> \verbatim | |||||
| *> JOBVL is CHARACTER*1 | |||||
| *> = 'N': do not compute the left generalized eigenvectors; | |||||
| *> = 'V': compute the left generalized eigenvectors (returned | |||||
| *> in VL). | |||||
| *> \endverbatim | |||||
| *> | |||||
| *> \param[in] JOBVR | |||||
| *> \verbatim | |||||
| *> JOBVR is CHARACTER*1 | |||||
| *> = 'N': do not compute the right generalized eigenvectors; | |||||
| *> = 'V': compute the right generalized eigenvectors (returned | |||||
| *> in VR). | |||||
| *> \endverbatim | |||||
| *> | |||||
| *> \param[in] N | |||||
| *> \verbatim | |||||
| *> N is INTEGER | |||||
| *> The order of the matrices A, B, VL, and VR. N >= 0. | |||||
| *> \endverbatim | |||||
| *> | |||||
| *> \param[in,out] A | |||||
| *> \verbatim | |||||
| *> A is REAL array, dimension (LDA, N) | |||||
| *> On entry, the matrix A. | |||||
| *> If JOBVL = 'V' or JOBVR = 'V', then on exit A | |||||
| *> contains the real Schur form of A from the generalized Schur | |||||
| *> factorization of the pair (A,B) after balancing. | |||||
| *> If no eigenvectors were computed, then only the diagonal | |||||
| *> blocks from the Schur form will be correct. See SGGHRD and | |||||
| *> SHGEQZ for details. | |||||
| *> \endverbatim | |||||
| *> | |||||
| *> \param[in] LDA | |||||
| *> \verbatim | |||||
| *> LDA is INTEGER | |||||
| *> The leading dimension of A. LDA >= max(1,N). | |||||
| *> \endverbatim | |||||
| *> | |||||
| *> \param[in,out] B | |||||
| *> \verbatim | |||||
| *> B is REAL array, dimension (LDB, N) | |||||
| *> On entry, the matrix B. | |||||
| *> If JOBVL = 'V' or JOBVR = 'V', then on exit B contains the | |||||
| *> upper triangular matrix obtained from B in the generalized | |||||
| *> Schur factorization of the pair (A,B) after balancing. | |||||
| *> If no eigenvectors were computed, then only those elements of | |||||
| *> B corresponding to the diagonal blocks from the Schur form of | |||||
| *> A will be correct. See SGGHRD and SHGEQZ for details. | |||||
| *> \endverbatim | |||||
| *> | |||||
| *> \param[in] LDB | |||||
| *> \verbatim | |||||
| *> LDB is INTEGER | |||||
| *> The leading dimension of B. LDB >= max(1,N). | |||||
| *> \endverbatim | |||||
| *> | |||||
| *> \param[out] ALPHAR | |||||
| *> \verbatim | |||||
| *> ALPHAR is REAL array, dimension (N) | |||||
| *> The real parts of each scalar alpha defining an eigenvalue of | |||||
| *> GNEP. | |||||
| *> \endverbatim | |||||
| *> | |||||
| *> \param[out] ALPHAI | |||||
| *> \verbatim | |||||
| *> ALPHAI is REAL array, dimension (N) | |||||
| *> The imaginary parts of each scalar alpha defining an | |||||
| *> eigenvalue of GNEP. If ALPHAI(j) is zero, then the j-th | |||||
| *> eigenvalue is real; if positive, then the j-th and | |||||
| *> (j+1)-st eigenvalues are a complex conjugate pair, with | |||||
| *> ALPHAI(j+1) = -ALPHAI(j). | |||||
| *> \endverbatim | |||||
| *> | |||||
| *> \param[out] BETA | |||||
| *> \verbatim | |||||
| *> BETA is REAL array, dimension (N) | |||||
| *> The scalars beta that define the eigenvalues of GNEP. | |||||
| *> | |||||
| *> Together, the quantities alpha = (ALPHAR(j),ALPHAI(j)) and | |||||
| *> beta = BETA(j) represent the j-th eigenvalue of the matrix | |||||
| *> pair (A,B), in one of the forms lambda = alpha/beta or | |||||
| *> mu = beta/alpha. Since either lambda or mu may overflow, | |||||
| *> they should not, in general, be computed. | |||||
| *> \endverbatim | |||||
| *> | |||||
| *> \param[out] VL | |||||
| *> \verbatim | |||||
| *> VL is REAL array, dimension (LDVL,N) | |||||
| *> If JOBVL = 'V', the left eigenvectors u(j) are stored | |||||
| *> in the columns of VL, in the same order as their eigenvalues. | |||||
| *> If the j-th eigenvalue is real, then u(j) = VL(:,j). | |||||
| *> If the j-th and (j+1)-st eigenvalues form a complex conjugate | |||||
| *> pair, then | |||||
| *> u(j) = VL(:,j) + i*VL(:,j+1) | |||||
| *> and | |||||
| *> u(j+1) = VL(:,j) - i*VL(:,j+1). | |||||
| *> | |||||
| *> Each eigenvector is scaled so that its largest component has | |||||
| *> abs(real part) + abs(imag. part) = 1, except for eigenvectors | |||||
| *> corresponding to an eigenvalue with alpha = beta = 0, which | |||||
| *> are set to zero. | |||||
| *> Not referenced if JOBVL = 'N'. | |||||
| *> \endverbatim | |||||
| *> | |||||
| *> \param[in] LDVL | |||||
| *> \verbatim | |||||
| *> LDVL is INTEGER | |||||
| *> The leading dimension of the matrix VL. LDVL >= 1, and | |||||
| *> if JOBVL = 'V', LDVL >= N. | |||||
| *> \endverbatim | |||||
| *> | |||||
| *> \param[out] VR | |||||
| *> \verbatim | |||||
| *> VR is REAL array, dimension (LDVR,N) | |||||
| *> If JOBVR = 'V', the right eigenvectors x(j) are stored | |||||
| *> in the columns of VR, in the same order as their eigenvalues. | |||||
| *> If the j-th eigenvalue is real, then x(j) = VR(:,j). | |||||
| *> If the j-th and (j+1)-st eigenvalues form a complex conjugate | |||||
| *> pair, then | |||||
| *> x(j) = VR(:,j) + i*VR(:,j+1) | |||||
| *> and | |||||
| *> x(j+1) = VR(:,j) - i*VR(:,j+1). | |||||
| *> | |||||
| *> Each eigenvector is scaled so that its largest component has | |||||
| *> abs(real part) + abs(imag. part) = 1, except for eigenvalues | |||||
| *> corresponding to an eigenvalue with alpha = beta = 0, which | |||||
| *> are set to zero. | |||||
| *> Not referenced if JOBVR = 'N'. | |||||
| *> \endverbatim | |||||
| *> | |||||
| *> \param[in] LDVR | |||||
| *> \verbatim | |||||
| *> LDVR is INTEGER | |||||
| *> The leading dimension of the matrix VR. LDVR >= 1, and | |||||
| *> if JOBVR = 'V', LDVR >= N. | |||||
| *> \endverbatim | |||||
| *> | |||||
| *> \param[out] WORK | |||||
| *> \verbatim | |||||
| *> WORK is REAL array, dimension (MAX(1,LWORK)) | |||||
| *> On exit, if INFO = 0, WORK(1) returns the optimal LWORK. | |||||
| *> \endverbatim | |||||
| *> | |||||
| *> \param[in] LWORK | |||||
| *> \verbatim | |||||
| *> LWORK is INTEGER | |||||
| *> The dimension of the array WORK. LWORK >= max(1,8*N). | |||||
| *> For good performance, LWORK must generally be larger. | |||||
| *> To compute the optimal value of LWORK, call ILAENV to get | |||||
| *> blocksizes (for SGEQRF, SORMQR, and SORGQR.) Then compute: | |||||
| *> NB -- MAX of the blocksizes for SGEQRF, SORMQR, and SORGQR; | |||||
| *> The optimal LWORK is: | |||||
| *> 2*N + MAX( 6*N, N*(NB+1) ). | |||||
| *> | |||||
| *> If LWORK = -1, then a workspace query is assumed; the routine | |||||
| *> only calculates the optimal size of the WORK array, returns | |||||
| *> this value as the first entry of the WORK array, and no error | |||||
| *> message related to LWORK is issued by XERBLA. | |||||
| *> \endverbatim | |||||
| *> | |||||
| *> \param[out] INFO | |||||
| *> \verbatim | |||||
| *> INFO is INTEGER | |||||
| *> = 0: successful exit | |||||
| *> < 0: if INFO = -i, the i-th argument had an illegal value. | |||||
| *> = 1,...,N: | |||||
| *> The QZ iteration failed. No eigenvectors have been | |||||
| *> calculated, but ALPHAR(j), ALPHAI(j), and BETA(j) | |||||
| *> should be correct for j=INFO+1,...,N. | |||||
| *> > N: errors that usually indicate LAPACK problems: | |||||
| *> =N+1: error return from SGGBAL | |||||
| *> =N+2: error return from SGEQRF | |||||
| *> =N+3: error return from SORMQR | |||||
| *> =N+4: error return from SORGQR | |||||
| *> =N+5: error return from SGGHRD | |||||
| *> =N+6: error return from SHGEQZ (other than failed | |||||
| *> iteration) | |||||
| *> =N+7: error return from STGEVC | |||||
| *> =N+8: error return from SGGBAK (computing VL) | |||||
| *> =N+9: error return from SGGBAK (computing VR) | |||||
| *> =N+10: error return from SLASCL (various calls) | |||||
| *> \endverbatim | |||||
| * | |||||
| * Authors: | |||||
| * ======== | |||||
| * | |||||
| *> \author Univ. of Tennessee | |||||
| *> \author Univ. of California Berkeley | |||||
| *> \author Univ. of Colorado Denver | |||||
| *> \author NAG Ltd. | |||||
| * | |||||
| *> \ingroup realGEeigen | |||||
| * | |||||
| *> \par Further Details: | |||||
| * ===================== | |||||
| *> | |||||
| *> \verbatim | |||||
| *> | |||||
| *> Balancing | |||||
| *> --------- | |||||
| *> | |||||
| *> This driver calls SGGBAL to both permute and scale rows and columns | |||||
| *> of A and B. The permutations PL and PR are chosen so that PL*A*PR | |||||
| *> and PL*B*R will be upper triangular except for the diagonal blocks | |||||
| *> A(i:j,i:j) and B(i:j,i:j), with i and j as close together as | |||||
| *> possible. The diagonal scaling matrices DL and DR are chosen so | |||||
| *> that the pair DL*PL*A*PR*DR, DL*PL*B*PR*DR have elements close to | |||||
| *> one (except for the elements that start out zero.) | |||||
| *> | |||||
| *> After the eigenvalues and eigenvectors of the balanced matrices | |||||
| *> have been computed, SGGBAK transforms the eigenvectors back to what | |||||
| *> they would have been (in perfect arithmetic) if they had not been | |||||
| *> balanced. | |||||
| *> | |||||
| *> Contents of A and B on Exit | |||||
| *> -------- -- - --- - -- ---- | |||||
| *> | |||||
| *> If any eigenvectors are computed (either JOBVL='V' or JOBVR='V' or | |||||
| *> both), then on exit the arrays A and B will contain the real Schur | |||||
| *> form[*] of the "balanced" versions of A and B. If no eigenvectors | |||||
| *> are computed, then only the diagonal blocks will be correct. | |||||
| *> | |||||
| *> [*] See SHGEQZ, SGEGS, or read the book "Matrix Computations", | |||||
| *> by Golub & van Loan, pub. by Johns Hopkins U. Press. | |||||
| *> \endverbatim | |||||
| *> | |||||
| * ===================================================================== | |||||
| SUBROUTINE SGEGV( JOBVL, JOBVR, N, A, LDA, B, LDB, ALPHAR, ALPHAI, | |||||
| $ BETA, VL, LDVL, VR, LDVR, WORK, LWORK, INFO ) | |||||
| * | |||||
| * -- LAPACK driver routine -- | |||||
| * -- LAPACK is a software package provided by Univ. of Tennessee, -- | |||||
| * -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..-- | |||||
| * | |||||
| * .. Scalar Arguments .. | |||||
| CHARACTER JOBVL, JOBVR | |||||
| INTEGER INFO, LDA, LDB, LDVL, LDVR, LWORK, N | |||||
| * .. | |||||
| * .. Array Arguments .. | |||||
| REAL A( LDA, * ), ALPHAI( * ), ALPHAR( * ), | |||||
| $ B( LDB, * ), BETA( * ), VL( LDVL, * ), | |||||
| $ VR( LDVR, * ), WORK( * ) | |||||
| * .. | |||||
| * | |||||
| * ===================================================================== | |||||
| * | |||||
| * .. Parameters .. | |||||
| REAL ZERO, ONE | |||||
| PARAMETER ( ZERO = 0.0E0, ONE = 1.0E0 ) | |||||
| * .. | |||||
| * .. Local Scalars .. | |||||
| LOGICAL ILIMIT, ILV, ILVL, ILVR, LQUERY | |||||
| CHARACTER CHTEMP | |||||
| INTEGER ICOLS, IHI, IINFO, IJOBVL, IJOBVR, ILEFT, ILO, | |||||
| $ IN, IRIGHT, IROWS, ITAU, IWORK, JC, JR, LOPT, | |||||
| $ LWKMIN, LWKOPT, NB, NB1, NB2, NB3 | |||||
| REAL ABSAI, ABSAR, ABSB, ANRM, ANRM1, ANRM2, BNRM, | |||||
| $ BNRM1, BNRM2, EPS, ONEPLS, SAFMAX, SAFMIN, | |||||
| $ SALFAI, SALFAR, SBETA, SCALE, TEMP | |||||
| * .. | |||||
| * .. Local Arrays .. | |||||
| LOGICAL LDUMMA( 1 ) | |||||
| * .. | |||||
| * .. External Subroutines .. | |||||
| EXTERNAL SGEQRF, SGGBAK, SGGBAL, SGGHRD, SHGEQZ, SLACPY, | |||||
| $ SLASCL, SLASET, SORGQR, SORMQR, STGEVC, XERBLA | |||||
| * .. | |||||
| * .. External Functions .. | |||||
| LOGICAL LSAME | |||||
| INTEGER ILAENV | |||||
| REAL SLAMCH, SLANGE | |||||
| EXTERNAL ILAENV, LSAME, SLAMCH, SLANGE | |||||
| * .. | |||||
| * .. Intrinsic Functions .. | |||||
| INTRINSIC ABS, INT, MAX | |||||
| * .. | |||||
| * .. Executable Statements .. | |||||
| * | |||||
| * Decode the input arguments | |||||
| * | |||||
| IF( LSAME( JOBVL, 'N' ) ) THEN | |||||
| IJOBVL = 1 | |||||
| ILVL = .FALSE. | |||||
| ELSE IF( LSAME( JOBVL, 'V' ) ) THEN | |||||
| IJOBVL = 2 | |||||
| ILVL = .TRUE. | |||||
| ELSE | |||||
| IJOBVL = -1 | |||||
| ILVL = .FALSE. | |||||
| END IF | |||||
| * | |||||
| IF( LSAME( JOBVR, 'N' ) ) THEN | |||||
| IJOBVR = 1 | |||||
| ILVR = .FALSE. | |||||
| ELSE IF( LSAME( JOBVR, 'V' ) ) THEN | |||||
| IJOBVR = 2 | |||||
| ILVR = .TRUE. | |||||
| ELSE | |||||
| IJOBVR = -1 | |||||
| ILVR = .FALSE. | |||||
| END IF | |||||
| ILV = ILVL .OR. ILVR | |||||
| * | |||||
| * Test the input arguments | |||||
| * | |||||
| LWKMIN = MAX( 8*N, 1 ) | |||||
| LWKOPT = LWKMIN | |||||
| WORK( 1 ) = LWKOPT | |||||
| LQUERY = ( LWORK.EQ.-1 ) | |||||
| INFO = 0 | |||||
| IF( IJOBVL.LE.0 ) THEN | |||||
| INFO = -1 | |||||
| ELSE IF( IJOBVR.LE.0 ) THEN | |||||
| INFO = -2 | |||||
| ELSE IF( N.LT.0 ) THEN | |||||
| INFO = -3 | |||||
| ELSE IF( LDA.LT.MAX( 1, N ) ) THEN | |||||
| INFO = -5 | |||||
| ELSE IF( LDB.LT.MAX( 1, N ) ) THEN | |||||
| INFO = -7 | |||||
| ELSE IF( LDVL.LT.1 .OR. ( ILVL .AND. LDVL.LT.N ) ) THEN | |||||
| INFO = -12 | |||||
| ELSE IF( LDVR.LT.1 .OR. ( ILVR .AND. LDVR.LT.N ) ) THEN | |||||
| INFO = -14 | |||||
| ELSE IF( LWORK.LT.LWKMIN .AND. .NOT.LQUERY ) THEN | |||||
| INFO = -16 | |||||
| END IF | |||||
| * | |||||
| IF( INFO.EQ.0 ) THEN | |||||
| NB1 = ILAENV( 1, 'SGEQRF', ' ', N, N, -1, -1 ) | |||||
| NB2 = ILAENV( 1, 'SORMQR', ' ', N, N, N, -1 ) | |||||
| NB3 = ILAENV( 1, 'SORGQR', ' ', N, N, N, -1 ) | |||||
| NB = MAX( NB1, NB2, NB3 ) | |||||
| LOPT = 2*N + MAX( 6*N, N*(NB+1) ) | |||||
| WORK( 1 ) = LOPT | |||||
| END IF | |||||
| * | |||||
| IF( INFO.NE.0 ) THEN | |||||
| CALL XERBLA( 'SGEGV ', -INFO ) | |||||
| RETURN | |||||
| ELSE IF( LQUERY ) THEN | |||||
| RETURN | |||||
| END IF | |||||
| * | |||||
| * Quick return if possible | |||||
| * | |||||
| IF( N.EQ.0 ) | |||||
| $ RETURN | |||||
| * | |||||
| * Get machine constants | |||||
| * | |||||
| EPS = SLAMCH( 'E' )*SLAMCH( 'B' ) | |||||
| SAFMIN = SLAMCH( 'S' ) | |||||
| SAFMIN = SAFMIN + SAFMIN | |||||
| SAFMAX = ONE / SAFMIN | |||||
| ONEPLS = ONE + ( 4*EPS ) | |||||
| * | |||||
| * Scale A | |||||
| * | |||||
| ANRM = SLANGE( 'M', N, N, A, LDA, WORK ) | |||||
| ANRM1 = ANRM | |||||
| ANRM2 = ONE | |||||
| IF( ANRM.LT.ONE ) THEN | |||||
| IF( SAFMAX*ANRM.LT.ONE ) THEN | |||||
| ANRM1 = SAFMIN | |||||
| ANRM2 = SAFMAX*ANRM | |||||
| END IF | |||||
| END IF | |||||
| * | |||||
| IF( ANRM.GT.ZERO ) THEN | |||||
| CALL SLASCL( 'G', -1, -1, ANRM, ONE, N, N, A, LDA, IINFO ) | |||||
| IF( IINFO.NE.0 ) THEN | |||||
| INFO = N + 10 | |||||
| RETURN | |||||
| END IF | |||||
| END IF | |||||
| * | |||||
| * Scale B | |||||
| * | |||||
| BNRM = SLANGE( 'M', N, N, B, LDB, WORK ) | |||||
| BNRM1 = BNRM | |||||
| BNRM2 = ONE | |||||
| IF( BNRM.LT.ONE ) THEN | |||||
| IF( SAFMAX*BNRM.LT.ONE ) THEN | |||||
| BNRM1 = SAFMIN | |||||
| BNRM2 = SAFMAX*BNRM | |||||
| END IF | |||||
| END IF | |||||
| * | |||||
| IF( BNRM.GT.ZERO ) THEN | |||||
| CALL SLASCL( 'G', -1, -1, BNRM, ONE, N, N, B, LDB, IINFO ) | |||||
| IF( IINFO.NE.0 ) THEN | |||||
| INFO = N + 10 | |||||
| RETURN | |||||
| END IF | |||||
| END IF | |||||
| * | |||||
| * Permute the matrix to make it more nearly triangular | |||||
| * Workspace layout: (8*N words -- "work" requires 6*N words) | |||||
| * left_permutation, right_permutation, work... | |||||
| * | |||||
| ILEFT = 1 | |||||
| IRIGHT = N + 1 | |||||
| IWORK = IRIGHT + N | |||||
| CALL SGGBAL( 'P', N, A, LDA, B, LDB, ILO, IHI, WORK( ILEFT ), | |||||
| $ WORK( IRIGHT ), WORK( IWORK ), IINFO ) | |||||
| IF( IINFO.NE.0 ) THEN | |||||
| INFO = N + 1 | |||||
| GO TO 120 | |||||
| END IF | |||||
| * | |||||
| * Reduce B to triangular form, and initialize VL and/or VR | |||||
| * Workspace layout: ("work..." must have at least N words) | |||||
| * left_permutation, right_permutation, tau, work... | |||||
| * | |||||
| IROWS = IHI + 1 - ILO | |||||
| IF( ILV ) THEN | |||||
| ICOLS = N + 1 - ILO | |||||
| ELSE | |||||
| ICOLS = IROWS | |||||
| END IF | |||||
| ITAU = IWORK | |||||
| IWORK = ITAU + IROWS | |||||
| CALL SGEQRF( IROWS, ICOLS, B( ILO, ILO ), LDB, WORK( ITAU ), | |||||
| $ WORK( IWORK ), LWORK+1-IWORK, IINFO ) | |||||
| IF( IINFO.GE.0 ) | |||||
| $ LWKOPT = MAX( LWKOPT, INT( WORK( IWORK ) )+IWORK-1 ) | |||||
| IF( IINFO.NE.0 ) THEN | |||||
| INFO = N + 2 | |||||
| GO TO 120 | |||||
| END IF | |||||
| * | |||||
| CALL SORMQR( 'L', 'T', IROWS, ICOLS, IROWS, B( ILO, ILO ), LDB, | |||||
| $ WORK( ITAU ), A( ILO, ILO ), LDA, WORK( IWORK ), | |||||
| $ LWORK+1-IWORK, IINFO ) | |||||
| IF( IINFO.GE.0 ) | |||||
| $ LWKOPT = MAX( LWKOPT, INT( WORK( IWORK ) )+IWORK-1 ) | |||||
| IF( IINFO.NE.0 ) THEN | |||||
| INFO = N + 3 | |||||
| GO TO 120 | |||||
| END IF | |||||
| * | |||||
| IF( ILVL ) THEN | |||||
| CALL SLASET( 'Full', N, N, ZERO, ONE, VL, LDVL ) | |||||
| CALL SLACPY( 'L', IROWS-1, IROWS-1, B( ILO+1, ILO ), LDB, | |||||
| $ VL( ILO+1, ILO ), LDVL ) | |||||
| CALL SORGQR( IROWS, IROWS, IROWS, VL( ILO, ILO ), LDVL, | |||||
| $ WORK( ITAU ), WORK( IWORK ), LWORK+1-IWORK, | |||||
| $ IINFO ) | |||||
| IF( IINFO.GE.0 ) | |||||
| $ LWKOPT = MAX( LWKOPT, INT( WORK( IWORK ) )+IWORK-1 ) | |||||
| IF( IINFO.NE.0 ) THEN | |||||
| INFO = N + 4 | |||||
| GO TO 120 | |||||
| END IF | |||||
| END IF | |||||
| * | |||||
| IF( ILVR ) | |||||
| $ CALL SLASET( 'Full', N, N, ZERO, ONE, VR, LDVR ) | |||||
| * | |||||
| * Reduce to generalized Hessenberg form | |||||
| * | |||||
| IF( ILV ) THEN | |||||
| * | |||||
| * Eigenvectors requested -- work on whole matrix. | |||||
| * | |||||
| CALL SGGHRD( JOBVL, JOBVR, N, ILO, IHI, A, LDA, B, LDB, VL, | |||||
| $ LDVL, VR, LDVR, IINFO ) | |||||
| ELSE | |||||
| CALL SGGHRD( 'N', 'N', IROWS, 1, IROWS, A( ILO, ILO ), LDA, | |||||
| $ B( ILO, ILO ), LDB, VL, LDVL, VR, LDVR, IINFO ) | |||||
| END IF | |||||
| IF( IINFO.NE.0 ) THEN | |||||
| INFO = N + 5 | |||||
| GO TO 120 | |||||
| END IF | |||||
| * | |||||
| * Perform QZ algorithm | |||||
| * Workspace layout: ("work..." must have at least 1 word) | |||||
| * left_permutation, right_permutation, work... | |||||
| * | |||||
| IWORK = ITAU | |||||
| IF( ILV ) THEN | |||||
| CHTEMP = 'S' | |||||
| ELSE | |||||
| CHTEMP = 'E' | |||||
| END IF | |||||
| CALL SHGEQZ( CHTEMP, JOBVL, JOBVR, N, ILO, IHI, A, LDA, B, LDB, | |||||
| $ ALPHAR, ALPHAI, BETA, VL, LDVL, VR, LDVR, | |||||
| $ WORK( IWORK ), LWORK+1-IWORK, IINFO ) | |||||
| IF( IINFO.GE.0 ) | |||||
| $ LWKOPT = MAX( LWKOPT, INT( WORK( IWORK ) )+IWORK-1 ) | |||||
| IF( IINFO.NE.0 ) THEN | |||||
| IF( IINFO.GT.0 .AND. IINFO.LE.N ) THEN | |||||
| INFO = IINFO | |||||
| ELSE IF( IINFO.GT.N .AND. IINFO.LE.2*N ) THEN | |||||
| INFO = IINFO - N | |||||
| ELSE | |||||
| INFO = N + 6 | |||||
| END IF | |||||
| GO TO 120 | |||||
| END IF | |||||
| * | |||||
| IF( ILV ) THEN | |||||
| * | |||||
| * Compute Eigenvectors (STGEVC requires 6*N words of workspace) | |||||
| * | |||||
| IF( ILVL ) THEN | |||||
| IF( ILVR ) THEN | |||||
| CHTEMP = 'B' | |||||
| ELSE | |||||
| CHTEMP = 'L' | |||||
| END IF | |||||
| ELSE | |||||
| CHTEMP = 'R' | |||||
| END IF | |||||
| * | |||||
| CALL STGEVC( CHTEMP, 'B', LDUMMA, N, A, LDA, B, LDB, VL, LDVL, | |||||
| $ VR, LDVR, N, IN, WORK( IWORK ), IINFO ) | |||||
| IF( IINFO.NE.0 ) THEN | |||||
| INFO = N + 7 | |||||
| GO TO 120 | |||||
| END IF | |||||
| * | |||||
| * Undo balancing on VL and VR, rescale | |||||
| * | |||||
| IF( ILVL ) THEN | |||||
| CALL SGGBAK( 'P', 'L', N, ILO, IHI, WORK( ILEFT ), | |||||
| $ WORK( IRIGHT ), N, VL, LDVL, IINFO ) | |||||
| IF( IINFO.NE.0 ) THEN | |||||
| INFO = N + 8 | |||||
| GO TO 120 | |||||
| END IF | |||||
| DO 50 JC = 1, N | |||||
| IF( ALPHAI( JC ).LT.ZERO ) | |||||
| $ GO TO 50 | |||||
| TEMP = ZERO | |||||
| IF( ALPHAI( JC ).EQ.ZERO ) THEN | |||||
| DO 10 JR = 1, N | |||||
| TEMP = MAX( TEMP, ABS( VL( JR, JC ) ) ) | |||||
| 10 CONTINUE | |||||
| ELSE | |||||
| DO 20 JR = 1, N | |||||
| TEMP = MAX( TEMP, ABS( VL( JR, JC ) )+ | |||||
| $ ABS( VL( JR, JC+1 ) ) ) | |||||
| 20 CONTINUE | |||||
| END IF | |||||
| IF( TEMP.LT.SAFMIN ) | |||||
| $ GO TO 50 | |||||
| TEMP = ONE / TEMP | |||||
| IF( ALPHAI( JC ).EQ.ZERO ) THEN | |||||
| DO 30 JR = 1, N | |||||
| VL( JR, JC ) = VL( JR, JC )*TEMP | |||||
| 30 CONTINUE | |||||
| ELSE | |||||
| DO 40 JR = 1, N | |||||
| VL( JR, JC ) = VL( JR, JC )*TEMP | |||||
| VL( JR, JC+1 ) = VL( JR, JC+1 )*TEMP | |||||
| 40 CONTINUE | |||||
| END IF | |||||
| 50 CONTINUE | |||||
| END IF | |||||
| IF( ILVR ) THEN | |||||
| CALL SGGBAK( 'P', 'R', N, ILO, IHI, WORK( ILEFT ), | |||||
| $ WORK( IRIGHT ), N, VR, LDVR, IINFO ) | |||||
| IF( IINFO.NE.0 ) THEN | |||||
| INFO = N + 9 | |||||
| GO TO 120 | |||||
| END IF | |||||
| DO 100 JC = 1, N | |||||
| IF( ALPHAI( JC ).LT.ZERO ) | |||||
| $ GO TO 100 | |||||
| TEMP = ZERO | |||||
| IF( ALPHAI( JC ).EQ.ZERO ) THEN | |||||
| DO 60 JR = 1, N | |||||
| TEMP = MAX( TEMP, ABS( VR( JR, JC ) ) ) | |||||
| 60 CONTINUE | |||||
| ELSE | |||||
| DO 70 JR = 1, N | |||||
| TEMP = MAX( TEMP, ABS( VR( JR, JC ) )+ | |||||
| $ ABS( VR( JR, JC+1 ) ) ) | |||||
| 70 CONTINUE | |||||
| END IF | |||||
| IF( TEMP.LT.SAFMIN ) | |||||
| $ GO TO 100 | |||||
| TEMP = ONE / TEMP | |||||
| IF( ALPHAI( JC ).EQ.ZERO ) THEN | |||||
| DO 80 JR = 1, N | |||||
| VR( JR, JC ) = VR( JR, JC )*TEMP | |||||
| 80 CONTINUE | |||||
| ELSE | |||||
| DO 90 JR = 1, N | |||||
| VR( JR, JC ) = VR( JR, JC )*TEMP | |||||
| VR( JR, JC+1 ) = VR( JR, JC+1 )*TEMP | |||||
| 90 CONTINUE | |||||
| END IF | |||||
| 100 CONTINUE | |||||
| END IF | |||||
| * | |||||
| * End of eigenvector calculation | |||||
| * | |||||
| END IF | |||||
| * | |||||
| * Undo scaling in alpha, beta | |||||
| * | |||||
| * Note: this does not give the alpha and beta for the unscaled | |||||
| * problem. | |||||
| * | |||||
| * Un-scaling is limited to avoid underflow in alpha and beta | |||||
| * if they are significant. | |||||
| * | |||||
| DO 110 JC = 1, N | |||||
| ABSAR = ABS( ALPHAR( JC ) ) | |||||
| ABSAI = ABS( ALPHAI( JC ) ) | |||||
| ABSB = ABS( BETA( JC ) ) | |||||
| SALFAR = ANRM*ALPHAR( JC ) | |||||
| SALFAI = ANRM*ALPHAI( JC ) | |||||
| SBETA = BNRM*BETA( JC ) | |||||
| ILIMIT = .FALSE. | |||||
| SCALE = ONE | |||||
| * | |||||
| * Check for significant underflow in ALPHAI | |||||
| * | |||||
| IF( ABS( SALFAI ).LT.SAFMIN .AND. ABSAI.GE. | |||||
| $ MAX( SAFMIN, EPS*ABSAR, EPS*ABSB ) ) THEN | |||||
| ILIMIT = .TRUE. | |||||
| SCALE = ( ONEPLS*SAFMIN / ANRM1 ) / | |||||
| $ MAX( ONEPLS*SAFMIN, ANRM2*ABSAI ) | |||||
| * | |||||
| ELSE IF( SALFAI.EQ.ZERO ) THEN | |||||
| * | |||||
| * If insignificant underflow in ALPHAI, then make the | |||||
| * conjugate eigenvalue real. | |||||
| * | |||||
| IF( ALPHAI( JC ).LT.ZERO .AND. JC.GT.1 ) THEN | |||||
| ALPHAI( JC-1 ) = ZERO | |||||
| ELSE IF( ALPHAI( JC ).GT.ZERO .AND. JC.LT.N ) THEN | |||||
| ALPHAI( JC+1 ) = ZERO | |||||
| END IF | |||||
| END IF | |||||
| * | |||||
| * Check for significant underflow in ALPHAR | |||||
| * | |||||
| IF( ABS( SALFAR ).LT.SAFMIN .AND. ABSAR.GE. | |||||
| $ MAX( SAFMIN, EPS*ABSAI, EPS*ABSB ) ) THEN | |||||
| ILIMIT = .TRUE. | |||||
| SCALE = MAX( SCALE, ( ONEPLS*SAFMIN / ANRM1 ) / | |||||
| $ MAX( ONEPLS*SAFMIN, ANRM2*ABSAR ) ) | |||||
| END IF | |||||
| * | |||||
| * Check for significant underflow in BETA | |||||
| * | |||||
| IF( ABS( SBETA ).LT.SAFMIN .AND. ABSB.GE. | |||||
| $ MAX( SAFMIN, EPS*ABSAR, EPS*ABSAI ) ) THEN | |||||
| ILIMIT = .TRUE. | |||||
| SCALE = MAX( SCALE, ( ONEPLS*SAFMIN / BNRM1 ) / | |||||
| $ MAX( ONEPLS*SAFMIN, BNRM2*ABSB ) ) | |||||
| END IF | |||||
| * | |||||
| * Check for possible overflow when limiting scaling | |||||
| * | |||||
| IF( ILIMIT ) THEN | |||||
| TEMP = ( SCALE*SAFMIN )*MAX( ABS( SALFAR ), ABS( SALFAI ), | |||||
| $ ABS( SBETA ) ) | |||||
| IF( TEMP.GT.ONE ) | |||||
| $ SCALE = SCALE / TEMP | |||||
| IF( SCALE.LT.ONE ) | |||||
| $ ILIMIT = .FALSE. | |||||
| END IF | |||||
| * | |||||
| * Recompute un-scaled ALPHAR, ALPHAI, BETA if necessary. | |||||
| * | |||||
| IF( ILIMIT ) THEN | |||||
| SALFAR = ( SCALE*ALPHAR( JC ) )*ANRM | |||||
| SALFAI = ( SCALE*ALPHAI( JC ) )*ANRM | |||||
| SBETA = ( SCALE*BETA( JC ) )*BNRM | |||||
| END IF | |||||
| ALPHAR( JC ) = SALFAR | |||||
| ALPHAI( JC ) = SALFAI | |||||
| BETA( JC ) = SBETA | |||||
| 110 CONTINUE | |||||
| * | |||||
| 120 CONTINUE | |||||
| WORK( 1 ) = LWKOPT | |||||
| * | |||||
| RETURN | |||||
| * | |||||
| * End of SGEGV | |||||
| * | |||||
| END | |||||
| @@ -0,0 +1,528 @@ | |||||
| *> \brief <b> ZGEGS computes the eigenvalues, Schur form, and, optionally, the left and or/right Schur vectors of a complex matrix pair (A,B)</b> | |||||
| * | |||||
| * =========== DOCUMENTATION =========== | |||||
| * | |||||
| * Online html documentation available at | |||||
| * http://www.netlib.org/lapack/explore-html/ | |||||
| * | |||||
| *> \htmlonly | |||||
| *> Download ZGEGS + dependencies | |||||
| *> <a href="http://www.netlib.org/cgi-bin/netlibfiles.tgz?format=tgz&filename=/lapack/lapack_routine/zgegs.f"> | |||||
| *> [TGZ]</a> | |||||
| *> <a href="http://www.netlib.org/cgi-bin/netlibfiles.zip?format=zip&filename=/lapack/lapack_routine/zgegs.f"> | |||||
| *> [ZIP]</a> | |||||
| *> <a href="http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/zgegs.f"> | |||||
| *> [TXT]</a> | |||||
| *> \endhtmlonly | |||||
| * | |||||
| * Definition: | |||||
| * =========== | |||||
| * | |||||
| * SUBROUTINE ZGEGS( JOBVSL, JOBVSR, N, A, LDA, B, LDB, ALPHA, BETA, | |||||
| * VSL, LDVSL, VSR, LDVSR, WORK, LWORK, RWORK, | |||||
| * INFO ) | |||||
| * | |||||
| * .. Scalar Arguments .. | |||||
| * CHARACTER JOBVSL, JOBVSR | |||||
| * INTEGER INFO, LDA, LDB, LDVSL, LDVSR, LWORK, N | |||||
| * .. | |||||
| * .. Array Arguments .. | |||||
| * DOUBLE PRECISION RWORK( * ) | |||||
| * COMPLEX*16 A( LDA, * ), ALPHA( * ), B( LDB, * ), | |||||
| * $ BETA( * ), VSL( LDVSL, * ), VSR( LDVSR, * ), | |||||
| * $ WORK( * ) | |||||
| * .. | |||||
| * | |||||
| * | |||||
| *> \par Purpose: | |||||
| * ============= | |||||
| *> | |||||
| *> \verbatim | |||||
| *> | |||||
| *> This routine is deprecated and has been replaced by routine ZGGES. | |||||
| *> | |||||
| *> ZGEGS computes the eigenvalues, Schur form, and, optionally, the | |||||
| *> left and or/right Schur vectors of a complex matrix pair (A,B). | |||||
| *> Given two square matrices A and B, the generalized Schur | |||||
| *> factorization has the form | |||||
| *> | |||||
| *> A = Q*S*Z**H, B = Q*T*Z**H | |||||
| *> | |||||
| *> where Q and Z are unitary matrices and S and T are upper triangular. | |||||
| *> The columns of Q are the left Schur vectors | |||||
| *> and the columns of Z are the right Schur vectors. | |||||
| *> | |||||
| *> If only the eigenvalues of (A,B) are needed, the driver routine | |||||
| *> ZGEGV should be used instead. See ZGEGV for a description of the | |||||
| *> eigenvalues of the generalized nonsymmetric eigenvalue problem | |||||
| *> (GNEP). | |||||
| *> \endverbatim | |||||
| * | |||||
| * Arguments: | |||||
| * ========== | |||||
| * | |||||
| *> \param[in] JOBVSL | |||||
| *> \verbatim | |||||
| *> JOBVSL is CHARACTER*1 | |||||
| *> = 'N': do not compute the left Schur vectors; | |||||
| *> = 'V': compute the left Schur vectors (returned in VSL). | |||||
| *> \endverbatim | |||||
| *> | |||||
| *> \param[in] JOBVSR | |||||
| *> \verbatim | |||||
| *> JOBVSR is CHARACTER*1 | |||||
| *> = 'N': do not compute the right Schur vectors; | |||||
| *> = 'V': compute the right Schur vectors (returned in VSR). | |||||
| *> \endverbatim | |||||
| *> | |||||
| *> \param[in] N | |||||
| *> \verbatim | |||||
| *> N is INTEGER | |||||
| *> The order of the matrices A, B, VSL, and VSR. N >= 0. | |||||
| *> \endverbatim | |||||
| *> | |||||
| *> \param[in,out] A | |||||
| *> \verbatim | |||||
| *> A is COMPLEX*16 array, dimension (LDA, N) | |||||
| *> On entry, the matrix A. | |||||
| *> On exit, the upper triangular matrix S from the generalized | |||||
| *> Schur factorization. | |||||
| *> \endverbatim | |||||
| *> | |||||
| *> \param[in] LDA | |||||
| *> \verbatim | |||||
| *> LDA is INTEGER | |||||
| *> The leading dimension of A. LDA >= max(1,N). | |||||
| *> \endverbatim | |||||
| *> | |||||
| *> \param[in,out] B | |||||
| *> \verbatim | |||||
| *> B is COMPLEX*16 array, dimension (LDB, N) | |||||
| *> On entry, the matrix B. | |||||
| *> On exit, the upper triangular matrix T from the generalized | |||||
| *> Schur factorization. | |||||
| *> \endverbatim | |||||
| *> | |||||
| *> \param[in] LDB | |||||
| *> \verbatim | |||||
| *> LDB is INTEGER | |||||
| *> The leading dimension of B. LDB >= max(1,N). | |||||
| *> \endverbatim | |||||
| *> | |||||
| *> \param[out] ALPHA | |||||
| *> \verbatim | |||||
| *> ALPHA is COMPLEX*16 array, dimension (N) | |||||
| *> The complex scalars alpha that define the eigenvalues of | |||||
| *> GNEP. ALPHA(j) = S(j,j), the diagonal element of the Schur | |||||
| *> form of A. | |||||
| *> \endverbatim | |||||
| *> | |||||
| *> \param[out] BETA | |||||
| *> \verbatim | |||||
| *> BETA is COMPLEX*16 array, dimension (N) | |||||
| *> The non-negative real scalars beta that define the | |||||
| *> eigenvalues of GNEP. BETA(j) = T(j,j), the diagonal element | |||||
| *> of the triangular factor T. | |||||
| *> | |||||
| *> Together, the quantities alpha = ALPHA(j) and beta = BETA(j) | |||||
| *> represent the j-th eigenvalue of the matrix pair (A,B), in | |||||
| *> one of the forms lambda = alpha/beta or mu = beta/alpha. | |||||
| *> Since either lambda or mu may overflow, they should not, | |||||
| *> in general, be computed. | |||||
| *> \endverbatim | |||||
| *> | |||||
| *> \param[out] VSL | |||||
| *> \verbatim | |||||
| *> VSL is COMPLEX*16 array, dimension (LDVSL,N) | |||||
| *> If JOBVSL = 'V', the matrix of left Schur vectors Q. | |||||
| *> Not referenced if JOBVSL = 'N'. | |||||
| *> \endverbatim | |||||
| *> | |||||
| *> \param[in] LDVSL | |||||
| *> \verbatim | |||||
| *> LDVSL is INTEGER | |||||
| *> The leading dimension of the matrix VSL. LDVSL >= 1, and | |||||
| *> if JOBVSL = 'V', LDVSL >= N. | |||||
| *> \endverbatim | |||||
| *> | |||||
| *> \param[out] VSR | |||||
| *> \verbatim | |||||
| *> VSR is COMPLEX*16 array, dimension (LDVSR,N) | |||||
| *> If JOBVSR = 'V', the matrix of right Schur vectors Z. | |||||
| *> Not referenced if JOBVSR = 'N'. | |||||
| *> \endverbatim | |||||
| *> | |||||
| *> \param[in] LDVSR | |||||
| *> \verbatim | |||||
| *> LDVSR is INTEGER | |||||
| *> The leading dimension of the matrix VSR. LDVSR >= 1, and | |||||
| *> if JOBVSR = 'V', LDVSR >= N. | |||||
| *> \endverbatim | |||||
| *> | |||||
| *> \param[out] WORK | |||||
| *> \verbatim | |||||
| *> WORK is COMPLEX*16 array, dimension (MAX(1,LWORK)) | |||||
| *> On exit, if INFO = 0, WORK(1) returns the optimal LWORK. | |||||
| *> \endverbatim | |||||
| *> | |||||
| *> \param[in] LWORK | |||||
| *> \verbatim | |||||
| *> LWORK is INTEGER | |||||
| *> The dimension of the array WORK. LWORK >= max(1,2*N). | |||||
| *> For good performance, LWORK must generally be larger. | |||||
| *> To compute the optimal value of LWORK, call ILAENV to get | |||||
| *> blocksizes (for ZGEQRF, ZUNMQR, and CUNGQR.) Then compute: | |||||
| *> NB -- MAX of the blocksizes for ZGEQRF, ZUNMQR, and CUNGQR; | |||||
| *> the optimal LWORK is N*(NB+1). | |||||
| *> | |||||
| *> If LWORK = -1, then a workspace query is assumed; the routine | |||||
| *> only calculates the optimal size of the WORK array, returns | |||||
| *> this value as the first entry of the WORK array, and no error | |||||
| *> message related to LWORK is issued by XERBLA. | |||||
| *> \endverbatim | |||||
| *> | |||||
| *> \param[out] RWORK | |||||
| *> \verbatim | |||||
| *> RWORK is DOUBLE PRECISION array, dimension (3*N) | |||||
| *> \endverbatim | |||||
| *> | |||||
| *> \param[out] INFO | |||||
| *> \verbatim | |||||
| *> INFO is INTEGER | |||||
| *> = 0: successful exit | |||||
| *> < 0: if INFO = -i, the i-th argument had an illegal value. | |||||
| *> =1,...,N: | |||||
| *> The QZ iteration failed. (A,B) are not in Schur | |||||
| *> form, but ALPHA(j) and BETA(j) should be correct for | |||||
| *> j=INFO+1,...,N. | |||||
| *> > N: errors that usually indicate LAPACK problems: | |||||
| *> =N+1: error return from ZGGBAL | |||||
| *> =N+2: error return from ZGEQRF | |||||
| *> =N+3: error return from ZUNMQR | |||||
| *> =N+4: error return from ZUNGQR | |||||
| *> =N+5: error return from ZGGHRD | |||||
| *> =N+6: error return from ZHGEQZ (other than failed | |||||
| *> iteration) | |||||
| *> =N+7: error return from ZGGBAK (computing VSL) | |||||
| *> =N+8: error return from ZGGBAK (computing VSR) | |||||
| *> =N+9: error return from ZLASCL (various places) | |||||
| *> \endverbatim | |||||
| * | |||||
| * Authors: | |||||
| * ======== | |||||
| * | |||||
| *> \author Univ. of Tennessee | |||||
| *> \author Univ. of California Berkeley | |||||
| *> \author Univ. of Colorado Denver | |||||
| *> \author NAG Ltd. | |||||
| * | |||||
| *> \ingroup complex16GEeigen | |||||
| * | |||||
| * ===================================================================== | |||||
| SUBROUTINE ZGEGS( JOBVSL, JOBVSR, N, A, LDA, B, LDB, ALPHA, BETA, | |||||
| $ VSL, LDVSL, VSR, LDVSR, WORK, LWORK, RWORK, | |||||
| $ INFO ) | |||||
| * | |||||
| * -- LAPACK driver routine -- | |||||
| * -- LAPACK is a software package provided by Univ. of Tennessee, -- | |||||
| * -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..-- | |||||
| * | |||||
| * .. Scalar Arguments .. | |||||
| CHARACTER JOBVSL, JOBVSR | |||||
| INTEGER INFO, LDA, LDB, LDVSL, LDVSR, LWORK, N | |||||
| * .. | |||||
| * .. Array Arguments .. | |||||
| DOUBLE PRECISION RWORK( * ) | |||||
| COMPLEX*16 A( LDA, * ), ALPHA( * ), B( LDB, * ), | |||||
| $ BETA( * ), VSL( LDVSL, * ), VSR( LDVSR, * ), | |||||
| $ WORK( * ) | |||||
| * .. | |||||
| * | |||||
| * ===================================================================== | |||||
| * | |||||
| * .. Parameters .. | |||||
| DOUBLE PRECISION ZERO, ONE | |||||
| PARAMETER ( ZERO = 0.0D0, ONE = 1.0D0 ) | |||||
| COMPLEX*16 CZERO, CONE | |||||
| PARAMETER ( CZERO = ( 0.0D0, 0.0D0 ), | |||||
| $ CONE = ( 1.0D0, 0.0D0 ) ) | |||||
| * .. | |||||
| * .. Local Scalars .. | |||||
| LOGICAL ILASCL, ILBSCL, ILVSL, ILVSR, LQUERY | |||||
| INTEGER ICOLS, IHI, IINFO, IJOBVL, IJOBVR, ILEFT, ILO, | |||||
| $ IRIGHT, IROWS, IRWORK, ITAU, IWORK, LOPT, | |||||
| $ LWKMIN, LWKOPT, NB, NB1, NB2, NB3 | |||||
| DOUBLE PRECISION ANRM, ANRMTO, BIGNUM, BNRM, BNRMTO, EPS, | |||||
| $ SAFMIN, SMLNUM | |||||
| * .. | |||||
| * .. External Subroutines .. | |||||
| EXTERNAL XERBLA, ZGEQRF, ZGGBAK, ZGGBAL, ZGGHRD, ZHGEQZ, | |||||
| $ ZLACPY, ZLASCL, ZLASET, ZUNGQR, ZUNMQR | |||||
| * .. | |||||
| * .. External Functions .. | |||||
| LOGICAL LSAME | |||||
| INTEGER ILAENV | |||||
| DOUBLE PRECISION DLAMCH, ZLANGE | |||||
| EXTERNAL LSAME, ILAENV, DLAMCH, ZLANGE | |||||
| * .. | |||||
| * .. Intrinsic Functions .. | |||||
| INTRINSIC INT, MAX | |||||
| * .. | |||||
| * .. Executable Statements .. | |||||
| * | |||||
| * Decode the input arguments | |||||
| * | |||||
| IF( LSAME( JOBVSL, 'N' ) ) THEN | |||||
| IJOBVL = 1 | |||||
| ILVSL = .FALSE. | |||||
| ELSE IF( LSAME( JOBVSL, 'V' ) ) THEN | |||||
| IJOBVL = 2 | |||||
| ILVSL = .TRUE. | |||||
| ELSE | |||||
| IJOBVL = -1 | |||||
| ILVSL = .FALSE. | |||||
| END IF | |||||
| * | |||||
| IF( LSAME( JOBVSR, 'N' ) ) THEN | |||||
| IJOBVR = 1 | |||||
| ILVSR = .FALSE. | |||||
| ELSE IF( LSAME( JOBVSR, 'V' ) ) THEN | |||||
| IJOBVR = 2 | |||||
| ILVSR = .TRUE. | |||||
| ELSE | |||||
| IJOBVR = -1 | |||||
| ILVSR = .FALSE. | |||||
| END IF | |||||
| * | |||||
| * Test the input arguments | |||||
| * | |||||
| LWKMIN = MAX( 2*N, 1 ) | |||||
| LWKOPT = LWKMIN | |||||
| WORK( 1 ) = LWKOPT | |||||
| LQUERY = ( LWORK.EQ.-1 ) | |||||
| INFO = 0 | |||||
| IF( IJOBVL.LE.0 ) THEN | |||||
| INFO = -1 | |||||
| ELSE IF( IJOBVR.LE.0 ) THEN | |||||
| INFO = -2 | |||||
| ELSE IF( N.LT.0 ) THEN | |||||
| INFO = -3 | |||||
| ELSE IF( LDA.LT.MAX( 1, N ) ) THEN | |||||
| INFO = -5 | |||||
| ELSE IF( LDB.LT.MAX( 1, N ) ) THEN | |||||
| INFO = -7 | |||||
| ELSE IF( LDVSL.LT.1 .OR. ( ILVSL .AND. LDVSL.LT.N ) ) THEN | |||||
| INFO = -11 | |||||
| ELSE IF( LDVSR.LT.1 .OR. ( ILVSR .AND. LDVSR.LT.N ) ) THEN | |||||
| INFO = -13 | |||||
| ELSE IF( LWORK.LT.LWKMIN .AND. .NOT.LQUERY ) THEN | |||||
| INFO = -15 | |||||
| END IF | |||||
| * | |||||
| IF( INFO.EQ.0 ) THEN | |||||
| NB1 = ILAENV( 1, 'ZGEQRF', ' ', N, N, -1, -1 ) | |||||
| NB2 = ILAENV( 1, 'ZUNMQR', ' ', N, N, N, -1 ) | |||||
| NB3 = ILAENV( 1, 'ZUNGQR', ' ', N, N, N, -1 ) | |||||
| NB = MAX( NB1, NB2, NB3 ) | |||||
| LOPT = N*( NB+1 ) | |||||
| WORK( 1 ) = LOPT | |||||
| END IF | |||||
| * | |||||
| IF( INFO.NE.0 ) THEN | |||||
| CALL XERBLA( 'ZGEGS ', -INFO ) | |||||
| RETURN | |||||
| ELSE IF( LQUERY ) THEN | |||||
| RETURN | |||||
| END IF | |||||
| * | |||||
| * Quick return if possible | |||||
| * | |||||
| IF( N.EQ.0 ) | |||||
| $ RETURN | |||||
| * | |||||
| * Get machine constants | |||||
| * | |||||
| EPS = DLAMCH( 'E' )*DLAMCH( 'B' ) | |||||
| SAFMIN = DLAMCH( 'S' ) | |||||
| SMLNUM = N*SAFMIN / EPS | |||||
| BIGNUM = ONE / SMLNUM | |||||
| * | |||||
| * Scale A if max element outside range [SMLNUM,BIGNUM] | |||||
| * | |||||
| ANRM = ZLANGE( 'M', N, N, A, LDA, RWORK ) | |||||
| ILASCL = .FALSE. | |||||
| IF( ANRM.GT.ZERO .AND. ANRM.LT.SMLNUM ) THEN | |||||
| ANRMTO = SMLNUM | |||||
| ILASCL = .TRUE. | |||||
| ELSE IF( ANRM.GT.BIGNUM ) THEN | |||||
| ANRMTO = BIGNUM | |||||
| ILASCL = .TRUE. | |||||
| END IF | |||||
| * | |||||
| IF( ILASCL ) THEN | |||||
| CALL ZLASCL( 'G', -1, -1, ANRM, ANRMTO, N, N, A, LDA, IINFO ) | |||||
| IF( IINFO.NE.0 ) THEN | |||||
| INFO = N + 9 | |||||
| RETURN | |||||
| END IF | |||||
| END IF | |||||
| * | |||||
| * Scale B if max element outside range [SMLNUM,BIGNUM] | |||||
| * | |||||
| BNRM = ZLANGE( 'M', N, N, B, LDB, RWORK ) | |||||
| ILBSCL = .FALSE. | |||||
| IF( BNRM.GT.ZERO .AND. BNRM.LT.SMLNUM ) THEN | |||||
| BNRMTO = SMLNUM | |||||
| ILBSCL = .TRUE. | |||||
| ELSE IF( BNRM.GT.BIGNUM ) THEN | |||||
| BNRMTO = BIGNUM | |||||
| ILBSCL = .TRUE. | |||||
| END IF | |||||
| * | |||||
| IF( ILBSCL ) THEN | |||||
| CALL ZLASCL( 'G', -1, -1, BNRM, BNRMTO, N, N, B, LDB, IINFO ) | |||||
| IF( IINFO.NE.0 ) THEN | |||||
| INFO = N + 9 | |||||
| RETURN | |||||
| END IF | |||||
| END IF | |||||
| * | |||||
| * Permute the matrix to make it more nearly triangular | |||||
| * | |||||
| ILEFT = 1 | |||||
| IRIGHT = N + 1 | |||||
| IRWORK = IRIGHT + N | |||||
| IWORK = 1 | |||||
| CALL ZGGBAL( 'P', N, A, LDA, B, LDB, ILO, IHI, RWORK( ILEFT ), | |||||
| $ RWORK( IRIGHT ), RWORK( IRWORK ), IINFO ) | |||||
| IF( IINFO.NE.0 ) THEN | |||||
| INFO = N + 1 | |||||
| GO TO 10 | |||||
| END IF | |||||
| * | |||||
| * Reduce B to triangular form, and initialize VSL and/or VSR | |||||
| * | |||||
| IROWS = IHI + 1 - ILO | |||||
| ICOLS = N + 1 - ILO | |||||
| ITAU = IWORK | |||||
| IWORK = ITAU + IROWS | |||||
| CALL ZGEQRF( IROWS, ICOLS, B( ILO, ILO ), LDB, WORK( ITAU ), | |||||
| $ WORK( IWORK ), LWORK+1-IWORK, IINFO ) | |||||
| IF( IINFO.GE.0 ) | |||||
| $ LWKOPT = MAX( LWKOPT, INT( WORK( IWORK ) )+IWORK-1 ) | |||||
| IF( IINFO.NE.0 ) THEN | |||||
| INFO = N + 2 | |||||
| GO TO 10 | |||||
| END IF | |||||
| * | |||||
| CALL ZUNMQR( 'L', 'C', IROWS, ICOLS, IROWS, B( ILO, ILO ), LDB, | |||||
| $ WORK( ITAU ), A( ILO, ILO ), LDA, WORK( IWORK ), | |||||
| $ LWORK+1-IWORK, IINFO ) | |||||
| IF( IINFO.GE.0 ) | |||||
| $ LWKOPT = MAX( LWKOPT, INT( WORK( IWORK ) )+IWORK-1 ) | |||||
| IF( IINFO.NE.0 ) THEN | |||||
| INFO = N + 3 | |||||
| GO TO 10 | |||||
| END IF | |||||
| * | |||||
| IF( ILVSL ) THEN | |||||
| CALL ZLASET( 'Full', N, N, CZERO, CONE, VSL, LDVSL ) | |||||
| CALL ZLACPY( 'L', IROWS-1, IROWS-1, B( ILO+1, ILO ), LDB, | |||||
| $ VSL( ILO+1, ILO ), LDVSL ) | |||||
| CALL ZUNGQR( IROWS, IROWS, IROWS, VSL( ILO, ILO ), LDVSL, | |||||
| $ WORK( ITAU ), WORK( IWORK ), LWORK+1-IWORK, | |||||
| $ IINFO ) | |||||
| IF( IINFO.GE.0 ) | |||||
| $ LWKOPT = MAX( LWKOPT, INT( WORK( IWORK ) )+IWORK-1 ) | |||||
| IF( IINFO.NE.0 ) THEN | |||||
| INFO = N + 4 | |||||
| GO TO 10 | |||||
| END IF | |||||
| END IF | |||||
| * | |||||
| IF( ILVSR ) | |||||
| $ CALL ZLASET( 'Full', N, N, CZERO, CONE, VSR, LDVSR ) | |||||
| * | |||||
| * Reduce to generalized Hessenberg form | |||||
| * | |||||
| CALL ZGGHRD( JOBVSL, JOBVSR, N, ILO, IHI, A, LDA, B, LDB, VSL, | |||||
| $ LDVSL, VSR, LDVSR, IINFO ) | |||||
| IF( IINFO.NE.0 ) THEN | |||||
| INFO = N + 5 | |||||
| GO TO 10 | |||||
| END IF | |||||
| * | |||||
| * Perform QZ algorithm, computing Schur vectors if desired | |||||
| * | |||||
| IWORK = ITAU | |||||
| CALL ZHGEQZ( 'S', JOBVSL, JOBVSR, N, ILO, IHI, A, LDA, B, LDB, | |||||
| $ ALPHA, BETA, VSL, LDVSL, VSR, LDVSR, WORK( IWORK ), | |||||
| $ LWORK+1-IWORK, RWORK( IRWORK ), IINFO ) | |||||
| IF( IINFO.GE.0 ) | |||||
| $ LWKOPT = MAX( LWKOPT, INT( WORK( IWORK ) )+IWORK-1 ) | |||||
| IF( IINFO.NE.0 ) THEN | |||||
| IF( IINFO.GT.0 .AND. IINFO.LE.N ) THEN | |||||
| INFO = IINFO | |||||
| ELSE IF( IINFO.GT.N .AND. IINFO.LE.2*N ) THEN | |||||
| INFO = IINFO - N | |||||
| ELSE | |||||
| INFO = N + 6 | |||||
| END IF | |||||
| GO TO 10 | |||||
| END IF | |||||
| * | |||||
| * Apply permutation to VSL and VSR | |||||
| * | |||||
| IF( ILVSL ) THEN | |||||
| CALL ZGGBAK( 'P', 'L', N, ILO, IHI, RWORK( ILEFT ), | |||||
| $ RWORK( IRIGHT ), N, VSL, LDVSL, IINFO ) | |||||
| IF( IINFO.NE.0 ) THEN | |||||
| INFO = N + 7 | |||||
| GO TO 10 | |||||
| END IF | |||||
| END IF | |||||
| IF( ILVSR ) THEN | |||||
| CALL ZGGBAK( 'P', 'R', N, ILO, IHI, RWORK( ILEFT ), | |||||
| $ RWORK( IRIGHT ), N, VSR, LDVSR, IINFO ) | |||||
| IF( IINFO.NE.0 ) THEN | |||||
| INFO = N + 8 | |||||
| GO TO 10 | |||||
| END IF | |||||
| END IF | |||||
| * | |||||
| * Undo scaling | |||||
| * | |||||
| IF( ILASCL ) THEN | |||||
| CALL ZLASCL( 'U', -1, -1, ANRMTO, ANRM, N, N, A, LDA, IINFO ) | |||||
| IF( IINFO.NE.0 ) THEN | |||||
| INFO = N + 9 | |||||
| RETURN | |||||
| END IF | |||||
| CALL ZLASCL( 'G', -1, -1, ANRMTO, ANRM, N, 1, ALPHA, N, IINFO ) | |||||
| IF( IINFO.NE.0 ) THEN | |||||
| INFO = N + 9 | |||||
| RETURN | |||||
| END IF | |||||
| END IF | |||||
| * | |||||
| IF( ILBSCL ) THEN | |||||
| CALL ZLASCL( 'U', -1, -1, BNRMTO, BNRM, N, N, B, LDB, IINFO ) | |||||
| IF( IINFO.NE.0 ) THEN | |||||
| INFO = N + 9 | |||||
| RETURN | |||||
| END IF | |||||
| CALL ZLASCL( 'G', -1, -1, BNRMTO, BNRM, N, 1, BETA, N, IINFO ) | |||||
| IF( IINFO.NE.0 ) THEN | |||||
| INFO = N + 9 | |||||
| RETURN | |||||
| END IF | |||||
| END IF | |||||
| * | |||||
| 10 CONTINUE | |||||
| WORK( 1 ) = LWKOPT | |||||
| * | |||||
| RETURN | |||||
| * | |||||
| * End of ZGEGS | |||||
| * | |||||
| END | |||||
| @@ -0,0 +1,703 @@ | |||||
| *> \brief <b> ZGEGV computes the eigenvalues and, optionally, the left and/or right eigenvectors of a complex matrix pair (A,B).</b> | |||||
| * | |||||
| * =========== DOCUMENTATION =========== | |||||
| * | |||||
| * Online html documentation available at | |||||
| * http://www.netlib.org/lapack/explore-html/ | |||||
| * | |||||
| *> \htmlonly | |||||
| *> Download ZGEGV + dependencies | |||||
| *> <a href="http://www.netlib.org/cgi-bin/netlibfiles.tgz?format=tgz&filename=/lapack/lapack_routine/zgegv.f"> | |||||
| *> [TGZ]</a> | |||||
| *> <a href="http://www.netlib.org/cgi-bin/netlibfiles.zip?format=zip&filename=/lapack/lapack_routine/zgegv.f"> | |||||
| *> [ZIP]</a> | |||||
| *> <a href="http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/zgegv.f"> | |||||
| *> [TXT]</a> | |||||
| *> \endhtmlonly | |||||
| * | |||||
| * Definition: | |||||
| * =========== | |||||
| * | |||||
| * SUBROUTINE ZGEGV( JOBVL, JOBVR, N, A, LDA, B, LDB, ALPHA, BETA, | |||||
| * VL, LDVL, VR, LDVR, WORK, LWORK, RWORK, INFO ) | |||||
| * | |||||
| * .. Scalar Arguments .. | |||||
| * CHARACTER JOBVL, JOBVR | |||||
| * INTEGER INFO, LDA, LDB, LDVL, LDVR, LWORK, N | |||||
| * .. | |||||
| * .. Array Arguments .. | |||||
| * DOUBLE PRECISION RWORK( * ) | |||||
| * COMPLEX*16 A( LDA, * ), ALPHA( * ), B( LDB, * ), | |||||
| * $ BETA( * ), VL( LDVL, * ), VR( LDVR, * ), | |||||
| * $ WORK( * ) | |||||
| * .. | |||||
| * | |||||
| * | |||||
| *> \par Purpose: | |||||
| * ============= | |||||
| *> | |||||
| *> \verbatim | |||||
| *> | |||||
| *> This routine is deprecated and has been replaced by routine ZGGEV. | |||||
| *> | |||||
| *> ZGEGV computes the eigenvalues and, optionally, the left and/or right | |||||
| *> eigenvectors of a complex matrix pair (A,B). | |||||
| *> Given two square matrices A and B, | |||||
| *> the generalized nonsymmetric eigenvalue problem (GNEP) is to find the | |||||
| *> eigenvalues lambda and corresponding (non-zero) eigenvectors x such | |||||
| *> that | |||||
| *> A*x = lambda*B*x. | |||||
| *> | |||||
| *> An alternate form is to find the eigenvalues mu and corresponding | |||||
| *> eigenvectors y such that | |||||
| *> mu*A*y = B*y. | |||||
| *> | |||||
| *> These two forms are equivalent with mu = 1/lambda and x = y if | |||||
| *> neither lambda nor mu is zero. In order to deal with the case that | |||||
| *> lambda or mu is zero or small, two values alpha and beta are returned | |||||
| *> for each eigenvalue, such that lambda = alpha/beta and | |||||
| *> mu = beta/alpha. | |||||
| *> | |||||
| *> The vectors x and y in the above equations are right eigenvectors of | |||||
| *> the matrix pair (A,B). Vectors u and v satisfying | |||||
| *> u**H*A = lambda*u**H*B or mu*v**H*A = v**H*B | |||||
| *> are left eigenvectors of (A,B). | |||||
| *> | |||||
| *> Note: this routine performs "full balancing" on A and B | |||||
| *> \endverbatim | |||||
| * | |||||
| * Arguments: | |||||
| * ========== | |||||
| * | |||||
| *> \param[in] JOBVL | |||||
| *> \verbatim | |||||
| *> JOBVL is CHARACTER*1 | |||||
| *> = 'N': do not compute the left generalized eigenvectors; | |||||
| *> = 'V': compute the left generalized eigenvectors (returned | |||||
| *> in VL). | |||||
| *> \endverbatim | |||||
| *> | |||||
| *> \param[in] JOBVR | |||||
| *> \verbatim | |||||
| *> JOBVR is CHARACTER*1 | |||||
| *> = 'N': do not compute the right generalized eigenvectors; | |||||
| *> = 'V': compute the right generalized eigenvectors (returned | |||||
| *> in VR). | |||||
| *> \endverbatim | |||||
| *> | |||||
| *> \param[in] N | |||||
| *> \verbatim | |||||
| *> N is INTEGER | |||||
| *> The order of the matrices A, B, VL, and VR. N >= 0. | |||||
| *> \endverbatim | |||||
| *> | |||||
| *> \param[in,out] A | |||||
| *> \verbatim | |||||
| *> A is COMPLEX*16 array, dimension (LDA, N) | |||||
| *> On entry, the matrix A. | |||||
| *> If JOBVL = 'V' or JOBVR = 'V', then on exit A | |||||
| *> contains the Schur form of A from the generalized Schur | |||||
| *> factorization of the pair (A,B) after balancing. If no | |||||
| *> eigenvectors were computed, then only the diagonal elements | |||||
| *> of the Schur form will be correct. See ZGGHRD and ZHGEQZ | |||||
| *> for details. | |||||
| *> \endverbatim | |||||
| *> | |||||
| *> \param[in] LDA | |||||
| *> \verbatim | |||||
| *> LDA is INTEGER | |||||
| *> The leading dimension of A. LDA >= max(1,N). | |||||
| *> \endverbatim | |||||
| *> | |||||
| *> \param[in,out] B | |||||
| *> \verbatim | |||||
| *> B is COMPLEX*16 array, dimension (LDB, N) | |||||
| *> On entry, the matrix B. | |||||
| *> If JOBVL = 'V' or JOBVR = 'V', then on exit B contains the | |||||
| *> upper triangular matrix obtained from B in the generalized | |||||
| *> Schur factorization of the pair (A,B) after balancing. | |||||
| *> If no eigenvectors were computed, then only the diagonal | |||||
| *> elements of B will be correct. See ZGGHRD and ZHGEQZ for | |||||
| *> details. | |||||
| *> \endverbatim | |||||
| *> | |||||
| *> \param[in] LDB | |||||
| *> \verbatim | |||||
| *> LDB is INTEGER | |||||
| *> The leading dimension of B. LDB >= max(1,N). | |||||
| *> \endverbatim | |||||
| *> | |||||
| *> \param[out] ALPHA | |||||
| *> \verbatim | |||||
| *> ALPHA is COMPLEX*16 array, dimension (N) | |||||
| *> The complex scalars alpha that define the eigenvalues of | |||||
| *> GNEP. | |||||
| *> \endverbatim | |||||
| *> | |||||
| *> \param[out] BETA | |||||
| *> \verbatim | |||||
| *> BETA is COMPLEX*16 array, dimension (N) | |||||
| *> The complex scalars beta that define the eigenvalues of GNEP. | |||||
| *> | |||||
| *> Together, the quantities alpha = ALPHA(j) and beta = BETA(j) | |||||
| *> represent the j-th eigenvalue of the matrix pair (A,B), in | |||||
| *> one of the forms lambda = alpha/beta or mu = beta/alpha. | |||||
| *> Since either lambda or mu may overflow, they should not, | |||||
| *> in general, be computed. | |||||
| *> \endverbatim | |||||
| *> | |||||
| *> \param[out] VL | |||||
| *> \verbatim | |||||
| *> VL is COMPLEX*16 array, dimension (LDVL,N) | |||||
| *> If JOBVL = 'V', the left eigenvectors u(j) are stored | |||||
| *> in the columns of VL, in the same order as their eigenvalues. | |||||
| *> Each eigenvector is scaled so that its largest component has | |||||
| *> abs(real part) + abs(imag. part) = 1, except for eigenvectors | |||||
| *> corresponding to an eigenvalue with alpha = beta = 0, which | |||||
| *> are set to zero. | |||||
| *> Not referenced if JOBVL = 'N'. | |||||
| *> \endverbatim | |||||
| *> | |||||
| *> \param[in] LDVL | |||||
| *> \verbatim | |||||
| *> LDVL is INTEGER | |||||
| *> The leading dimension of the matrix VL. LDVL >= 1, and | |||||
| *> if JOBVL = 'V', LDVL >= N. | |||||
| *> \endverbatim | |||||
| *> | |||||
| *> \param[out] VR | |||||
| *> \verbatim | |||||
| *> VR is COMPLEX*16 array, dimension (LDVR,N) | |||||
| *> If JOBVR = 'V', the right eigenvectors x(j) are stored | |||||
| *> in the columns of VR, in the same order as their eigenvalues. | |||||
| *> Each eigenvector is scaled so that its largest component has | |||||
| *> abs(real part) + abs(imag. part) = 1, except for eigenvectors | |||||
| *> corresponding to an eigenvalue with alpha = beta = 0, which | |||||
| *> are set to zero. | |||||
| *> Not referenced if JOBVR = 'N'. | |||||
| *> \endverbatim | |||||
| *> | |||||
| *> \param[in] LDVR | |||||
| *> \verbatim | |||||
| *> LDVR is INTEGER | |||||
| *> The leading dimension of the matrix VR. LDVR >= 1, and | |||||
| *> if JOBVR = 'V', LDVR >= N. | |||||
| *> \endverbatim | |||||
| *> | |||||
| *> \param[out] WORK | |||||
| *> \verbatim | |||||
| *> WORK is COMPLEX*16 array, dimension (MAX(1,LWORK)) | |||||
| *> On exit, if INFO = 0, WORK(1) returns the optimal LWORK. | |||||
| *> \endverbatim | |||||
| *> | |||||
| *> \param[in] LWORK | |||||
| *> \verbatim | |||||
| *> LWORK is INTEGER | |||||
| *> The dimension of the array WORK. LWORK >= max(1,2*N). | |||||
| *> For good performance, LWORK must generally be larger. | |||||
| *> To compute the optimal value of LWORK, call ILAENV to get | |||||
| *> blocksizes (for ZGEQRF, ZUNMQR, and ZUNGQR.) Then compute: | |||||
| *> NB -- MAX of the blocksizes for ZGEQRF, ZUNMQR, and ZUNGQR; | |||||
| *> The optimal LWORK is MAX( 2*N, N*(NB+1) ). | |||||
| *> | |||||
| *> If LWORK = -1, then a workspace query is assumed; the routine | |||||
| *> only calculates the optimal size of the WORK array, returns | |||||
| *> this value as the first entry of the WORK array, and no error | |||||
| *> message related to LWORK is issued by XERBLA. | |||||
| *> \endverbatim | |||||
| *> | |||||
| *> \param[out] RWORK | |||||
| *> \verbatim | |||||
| *> RWORK is DOUBLE PRECISION array, dimension (8*N) | |||||
| *> \endverbatim | |||||
| *> | |||||
| *> \param[out] INFO | |||||
| *> \verbatim | |||||
| *> INFO is INTEGER | |||||
| *> = 0: successful exit | |||||
| *> < 0: if INFO = -i, the i-th argument had an illegal value. | |||||
| *> =1,...,N: | |||||
| *> The QZ iteration failed. No eigenvectors have been | |||||
| *> calculated, but ALPHA(j) and BETA(j) should be | |||||
| *> correct for j=INFO+1,...,N. | |||||
| *> > N: errors that usually indicate LAPACK problems: | |||||
| *> =N+1: error return from ZGGBAL | |||||
| *> =N+2: error return from ZGEQRF | |||||
| *> =N+3: error return from ZUNMQR | |||||
| *> =N+4: error return from ZUNGQR | |||||
| *> =N+5: error return from ZGGHRD | |||||
| *> =N+6: error return from ZHGEQZ (other than failed | |||||
| *> iteration) | |||||
| *> =N+7: error return from ZTGEVC | |||||
| *> =N+8: error return from ZGGBAK (computing VL) | |||||
| *> =N+9: error return from ZGGBAK (computing VR) | |||||
| *> =N+10: error return from ZLASCL (various calls) | |||||
| *> \endverbatim | |||||
| * | |||||
| * Authors: | |||||
| * ======== | |||||
| * | |||||
| *> \author Univ. of Tennessee | |||||
| *> \author Univ. of California Berkeley | |||||
| *> \author Univ. of Colorado Denver | |||||
| *> \author NAG Ltd. | |||||
| * | |||||
| *> \ingroup complex16GEeigen | |||||
| * | |||||
| *> \par Further Details: | |||||
| * ===================== | |||||
| *> | |||||
| *> \verbatim | |||||
| *> | |||||
| *> Balancing | |||||
| *> --------- | |||||
| *> | |||||
| *> This driver calls ZGGBAL to both permute and scale rows and columns | |||||
| *> of A and B. The permutations PL and PR are chosen so that PL*A*PR | |||||
| *> and PL*B*R will be upper triangular except for the diagonal blocks | |||||
| *> A(i:j,i:j) and B(i:j,i:j), with i and j as close together as | |||||
| *> possible. The diagonal scaling matrices DL and DR are chosen so | |||||
| *> that the pair DL*PL*A*PR*DR, DL*PL*B*PR*DR have elements close to | |||||
| *> one (except for the elements that start out zero.) | |||||
| *> | |||||
| *> After the eigenvalues and eigenvectors of the balanced matrices | |||||
| *> have been computed, ZGGBAK transforms the eigenvectors back to what | |||||
| *> they would have been (in perfect arithmetic) if they had not been | |||||
| *> balanced. | |||||
| *> | |||||
| *> Contents of A and B on Exit | |||||
| *> -------- -- - --- - -- ---- | |||||
| *> | |||||
| *> If any eigenvectors are computed (either JOBVL='V' or JOBVR='V' or | |||||
| *> both), then on exit the arrays A and B will contain the complex Schur | |||||
| *> form[*] of the "balanced" versions of A and B. If no eigenvectors | |||||
| *> are computed, then only the diagonal blocks will be correct. | |||||
| *> | |||||
| *> [*] In other words, upper triangular form. | |||||
| *> \endverbatim | |||||
| *> | |||||
| * ===================================================================== | |||||
| SUBROUTINE ZGEGV( JOBVL, JOBVR, N, A, LDA, B, LDB, ALPHA, BETA, | |||||
| $ VL, LDVL, VR, LDVR, WORK, LWORK, RWORK, INFO ) | |||||
| * | |||||
| * -- LAPACK driver routine -- | |||||
| * -- LAPACK is a software package provided by Univ. of Tennessee, -- | |||||
| * -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..-- | |||||
| * | |||||
| * .. Scalar Arguments .. | |||||
| CHARACTER JOBVL, JOBVR | |||||
| INTEGER INFO, LDA, LDB, LDVL, LDVR, LWORK, N | |||||
| * .. | |||||
| * .. Array Arguments .. | |||||
| DOUBLE PRECISION RWORK( * ) | |||||
| COMPLEX*16 A( LDA, * ), ALPHA( * ), B( LDB, * ), | |||||
| $ BETA( * ), VL( LDVL, * ), VR( LDVR, * ), | |||||
| $ WORK( * ) | |||||
| * .. | |||||
| * | |||||
| * ===================================================================== | |||||
| * | |||||
| * .. Parameters .. | |||||
| DOUBLE PRECISION ZERO, ONE | |||||
| PARAMETER ( ZERO = 0.0D0, ONE = 1.0D0 ) | |||||
| COMPLEX*16 CZERO, CONE | |||||
| PARAMETER ( CZERO = ( 0.0D0, 0.0D0 ), | |||||
| $ CONE = ( 1.0D0, 0.0D0 ) ) | |||||
| * .. | |||||
| * .. Local Scalars .. | |||||
| LOGICAL ILIMIT, ILV, ILVL, ILVR, LQUERY | |||||
| CHARACTER CHTEMP | |||||
| INTEGER ICOLS, IHI, IINFO, IJOBVL, IJOBVR, ILEFT, ILO, | |||||
| $ IN, IRIGHT, IROWS, IRWORK, ITAU, IWORK, JC, JR, | |||||
| $ LOPT, LWKMIN, LWKOPT, NB, NB1, NB2, NB3 | |||||
| DOUBLE PRECISION ABSAI, ABSAR, ABSB, ANRM, ANRM1, ANRM2, BNRM, | |||||
| $ BNRM1, BNRM2, EPS, SAFMAX, SAFMIN, SALFAI, | |||||
| $ SALFAR, SBETA, SCALE, TEMP | |||||
| COMPLEX*16 X | |||||
| * .. | |||||
| * .. Local Arrays .. | |||||
| LOGICAL LDUMMA( 1 ) | |||||
| * .. | |||||
| * .. External Subroutines .. | |||||
| EXTERNAL XERBLA, ZGEQRF, ZGGBAK, ZGGBAL, ZGGHRD, ZHGEQZ, | |||||
| $ ZLACPY, ZLASCL, ZLASET, ZTGEVC, ZUNGQR, ZUNMQR | |||||
| * .. | |||||
| * .. External Functions .. | |||||
| LOGICAL LSAME | |||||
| INTEGER ILAENV | |||||
| DOUBLE PRECISION DLAMCH, ZLANGE | |||||
| EXTERNAL LSAME, ILAENV, DLAMCH, ZLANGE | |||||
| * .. | |||||
| * .. Intrinsic Functions .. | |||||
| INTRINSIC ABS, DBLE, DCMPLX, DIMAG, INT, MAX | |||||
| * .. | |||||
| * .. Statement Functions .. | |||||
| DOUBLE PRECISION ABS1 | |||||
| * .. | |||||
| * .. Statement Function definitions .. | |||||
| ABS1( X ) = ABS( DBLE( X ) ) + ABS( DIMAG( X ) ) | |||||
| * .. | |||||
| * .. Executable Statements .. | |||||
| * | |||||
| * Decode the input arguments | |||||
| * | |||||
| IF( LSAME( JOBVL, 'N' ) ) THEN | |||||
| IJOBVL = 1 | |||||
| ILVL = .FALSE. | |||||
| ELSE IF( LSAME( JOBVL, 'V' ) ) THEN | |||||
| IJOBVL = 2 | |||||
| ILVL = .TRUE. | |||||
| ELSE | |||||
| IJOBVL = -1 | |||||
| ILVL = .FALSE. | |||||
| END IF | |||||
| * | |||||
| IF( LSAME( JOBVR, 'N' ) ) THEN | |||||
| IJOBVR = 1 | |||||
| ILVR = .FALSE. | |||||
| ELSE IF( LSAME( JOBVR, 'V' ) ) THEN | |||||
| IJOBVR = 2 | |||||
| ILVR = .TRUE. | |||||
| ELSE | |||||
| IJOBVR = -1 | |||||
| ILVR = .FALSE. | |||||
| END IF | |||||
| ILV = ILVL .OR. ILVR | |||||
| * | |||||
| * Test the input arguments | |||||
| * | |||||
| LWKMIN = MAX( 2*N, 1 ) | |||||
| LWKOPT = LWKMIN | |||||
| WORK( 1 ) = LWKOPT | |||||
| LQUERY = ( LWORK.EQ.-1 ) | |||||
| INFO = 0 | |||||
| IF( IJOBVL.LE.0 ) THEN | |||||
| INFO = -1 | |||||
| ELSE IF( IJOBVR.LE.0 ) THEN | |||||
| INFO = -2 | |||||
| ELSE IF( N.LT.0 ) THEN | |||||
| INFO = -3 | |||||
| ELSE IF( LDA.LT.MAX( 1, N ) ) THEN | |||||
| INFO = -5 | |||||
| ELSE IF( LDB.LT.MAX( 1, N ) ) THEN | |||||
| INFO = -7 | |||||
| ELSE IF( LDVL.LT.1 .OR. ( ILVL .AND. LDVL.LT.N ) ) THEN | |||||
| INFO = -11 | |||||
| ELSE IF( LDVR.LT.1 .OR. ( ILVR .AND. LDVR.LT.N ) ) THEN | |||||
| INFO = -13 | |||||
| ELSE IF( LWORK.LT.LWKMIN .AND. .NOT.LQUERY ) THEN | |||||
| INFO = -15 | |||||
| END IF | |||||
| * | |||||
| IF( INFO.EQ.0 ) THEN | |||||
| NB1 = ILAENV( 1, 'ZGEQRF', ' ', N, N, -1, -1 ) | |||||
| NB2 = ILAENV( 1, 'ZUNMQR', ' ', N, N, N, -1 ) | |||||
| NB3 = ILAENV( 1, 'ZUNGQR', ' ', N, N, N, -1 ) | |||||
| NB = MAX( NB1, NB2, NB3 ) | |||||
| LOPT = MAX( 2*N, N*( NB+1 ) ) | |||||
| WORK( 1 ) = LOPT | |||||
| END IF | |||||
| * | |||||
| IF( INFO.NE.0 ) THEN | |||||
| CALL XERBLA( 'ZGEGV ', -INFO ) | |||||
| RETURN | |||||
| ELSE IF( LQUERY ) THEN | |||||
| RETURN | |||||
| END IF | |||||
| * | |||||
| * Quick return if possible | |||||
| * | |||||
| IF( N.EQ.0 ) | |||||
| $ RETURN | |||||
| * | |||||
| * Get machine constants | |||||
| * | |||||
| EPS = DLAMCH( 'E' )*DLAMCH( 'B' ) | |||||
| SAFMIN = DLAMCH( 'S' ) | |||||
| SAFMIN = SAFMIN + SAFMIN | |||||
| SAFMAX = ONE / SAFMIN | |||||
| * | |||||
| * Scale A | |||||
| * | |||||
| ANRM = ZLANGE( 'M', N, N, A, LDA, RWORK ) | |||||
| ANRM1 = ANRM | |||||
| ANRM2 = ONE | |||||
| IF( ANRM.LT.ONE ) THEN | |||||
| IF( SAFMAX*ANRM.LT.ONE ) THEN | |||||
| ANRM1 = SAFMIN | |||||
| ANRM2 = SAFMAX*ANRM | |||||
| END IF | |||||
| END IF | |||||
| * | |||||
| IF( ANRM.GT.ZERO ) THEN | |||||
| CALL ZLASCL( 'G', -1, -1, ANRM, ONE, N, N, A, LDA, IINFO ) | |||||
| IF( IINFO.NE.0 ) THEN | |||||
| INFO = N + 10 | |||||
| RETURN | |||||
| END IF | |||||
| END IF | |||||
| * | |||||
| * Scale B | |||||
| * | |||||
| BNRM = ZLANGE( 'M', N, N, B, LDB, RWORK ) | |||||
| BNRM1 = BNRM | |||||
| BNRM2 = ONE | |||||
| IF( BNRM.LT.ONE ) THEN | |||||
| IF( SAFMAX*BNRM.LT.ONE ) THEN | |||||
| BNRM1 = SAFMIN | |||||
| BNRM2 = SAFMAX*BNRM | |||||
| END IF | |||||
| END IF | |||||
| * | |||||
| IF( BNRM.GT.ZERO ) THEN | |||||
| CALL ZLASCL( 'G', -1, -1, BNRM, ONE, N, N, B, LDB, IINFO ) | |||||
| IF( IINFO.NE.0 ) THEN | |||||
| INFO = N + 10 | |||||
| RETURN | |||||
| END IF | |||||
| END IF | |||||
| * | |||||
| * Permute the matrix to make it more nearly triangular | |||||
| * Also "balance" the matrix. | |||||
| * | |||||
| ILEFT = 1 | |||||
| IRIGHT = N + 1 | |||||
| IRWORK = IRIGHT + N | |||||
| CALL ZGGBAL( 'P', N, A, LDA, B, LDB, ILO, IHI, RWORK( ILEFT ), | |||||
| $ RWORK( IRIGHT ), RWORK( IRWORK ), IINFO ) | |||||
| IF( IINFO.NE.0 ) THEN | |||||
| INFO = N + 1 | |||||
| GO TO 80 | |||||
| END IF | |||||
| * | |||||
| * Reduce B to triangular form, and initialize VL and/or VR | |||||
| * | |||||
| IROWS = IHI + 1 - ILO | |||||
| IF( ILV ) THEN | |||||
| ICOLS = N + 1 - ILO | |||||
| ELSE | |||||
| ICOLS = IROWS | |||||
| END IF | |||||
| ITAU = 1 | |||||
| IWORK = ITAU + IROWS | |||||
| CALL ZGEQRF( IROWS, ICOLS, B( ILO, ILO ), LDB, WORK( ITAU ), | |||||
| $ WORK( IWORK ), LWORK+1-IWORK, IINFO ) | |||||
| IF( IINFO.GE.0 ) | |||||
| $ LWKOPT = MAX( LWKOPT, INT( WORK( IWORK ) )+IWORK-1 ) | |||||
| IF( IINFO.NE.0 ) THEN | |||||
| INFO = N + 2 | |||||
| GO TO 80 | |||||
| END IF | |||||
| * | |||||
| CALL ZUNMQR( 'L', 'C', IROWS, ICOLS, IROWS, B( ILO, ILO ), LDB, | |||||
| $ WORK( ITAU ), A( ILO, ILO ), LDA, WORK( IWORK ), | |||||
| $ LWORK+1-IWORK, IINFO ) | |||||
| IF( IINFO.GE.0 ) | |||||
| $ LWKOPT = MAX( LWKOPT, INT( WORK( IWORK ) )+IWORK-1 ) | |||||
| IF( IINFO.NE.0 ) THEN | |||||
| INFO = N + 3 | |||||
| GO TO 80 | |||||
| END IF | |||||
| * | |||||
| IF( ILVL ) THEN | |||||
| CALL ZLASET( 'Full', N, N, CZERO, CONE, VL, LDVL ) | |||||
| CALL ZLACPY( 'L', IROWS-1, IROWS-1, B( ILO+1, ILO ), LDB, | |||||
| $ VL( ILO+1, ILO ), LDVL ) | |||||
| CALL ZUNGQR( IROWS, IROWS, IROWS, VL( ILO, ILO ), LDVL, | |||||
| $ WORK( ITAU ), WORK( IWORK ), LWORK+1-IWORK, | |||||
| $ IINFO ) | |||||
| IF( IINFO.GE.0 ) | |||||
| $ LWKOPT = MAX( LWKOPT, INT( WORK( IWORK ) )+IWORK-1 ) | |||||
| IF( IINFO.NE.0 ) THEN | |||||
| INFO = N + 4 | |||||
| GO TO 80 | |||||
| END IF | |||||
| END IF | |||||
| * | |||||
| IF( ILVR ) | |||||
| $ CALL ZLASET( 'Full', N, N, CZERO, CONE, VR, LDVR ) | |||||
| * | |||||
| * Reduce to generalized Hessenberg form | |||||
| * | |||||
| IF( ILV ) THEN | |||||
| * | |||||
| * Eigenvectors requested -- work on whole matrix. | |||||
| * | |||||
| CALL ZGGHRD( JOBVL, JOBVR, N, ILO, IHI, A, LDA, B, LDB, VL, | |||||
| $ LDVL, VR, LDVR, IINFO ) | |||||
| ELSE | |||||
| CALL ZGGHRD( 'N', 'N', IROWS, 1, IROWS, A( ILO, ILO ), LDA, | |||||
| $ B( ILO, ILO ), LDB, VL, LDVL, VR, LDVR, IINFO ) | |||||
| END IF | |||||
| IF( IINFO.NE.0 ) THEN | |||||
| INFO = N + 5 | |||||
| GO TO 80 | |||||
| END IF | |||||
| * | |||||
| * Perform QZ algorithm | |||||
| * | |||||
| IWORK = ITAU | |||||
| IF( ILV ) THEN | |||||
| CHTEMP = 'S' | |||||
| ELSE | |||||
| CHTEMP = 'E' | |||||
| END IF | |||||
| CALL ZHGEQZ( CHTEMP, JOBVL, JOBVR, N, ILO, IHI, A, LDA, B, LDB, | |||||
| $ ALPHA, BETA, VL, LDVL, VR, LDVR, WORK( IWORK ), | |||||
| $ LWORK+1-IWORK, RWORK( IRWORK ), IINFO ) | |||||
| IF( IINFO.GE.0 ) | |||||
| $ LWKOPT = MAX( LWKOPT, INT( WORK( IWORK ) )+IWORK-1 ) | |||||
| IF( IINFO.NE.0 ) THEN | |||||
| IF( IINFO.GT.0 .AND. IINFO.LE.N ) THEN | |||||
| INFO = IINFO | |||||
| ELSE IF( IINFO.GT.N .AND. IINFO.LE.2*N ) THEN | |||||
| INFO = IINFO - N | |||||
| ELSE | |||||
| INFO = N + 6 | |||||
| END IF | |||||
| GO TO 80 | |||||
| END IF | |||||
| * | |||||
| IF( ILV ) THEN | |||||
| * | |||||
| * Compute Eigenvectors | |||||
| * | |||||
| IF( ILVL ) THEN | |||||
| IF( ILVR ) THEN | |||||
| CHTEMP = 'B' | |||||
| ELSE | |||||
| CHTEMP = 'L' | |||||
| END IF | |||||
| ELSE | |||||
| CHTEMP = 'R' | |||||
| END IF | |||||
| * | |||||
| CALL ZTGEVC( CHTEMP, 'B', LDUMMA, N, A, LDA, B, LDB, VL, LDVL, | |||||
| $ VR, LDVR, N, IN, WORK( IWORK ), RWORK( IRWORK ), | |||||
| $ IINFO ) | |||||
| IF( IINFO.NE.0 ) THEN | |||||
| INFO = N + 7 | |||||
| GO TO 80 | |||||
| END IF | |||||
| * | |||||
| * Undo balancing on VL and VR, rescale | |||||
| * | |||||
| IF( ILVL ) THEN | |||||
| CALL ZGGBAK( 'P', 'L', N, ILO, IHI, RWORK( ILEFT ), | |||||
| $ RWORK( IRIGHT ), N, VL, LDVL, IINFO ) | |||||
| IF( IINFO.NE.0 ) THEN | |||||
| INFO = N + 8 | |||||
| GO TO 80 | |||||
| END IF | |||||
| DO 30 JC = 1, N | |||||
| TEMP = ZERO | |||||
| DO 10 JR = 1, N | |||||
| TEMP = MAX( TEMP, ABS1( VL( JR, JC ) ) ) | |||||
| 10 CONTINUE | |||||
| IF( TEMP.LT.SAFMIN ) | |||||
| $ GO TO 30 | |||||
| TEMP = ONE / TEMP | |||||
| DO 20 JR = 1, N | |||||
| VL( JR, JC ) = VL( JR, JC )*TEMP | |||||
| 20 CONTINUE | |||||
| 30 CONTINUE | |||||
| END IF | |||||
| IF( ILVR ) THEN | |||||
| CALL ZGGBAK( 'P', 'R', N, ILO, IHI, RWORK( ILEFT ), | |||||
| $ RWORK( IRIGHT ), N, VR, LDVR, IINFO ) | |||||
| IF( IINFO.NE.0 ) THEN | |||||
| INFO = N + 9 | |||||
| GO TO 80 | |||||
| END IF | |||||
| DO 60 JC = 1, N | |||||
| TEMP = ZERO | |||||
| DO 40 JR = 1, N | |||||
| TEMP = MAX( TEMP, ABS1( VR( JR, JC ) ) ) | |||||
| 40 CONTINUE | |||||
| IF( TEMP.LT.SAFMIN ) | |||||
| $ GO TO 60 | |||||
| TEMP = ONE / TEMP | |||||
| DO 50 JR = 1, N | |||||
| VR( JR, JC ) = VR( JR, JC )*TEMP | |||||
| 50 CONTINUE | |||||
| 60 CONTINUE | |||||
| END IF | |||||
| * | |||||
| * End of eigenvector calculation | |||||
| * | |||||
| END IF | |||||
| * | |||||
| * Undo scaling in alpha, beta | |||||
| * | |||||
| * Note: this does not give the alpha and beta for the unscaled | |||||
| * problem. | |||||
| * | |||||
| * Un-scaling is limited to avoid underflow in alpha and beta | |||||
| * if they are significant. | |||||
| * | |||||
| DO 70 JC = 1, N | |||||
| ABSAR = ABS( DBLE( ALPHA( JC ) ) ) | |||||
| ABSAI = ABS( DIMAG( ALPHA( JC ) ) ) | |||||
| ABSB = ABS( DBLE( BETA( JC ) ) ) | |||||
| SALFAR = ANRM*DBLE( ALPHA( JC ) ) | |||||
| SALFAI = ANRM*DIMAG( ALPHA( JC ) ) | |||||
| SBETA = BNRM*DBLE( BETA( JC ) ) | |||||
| ILIMIT = .FALSE. | |||||
| SCALE = ONE | |||||
| * | |||||
| * Check for significant underflow in imaginary part of ALPHA | |||||
| * | |||||
| IF( ABS( SALFAI ).LT.SAFMIN .AND. ABSAI.GE. | |||||
| $ MAX( SAFMIN, EPS*ABSAR, EPS*ABSB ) ) THEN | |||||
| ILIMIT = .TRUE. | |||||
| SCALE = ( SAFMIN / ANRM1 ) / MAX( SAFMIN, ANRM2*ABSAI ) | |||||
| END IF | |||||
| * | |||||
| * Check for significant underflow in real part of ALPHA | |||||
| * | |||||
| IF( ABS( SALFAR ).LT.SAFMIN .AND. ABSAR.GE. | |||||
| $ MAX( SAFMIN, EPS*ABSAI, EPS*ABSB ) ) THEN | |||||
| ILIMIT = .TRUE. | |||||
| SCALE = MAX( SCALE, ( SAFMIN / ANRM1 ) / | |||||
| $ MAX( SAFMIN, ANRM2*ABSAR ) ) | |||||
| END IF | |||||
| * | |||||
| * Check for significant underflow in BETA | |||||
| * | |||||
| IF( ABS( SBETA ).LT.SAFMIN .AND. ABSB.GE. | |||||
| $ MAX( SAFMIN, EPS*ABSAR, EPS*ABSAI ) ) THEN | |||||
| ILIMIT = .TRUE. | |||||
| SCALE = MAX( SCALE, ( SAFMIN / BNRM1 ) / | |||||
| $ MAX( SAFMIN, BNRM2*ABSB ) ) | |||||
| END IF | |||||
| * | |||||
| * Check for possible overflow when limiting scaling | |||||
| * | |||||
| IF( ILIMIT ) THEN | |||||
| TEMP = ( SCALE*SAFMIN )*MAX( ABS( SALFAR ), ABS( SALFAI ), | |||||
| $ ABS( SBETA ) ) | |||||
| IF( TEMP.GT.ONE ) | |||||
| $ SCALE = SCALE / TEMP | |||||
| IF( SCALE.LT.ONE ) | |||||
| $ ILIMIT = .FALSE. | |||||
| END IF | |||||
| * | |||||
| * Recompute un-scaled ALPHA, BETA if necessary. | |||||
| * | |||||
| IF( ILIMIT ) THEN | |||||
| SALFAR = ( SCALE*DBLE( ALPHA( JC ) ) )*ANRM | |||||
| SALFAI = ( SCALE*DIMAG( ALPHA( JC ) ) )*ANRM | |||||
| SBETA = ( SCALE*BETA( JC ) )*BNRM | |||||
| END IF | |||||
| ALPHA( JC ) = DCMPLX( SALFAR, SALFAI ) | |||||
| BETA( JC ) = SBETA | |||||
| 70 CONTINUE | |||||
| * | |||||
| 80 CONTINUE | |||||
| WORK( 1 ) = LWKOPT | |||||
| * | |||||
| RETURN | |||||
| * | |||||
| * End of ZGEGV | |||||
| * | |||||
| END | |||||