📄 dtgevc.f
字号:
SUBROUTINE DTGEVC( SIDE, HOWMNY, SELECT, N, A, LDA, B, LDB, VL, $ LDVL, VR, LDVR, MM, M, WORK, INFO )** -- LAPACK routine (instrumented to count operations, version 3.0) --* Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd.,* Courant Institute, Argonne National Lab, and Rice University* June 30, 1999** .. Scalar Arguments .. CHARACTER HOWMNY, SIDE INTEGER INFO, LDA, LDB, LDVL, LDVR, M, MM, N* ..* .. Array Arguments .. LOGICAL SELECT( * ) DOUBLE PRECISION A( LDA, * ), B( LDB, * ), VL( LDVL, * ), $ VR( LDVR, * ), WORK( * )* ..** ---------------------- Begin Timing Code -------------------------* Common block to return operation count and iteration count* ITCNT is initialized to 0, OPS is only incremented* OPST is used to accumulate small contributions to OPS* to avoid roundoff error* .. Common blocks .. COMMON / LATIME / OPS, ITCNT* ..* .. Scalars in Common .. DOUBLE PRECISION ITCNT, OPS* ..* ----------------------- End Timing Code --------------------------*** Purpose* =======** DTGEVC computes some or all of the right and/or left generalized* eigenvectors of a pair of real upper triangular matrices (A,B).** The right generalized eigenvector x and the left generalized* eigenvector y of (A,B) corresponding to a generalized eigenvalue* w are defined by:** (A - wB) * x = 0 and y**H * (A - wB) = 0** where y**H denotes the conjugate tranpose of y.** If an eigenvalue w is determined by zero diagonal elements of both A* and B, a unit vector is returned as the corresponding eigenvector.** If all eigenvectors are requested, the routine may either return* the matrices X and/or Y of right or left eigenvectors of (A,B), or* the products Z*X and/or Q*Y, where Z and Q are input orthogonal* matrices. If (A,B) was obtained from the generalized real-Schur* factorization of an original pair of matrices* (A0,B0) = (Q*A*Z**H,Q*B*Z**H),* then Z*X and Q*Y are the matrices of right or left eigenvectors of* A.** A must be block upper triangular, with 1-by-1 and 2-by-2 diagonal* blocks. Corresponding to each 2-by-2 diagonal block is a complex* conjugate pair of eigenvalues and eigenvectors; only one* eigenvector of the pair is computed, namely the one corresponding* to the eigenvalue with positive imaginary part.** Arguments* =========** SIDE (input) CHARACTER*1* = 'R': compute right eigenvectors only;* = 'L': compute left eigenvectors only;* = 'B': compute both right and left eigenvectors.** HOWMNY (input) CHARACTER*1* = 'A': compute all right and/or left eigenvectors;* = 'B': compute all right and/or left eigenvectors, and* backtransform them using the input matrices supplied* in VR and/or VL;* = 'S': compute selected right and/or left eigenvectors,* specified by the logical array SELECT.** SELECT (input) LOGICAL array, dimension (N)* If HOWMNY='S', SELECT specifies the eigenvectors to be* computed.* If HOWMNY='A' or 'B', SELECT is not referenced.* To select the real eigenvector corresponding to the real* eigenvalue w(j), SELECT(j) must be set to .TRUE. To select* the complex eigenvector corresponding to a complex conjugate* pair w(j) and w(j+1), either SELECT(j) or SELECT(j+1) must* be set to .TRUE..** N (input) INTEGER* The order of the matrices A and B. N >= 0.** A (input) DOUBLE PRECISION array, dimension (LDA,N)* The upper quasi-triangular matrix A.** LDA (input) INTEGER* The leading dimension of array A. LDA >= max(1,N).** B (input) DOUBLE PRECISION array, dimension (LDB,N)* The upper triangular matrix B. If A has a 2-by-2 diagonal* block, then the corresponding 2-by-2 block of B must be* diagonal with positive elements.** LDB (input) INTEGER* The leading dimension of array B. LDB >= max(1,N).** VL (input/output) DOUBLE PRECISION array, dimension (LDVL,MM)* On entry, if SIDE = 'L' or 'B' and HOWMNY = 'B', VL must* contain an N-by-N matrix Q (usually the orthogonal matrix Q* of left Schur vectors returned by DHGEQZ).* On exit, if SIDE = 'L' or 'B', VL contains:* if HOWMNY = 'A', the matrix Y of left eigenvectors of (A,B);* if HOWMNY = 'B', the matrix Q*Y;* if HOWMNY = 'S', the left eigenvectors of (A,B) specified by* SELECT, stored consecutively in the columns of* VL, in the same order as their eigenvalues.* If SIDE = 'R', VL is not referenced.** A complex eigenvector corresponding to a complex eigenvalue* is stored in two consecutive columns, the first holding the* real part, and the second the imaginary part.** LDVL (input) INTEGER* The leading dimension of array VL.* LDVL >= max(1,N) if SIDE = 'L' or 'B'; LDVL >= 1 otherwise.** VR (input/output) DOUBLE PRECISION array, dimension (LDVR,MM)* On entry, if SIDE = 'R' or 'B' and HOWMNY = 'B', VR must* contain an N-by-N matrix Q (usually the orthogonal matrix Z* of right Schur vectors returned by DHGEQZ).* On exit, if SIDE = 'R' or 'B', VR contains:* if HOWMNY = 'A', the matrix X of right eigenvectors of (A,B);* if HOWMNY = 'B', the matrix Z*X;* if HOWMNY = 'S', the right eigenvectors of (A,B) specified by* SELECT, stored consecutively in the columns of* VR, in the same order as their eigenvalues.* If SIDE = 'L', VR is not referenced.** A complex eigenvector corresponding to a complex eigenvalue* is stored in two consecutive columns, the first holding the* real part and the second the imaginary part.** LDVR (input) INTEGER* The leading dimension of the array VR.* LDVR >= max(1,N) if SIDE = 'R' or 'B'; LDVR >= 1 otherwise.** MM (input) INTEGER* The number of columns in the arrays VL and/or VR. MM >= M.** M (output) INTEGER* The number of columns in the arrays VL and/or VR actually* used to store the eigenvectors. If HOWMNY = 'A' or 'B', M* is set to N. Each selected real eigenvector occupies one* column and each selected complex eigenvector occupies two* columns.** WORK (workspace) DOUBLE PRECISION array, dimension (6*N)** INFO (output) INTEGER* = 0: successful exit.* < 0: if INFO = -i, the i-th argument had an illegal value.* > 0: the 2-by-2 block (INFO:INFO+1) does not have a complex* eigenvalue.** Further Details* ===============** Allocation of workspace:* ---------- -- ---------** WORK( j ) = 1-norm of j-th column of A, above the diagonal* WORK( N+j ) = 1-norm of j-th column of B, above the diagonal* WORK( 2*N+1:3*N ) = real part of eigenvector* WORK( 3*N+1:4*N ) = imaginary part of eigenvector* WORK( 4*N+1:5*N ) = real part of back-transformed eigenvector* WORK( 5*N+1:6*N ) = imaginary part of back-transformed eigenvector** Rowwise vs. columnwise solution methods:* ------- -- ---------- -------- -------** Finding a generalized eigenvector consists basically of solving the* singular triangular system** (A - w B) x = 0 (for right) or: (A - w B)**H y = 0 (for left)** Consider finding the i-th right eigenvector (assume all eigenvalues* are real). The equation to be solved is:* n i* 0 = sum C(j,k) v(k) = sum C(j,k) v(k) for j = i,. . .,1* k=j k=j** where C = (A - w B) (The components v(i+1:n) are 0.)** The "rowwise" method is:** (1) v(i) := 1* for j = i-1,. . .,1:* i* (2) compute s = - sum C(j,k) v(k) and* k=j+1** (3) v(j) := s / C(j,j)** Step 2 is sometimes called the "dot product" step, since it is an* inner product between the j-th row and the portion of the eigenvector* that has been computed so far.** The "columnwise" method consists basically in doing the sums* for all the rows in parallel. As each v(j) is computed, the* contribution of v(j) times the j-th column of C is added to the* partial sums. Since FORTRAN arrays are stored columnwise, this has* the advantage that at each step, the elements of C that are accessed* are adjacent to one another, whereas with the rowwise method, the* elements accessed at a step are spaced LDA (and LDB) words apart.** When finding left eigenvectors, the matrix in question is the* transpose of the one in storage, so the rowwise method then* actually accesses columns of A and B at each step, and so is the* preferred method.** =====================================================================** .. Parameters .. DOUBLE PRECISION ZERO, ONE, SAFETY PARAMETER ( ZERO = 0.0D+0, ONE = 1.0D+0, $ SAFETY = 1.0D+2 )* ..* .. Local Scalars .. LOGICAL COMPL, COMPR, IL2BY2, ILABAD, ILALL, ILBACK, $ ILBBAD, ILCOMP, ILCPLX, LSA, LSB INTEGER I, IBEG, IEIG, IEND, IHWMNY, IINFO, IM, IN2BY2, $ ISIDE, J, JA, JC, JE, JR, JW, NA, NW DOUBLE PRECISION ACOEF, ACOEFA, ANORM, ASCALE, BCOEFA, BCOEFI, $ BCOEFR, BIG, BIGNUM, BNORM, BSCALE, CIM2A, $ CIM2B, CIMAGA, CIMAGB, CRE2A, CRE2B, CREALA, $ CREALB, DMIN, OPSSCA, OPST, SAFMIN, SALFAR, $ SBETA, SCALE, SMALL, TEMP, TEMP2, TEMP2I, $ TEMP2R, ULP, XMAX, XSCALE* ..* .. Local Arrays .. DOUBLE PRECISION BDIAG( 2 ), SUM( 2, 2 ), SUMA( 2, 2 ), $ SUMB( 2, 2 )* ..* .. External Functions .. LOGICAL LSAME DOUBLE PRECISION DLAMCH EXTERNAL LSAME, DLAMCH* ..* .. External Subroutines .. EXTERNAL DGEMV, DLABAD, DLACPY, DLAG2, DLALN2, XERBLA* ..* .. Intrinsic Functions .. INTRINSIC ABS, DBLE, MAX, MIN* ..* .. Executable Statements ..** Decode and Test the input parameters* IF( LSAME( HOWMNY, 'A' ) ) THEN IHWMNY = 1 ILALL = .TRUE. ILBACK = .FALSE. ELSE IF( LSAME( HOWMNY, 'S' ) ) THEN IHWMNY = 2 ILALL = .FALSE. ILBACK = .FALSE. ELSE IF( LSAME( HOWMNY, 'B' ) .OR. LSAME( HOWMNY, 'T' ) ) THEN IHWMNY = 3 ILALL = .TRUE. ILBACK = .TRUE. ELSE IHWMNY = -1 ILALL = .TRUE. END IF* IF( LSAME( SIDE, 'R' ) ) THEN ISIDE = 1 COMPL = .FALSE. COMPR = .TRUE. ELSE IF( LSAME( SIDE, 'L' ) ) THEN ISIDE = 2 COMPL = .TRUE. COMPR = .FALSE. ELSE IF( LSAME( SIDE, 'B' ) ) THEN ISIDE = 3 COMPL = .TRUE. COMPR = .TRUE. ELSE ISIDE = -1 END IF* INFO = 0 IF( ISIDE.LT.0 ) THEN INFO = -1 ELSE IF( IHWMNY.LT.0 ) THEN INFO = -2 ELSE IF( N.LT.0 ) THEN INFO = -4 ELSE IF( LDA.LT.MAX( 1, N ) ) THEN INFO = -6 ELSE IF( LDB.LT.MAX( 1, N ) ) THEN INFO = -8 END IF IF( INFO.NE.0 ) THEN CALL XERBLA( 'DTGEVC', -INFO ) RETURN END IF** Count the number of eigenvectors to be computed* IF( .NOT.ILALL ) THEN IM = 0 ILCPLX = .FALSE. DO 10 J = 1, N IF( ILCPLX ) THEN ILCPLX = .FALSE. GO TO 10 END IF IF( J.LT.N ) THEN IF( A( J+1, J ).NE.ZERO ) $ ILCPLX = .TRUE. END IF IF( ILCPLX ) THEN IF( SELECT( J ) .OR. SELECT( J+1 ) ) $ IM = IM + 2 ELSE IF( SELECT( J ) ) $ IM = IM + 1 END IF 10 CONTINUE ELSE IM = N END IF** Check 2-by-2 diagonal blocks of A, B* ILABAD = .FALSE. ILBBAD = .FALSE. DO 20 J = 1, N - 1 IF( A( J+1, J ).NE.ZERO ) THEN IF( B( J, J ).EQ.ZERO .OR. B( J+1, J+1 ).EQ.ZERO .OR. $ B( J, J+1 ).NE.ZERO )ILBBAD = .TRUE. IF( J.LT.N-1 ) THEN IF( A( J+2, J+1 ).NE.ZERO ) $ ILABAD = .TRUE. END IF END IF 20 CONTINUE* IF( ILABAD ) THEN INFO = -5 ELSE IF( ILBBAD ) THEN INFO = -7 ELSE IF( COMPL .AND. LDVL.LT.N .OR. LDVL.LT.1 ) THEN INFO = -10 ELSE IF( COMPR .AND. LDVR.LT.N .OR. LDVR.LT.1 ) THEN INFO = -12 ELSE IF( MM.LT.IM ) THEN INFO = -13 END IF IF( INFO.NE.0 ) THEN CALL XERBLA( 'DTGEVC', -INFO ) RETURN END IF** Quick return if possible* M = IM IF( N.EQ.0 ) $ RETURN** Machine Constants* SAFMIN = DLAMCH( 'Safe minimum' ) BIG = ONE / SAFMIN CALL DLABAD( SAFMIN, BIG ) ULP = DLAMCH( 'Epsilon' )*DLAMCH( 'Base' ) SMALL = SAFMIN*N / ULP BIG = ONE / SMALL BIGNUM = ONE / ( SAFMIN*N )** Compute the 1-norm of each column of the strictly upper triangular* part (i.e., excluding all elements belonging to the diagonal* blocks) of A and B to check for possible overflow in the* triangular solver.* ANORM = ABS( A( 1, 1 ) ) IF( N.GT.1 ) $ ANORM = ANORM + ABS( A( 2, 1 ) ) BNORM = ABS( B( 1, 1 ) ) WORK( 1 ) = ZERO WORK( N+1 ) = ZERO* DO 50 J = 2, N TEMP = ZERO TEMP2 = ZERO IF( A( J, J-1 ).EQ.ZERO ) THEN IEND = J - 1 ELSE IEND = J - 2 END IF DO 30 I = 1, IEND TEMP = TEMP + ABS( A( I, J ) ) TEMP2 = TEMP2 + ABS( B( I, J ) ) 30 CONTINUE WORK( J ) = TEMP WORK( N+J ) = TEMP2 DO 40 I = IEND + 1, MIN( J+1, N ) TEMP = TEMP + ABS( A( I, J ) ) TEMP2 = TEMP2 + ABS( B( I, J ) ) 40 CONTINUE ANORM = MAX( ANORM, TEMP ) BNORM = MAX( BNORM, TEMP2 ) 50 CONTINUE* ASCALE = ONE / MAX( ANORM, SAFMIN ) BSCALE = ONE / MAX( BNORM, SAFMIN )** ---------------------- Begin Timing Code ------------------------- OPS = OPS + DBLE( N**2+3*N+6 )* ----------------------- End Timing Code --------------------------** Left eigenvectors
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -