⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 dtgevc.f

📁 计算矩阵的经典开源库.全世界都在用它.相信你也不能例外.
💻 F
📖 第 1 页 / 共 3 页
字号:
      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 + -