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

📄 zlahqr.f

📁 计算矩阵的经典开源库.全世界都在用它.相信你也不能例外.
💻 F
字号:
      SUBROUTINE ZLAHQR( WANTT, WANTZ, N, ILO, IHI, H, LDH, W, ILOZ,     $                   IHIZ, Z, LDZ, INFO )**  -- LAPACK auxiliary routine (instrumented to count operations) --*     Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd.,*     Courant Institute, Argonne National Lab, and Rice University*     June 30, 1999**     .. Scalar Arguments ..      LOGICAL            WANTT, WANTZ      INTEGER            IHI, IHIZ, ILO, ILOZ, INFO, LDH, LDZ, N*     ..*     .. Array Arguments ..      COMPLEX*16         H( LDH, * ), W( * ), Z( LDZ, * )*     ..*     Common block to return operation count.*     .. Common blocks ..      COMMON             / LATIME / OPS, ITCNT*     ..*     .. Scalars in Common ..      DOUBLE PRECISION   ITCNT, OPS*     ..**  Purpose*  =======**  ZLAHQR is an auxiliary routine called by ZHSEQR to update the*  eigenvalues and Schur decomposition already computed by ZHSEQR, by*  dealing with the Hessenberg submatrix in rows and columns ILO to IHI.**  Arguments*  =========**  WANTT   (input) LOGICAL*          = .TRUE. : the full Schur form T is required;*          = .FALSE.: only eigenvalues are required.**  WANTZ   (input) LOGICAL*          = .TRUE. : the matrix of Schur vectors Z is required;*          = .FALSE.: Schur vectors are not required.**  N       (input) INTEGER*          The order of the matrix H.  N >= 0.**  ILO     (input) INTEGER*  IHI     (input) INTEGER*          It is assumed that H is already upper triangular in rows and*          columns IHI+1:N, and that H(ILO,ILO-1) = 0 (unless ILO = 1).*          ZLAHQR works primarily with the Hessenberg submatrix in rows*          and columns ILO to IHI, but applies transformations to all of*          H if WANTT is .TRUE..*          1 <= ILO <= max(1,IHI); IHI <= N.**  H       (input/output) COMPLEX*16 array, dimension (LDH,N)*          On entry, the upper Hessenberg matrix H.*          On exit, if WANTT is .TRUE., H is upper triangular in rows*          and columns ILO:IHI, with any 2-by-2 diagonal blocks in*          standard form. If WANTT is .FALSE., the contents of H are*          unspecified on exit.**  LDH     (input) INTEGER*          The leading dimension of the array H. LDH >= max(1,N).**  W       (output) COMPLEX*16 array, dimension (N)*          The computed eigenvalues ILO to IHI are stored in the*          corresponding elements of W. If WANTT is .TRUE., the*          eigenvalues are stored in the same order as on the diagonal*          of the Schur form returned in H, with W(i) = H(i,i).**  ILOZ    (input) INTEGER*  IHIZ    (input) INTEGER*          Specify the rows of Z to which transformations must be*          applied if WANTZ is .TRUE..*          1 <= ILOZ <= ILO; IHI <= IHIZ <= N.**  Z       (input/output) COMPLEX*16 array, dimension (LDZ,N)*          If WANTZ is .TRUE., on entry Z must contain the current*          matrix Z of transformations accumulated by ZHSEQR, and on*          exit Z has been updated; transformations are applied only to*          the submatrix Z(ILOZ:IHIZ,ILO:IHI).*          If WANTZ is .FALSE., Z is not referenced.**  LDZ     (input) INTEGER*          The leading dimension of the array Z. LDZ >= max(1,N).**  INFO    (output) INTEGER*          = 0: successful exit*          > 0: if INFO = i, ZLAHQR failed to compute all the*               eigenvalues ILO to IHI in a total of 30*(IHI-ILO+1)*               iterations; elements i+1:ihi of W contain those*               eigenvalues which have been successfully computed.**  =====================================================================**     .. Parameters ..      COMPLEX*16         ZERO, ONE      PARAMETER          ( ZERO = ( 0.0D+0, 0.0D+0 ),     $                   ONE = ( 1.0D+0, 0.0D+0 ) )      DOUBLE PRECISION   RZERO, HALF      PARAMETER          ( RZERO = 0.0D+0, HALF = 0.5D+0 )      DOUBLE PRECISION   DAT1      PARAMETER          ( DAT1 = 0.75D+0 )*     ..*     .. Local Scalars ..      INTEGER            I, I1, I2, ITN, ITS, J, K, L, M, NH, NZ      DOUBLE PRECISION   H10, H21, OPST, RTEMP, S, SMLNUM, T2, TST1, ULP      COMPLEX*16         CDUM, H11, H11S, H22, SUM, T, T1, TEMP, U, V2,     $                   X, Y*     ..*     .. Local Arrays ..      DOUBLE PRECISION   RWORK( 1 )      COMPLEX*16         V( 2 )*     ..*     .. External Functions ..      DOUBLE PRECISION   DLAMCH, ZLANHS      COMPLEX*16         ZLADIV      EXTERNAL           DLAMCH, ZLANHS, ZLADIV*     ..*     .. External Subroutines ..      EXTERNAL           ZCOPY, ZLARFG, ZSCAL*     ..*     .. Intrinsic Functions ..      INTRINSIC          ABS, DBLE, DCONJG, DIMAG, MAX, MIN, SQRT*     ..*     .. Statement Functions ..      DOUBLE PRECISION   CABS1*     ..*     .. Statement Function definitions ..      CABS1( CDUM ) = ABS( DBLE( CDUM ) ) + ABS( DIMAG( CDUM ) )*     ..*     .. Executable Statements ..*      INFO = 0****     Initialize      OPST = 0*****     Quick return if possible*      IF( N.EQ.0 )     $   RETURN      IF( ILO.EQ.IHI ) THEN         W( ILO ) = H( ILO, ILO )         RETURN      END IF*      NH = IHI - ILO + 1      NZ = IHIZ - ILOZ + 1**     Set machine-dependent constants for the stopping criterion.*     If norm(H) <= sqrt(OVFL), overflow should not occur.*      ULP = DLAMCH( 'Precision' )      SMLNUM = DLAMCH( 'Safe minimum' ) / ULP**     I1 and I2 are the indices of the first row and last column of H*     to which transformations must be applied. If eigenvalues only are*     being computed, I1 and I2 are set inside the main loop.*      IF( WANTT ) THEN         I1 = 1         I2 = N      END IF**     ITN is the total number of QR iterations allowed.*      ITN = 30*NH**     The main loop begins here. I is the loop index and decreases from*     IHI to ILO in steps of 1. Each iteration of the loop works*     with the active submatrix in rows and columns L to I.*     Eigenvalues I+1 to IHI have already converged. Either L = ILO, or*     H(L,L-1) is negligible so that the matrix splits.*      I = IHI   10 CONTINUE      IF( I.LT.ILO )     $   GO TO 130**     Perform QR iterations on rows and columns ILO to I until a*     submatrix of order 1 splits off at the bottom because a*     subdiagonal element has become negligible.*      L = ILO      DO 110 ITS = 0, ITN**        Look for a single small subdiagonal element.*         DO 20 K = I, L + 1, -1            TST1 = CABS1( H( K-1, K-1 ) ) + CABS1( H( K, K ) )            IF( TST1.EQ.RZERO ) THEN               TST1 = ZLANHS( '1', I-L+1, H( L, L ), LDH, RWORK )****              Increment op count               OPS = OPS + 5*( I-L+1 )*( I-L ) / 2***            END IF            IF( ABS( DBLE( H( K, K-1 ) ) ).LE.MAX( ULP*TST1, SMLNUM ) )     $         GO TO 30   20    CONTINUE   30    CONTINUE         L = K****        Increment op count         OPST = OPST + 5*( I-L+1 )***         IF( L.GT.ILO ) THEN**           H(L,L-1) is negligible*            H( L, L-1 ) = ZERO         END IF**        Exit from loop if a submatrix of order 1 has split off.*         IF( L.GE.I )     $      GO TO 120**        Now the active submatrix is in rows and columns L to I. If*        eigenvalues only are being computed, only the active submatrix*        need be transformed.*         IF( .NOT.WANTT ) THEN            I1 = L            I2 = I         END IF*         IF( ITS.EQ.10 .OR. ITS.EQ.20 ) THEN**           Exceptional shift.*            S = DAT1*ABS( DBLE( H( I, I-1 ) ) )            T = S + H( I, I )****           Increment op count            OPST = OPST + 1***         ELSE**           Wilkinson's shift.*            T = H( I, I )            U = H( I-1, I )*DBLE( H( I, I-1 ) )****           Increment op count            OPST = OPST + 2***            IF( U.NE.ZERO ) THEN               X = HALF*( H( I-1, I-1 )-T )               Y = SQRT( X*X+U )               IF( DBLE( X )*DBLE( Y )+DIMAG( X )*DIMAG( Y ).LT.RZERO )     $            Y = -Y               T = T - ZLADIV( U, ( X+Y ) )****              Increment op count               OPST = OPST + 20***            END IF         END IF**        Look for two consecutive small subdiagonal elements.*         DO 40 M = I - 1, L + 1, -1**           Determine the effect of starting the single-shift QR*           iteration at row M, and see if this would make H(M,M-1)*           negligible.*            H11 = H( M, M )            H22 = H( M+1, M+1 )            H11S = H11 - T            H21 = H( M+1, M )            S = CABS1( H11S ) + ABS( H21 )            H11S = H11S / S            H21 = H21 / S            V( 1 ) = H11S            V( 2 ) = H21            H10 = H( M, M-1 )            TST1 = CABS1( H11S )*( CABS1( H11 )+CABS1( H22 ) )            IF( ABS( H10*H21 ).LE.ULP*TST1 )     $         GO TO 50   40    CONTINUE         H11 = H( L, L )         H22 = H( L+1, L+1 )         H11S = H11 - T         H21 = H( L+1, L )         S = CABS1( H11S ) + ABS( H21 )         H11S = H11S / S         H21 = H21 / S         V( 1 ) = H11S         V( 2 ) = H21   50    CONTINUE****        Increment op count         OPST = OPST + 14*( I-M )*****        Single-shift QR step*         DO 100 K = M, I - 1**           The first iteration of this loop determines a reflection G*           from the vector V and applies it from left and right to H,*           thus creating a nonzero bulge below the subdiagonal.**           Each subsequent iteration determines a reflection G to*           restore the Hessenberg form in the (K-1)th column, and thus*           chases the bulge one step toward the bottom of the active*           submatrix.**           V(2) is always real before the call to ZLARFG, and hence*           after the call T2 ( = T1*V(2) ) is also real.*            IF( K.GT.M )     $         CALL ZCOPY( 2, H( K, K-1 ), 1, V, 1 )            CALL ZLARFG( 2, V( 1 ), V( 2 ), 1, T1 )****           Increment op count            OPST = OPST + 38***            IF( K.GT.M ) THEN               H( K, K-1 ) = V( 1 )               H( K+1, K-1 ) = ZERO            END IF            V2 = V( 2 )            T2 = DBLE( T1*V2 )**           Apply G from the left to transform the rows of the matrix*           in columns K to I2.*            DO 60 J = K, I2               SUM = DCONJG( T1 )*H( K, J ) + T2*H( K+1, J )               H( K, J ) = H( K, J ) - SUM               H( K+1, J ) = H( K+1, J ) - SUM*V2   60       CONTINUE**           Apply G from the right to transform the columns of the*           matrix in rows I1 to min(K+2,I).*            DO 70 J = I1, MIN( K+2, I )               SUM = T1*H( J, K ) + T2*H( J, K+1 )               H( J, K ) = H( J, K ) - SUM               H( J, K+1 ) = H( J, K+1 ) - SUM*DCONJG( V2 )   70       CONTINUE****           Increment op count            OPS = OPS + 20*( I2-I1+2+MIN( 2, I-K ) )****            IF( WANTZ ) THEN**              Accumulate transformations in the matrix Z*               DO 80 J = ILOZ, IHIZ                  SUM = T1*Z( J, K ) + T2*Z( J, K+1 )                  Z( J, K ) = Z( J, K ) - SUM                  Z( J, K+1 ) = Z( J, K+1 ) - SUM*DCONJG( V2 )   80          CONTINUE****              Increment op count               OPS = OPS + 20*NZ***            END IF*            IF( K.EQ.M .AND. M.GT.L ) THEN**              If the QR step was started at row M > L because two*              consecutive small subdiagonals were found, then extra*              scaling must be performed to ensure that H(M,M-1) remains*              real.*               TEMP = ONE - T1               TEMP = TEMP / ABS( TEMP )               H( M+1, M ) = H( M+1, M )*DCONJG( TEMP )               IF( M+2.LE.I )     $            H( M+2, M+1 ) = H( M+2, M+1 )*TEMP               DO 90 J = M, I                  IF( J.NE.M+1 ) THEN                     IF( I2.GT.J )     $                  CALL ZSCAL( I2-J, TEMP, H( J, J+1 ), LDH )                     CALL ZSCAL( J-I1, DCONJG( TEMP ), H( I1, J ), 1 )****                    Increment op count                     OPST = OPST + 6*( I2-I1+3 )***                     IF( WANTZ ) THEN                        CALL ZSCAL( NZ, DCONJG( TEMP ), Z( ILOZ, J ),     $                              1 )****                       Increment op count                        OPST = OPST + 6*NZ***                     END IF                  END IF   90          CONTINUE            END IF  100    CONTINUE**        Ensure that H(I,I-1) is real.*         TEMP = H( I, I-1 )         IF( DIMAG( TEMP ).NE.RZERO ) THEN            RTEMP = ABS( TEMP )            H( I, I-1 ) = RTEMP            TEMP = TEMP / RTEMP            IF( I2.GT.I )     $         CALL ZSCAL( I2-I, DCONJG( TEMP ), H( I, I+1 ), LDH )            CALL ZSCAL( I-I1, TEMP, H( I1, I ), 1 )****           Increment op count            OPST = OPST + 6*( I2-I1+1 )***            IF( WANTZ ) THEN               CALL ZSCAL( NZ, TEMP, Z( ILOZ, I ), 1 )****              Increment op count               OPST = OPST + 6*NZ***            END IF         END IF*  110 CONTINUE**     Failure to converge in remaining number of iterations*      INFO = I      RETURN*  120 CONTINUE**     H(I,I-1) is negligible: one eigenvalue has converged.*      W( I ) = H( I, I )**     Decrement number of remaining iterations, and return to start of*     the main loop with new value of I.*      ITN = ITN - ITS      I = L - 1      GO TO 10*  130 CONTINUE****     Compute final op count      OPS = OPS + OPST***      RETURN**     End of ZLAHQR*      END

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -