📄 dhseqr.f
字号:
** ITN is the total number of multiple-shift 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 at most MAXB. 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 50 CONTINUE L = ILO IF( I.LT.ILO ) $ GO TO 170** Perform multiple-shift QR iterations on rows and columns ILO to I* until a submatrix of order at most MAXB splits off at the bottom* because a subdiagonal element has become negligible.* DO 150 ITS = 0, ITN** Look for a single small subdiagonal element.* DO 60 K = I, L + 1, -1 TST1 = ABS( H( K-1, K-1 ) ) + ABS( H( K, K ) ) IF( TST1.EQ.ZERO ) THEN TST1 = DLANHS( '1', I-L+1, H( L, L ), LDH, WORK )**** Increment op count OPS = OPS + ( I-L+1 )*( I-L+2 ) / 2*** END IF IF( ABS( H( K, K-1 ) ).LE.MAX( ULP*TST1, SMLNUM ) ) $ GO TO 70 60 CONTINUE 70 CONTINUE L = K**** Increment op count OPST = OPST + 3*( 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 <= MAXB has split off.* IF( L.GE.I-MAXB+1 ) $ GO TO 160** 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.20 .OR. ITS.EQ.30 ) THEN** Exceptional shifts.* DO 80 II = I - NS + 1, I WR( II ) = CONST*( ABS( H( II, II-1 ) )+ $ ABS( H( II, II ) ) ) WI( II ) = ZERO 80 CONTINUE**** Increment op count OPST = OPST + 2*NS*** ELSE** Use eigenvalues of trailing submatrix of order NS as shifts.* CALL DLACPY( 'Full', NS, NS, H( I-NS+1, I-NS+1 ), LDH, S, $ LDS ) CALL DLAHQR( .FALSE., .FALSE., NS, 1, NS, S, LDS, $ WR( I-NS+1 ), WI( I-NS+1 ), 1, NS, Z, LDZ, $ IERR ) IF( IERR.GT.0 ) THEN** If DLAHQR failed to compute all NS eigenvalues, use the* unconverged diagonal elements as the remaining shifts.* DO 90 II = 1, IERR WR( I-NS+II ) = S( II, II ) WI( I-NS+II ) = ZERO 90 CONTINUE END IF END IF** Form the first column of (G-w(1)) (G-w(2)) . . . (G-w(ns))* where G is the Hessenberg submatrix H(L:I,L:I) and w is* the vector of shifts (stored in WR and WI). The result is* stored in the local array V.* V( 1 ) = ONE DO 100 II = 2, NS + 1 V( II ) = ZERO 100 CONTINUE NV = 1 DO 120 J = I - NS + 1, I IF( WI( J ).GE.ZERO ) THEN IF( WI( J ).EQ.ZERO ) THEN** real shift* CALL DCOPY( NV+1, V, 1, VV, 1 ) CALL DGEMV( 'No transpose', NV+1, NV, ONE, H( L, L ), $ LDH, VV, 1, -WR( J ), V, 1 ) NV = NV + 1**** Increment op count OPST = OPST + 2*NV*( NV+1 ) + NV + 1*** ELSE IF( WI( J ).GT.ZERO ) THEN** complex conjugate pair of shifts* CALL DCOPY( NV+1, V, 1, VV, 1 ) CALL DGEMV( 'No transpose', NV+1, NV, ONE, H( L, L ), $ LDH, V, 1, -TWO*WR( J ), VV, 1 ) ITEMP = IDAMAX( NV+1, VV, 1 ) TEMP = ONE / MAX( ABS( VV( ITEMP ) ), SMLNUM ) CALL DSCAL( NV+1, TEMP, VV, 1 ) ABSW = DLAPY2( WR( J ), WI( J ) ) TEMP = ( TEMP*ABSW )*ABSW CALL DGEMV( 'No transpose', NV+2, NV+1, ONE, $ H( L, L ), LDH, VV, 1, TEMP, V, 1 ) NV = NV + 2**** Increment op count OPST = OPST + 4*( NV+1 )**2 + 4*NV + 9*** END IF** Scale V(1:NV) so that max(abs(V(i))) = 1. If V is zero,* reset it to the unit vector.* ITEMP = IDAMAX( NV, V, 1 )**** Increment op count OPST = OPST + NV*** TEMP = ABS( V( ITEMP ) ) IF( TEMP.EQ.ZERO ) THEN V( 1 ) = ONE DO 110 II = 2, NV V( II ) = ZERO 110 CONTINUE ELSE TEMP = MAX( TEMP, SMLNUM ) CALL DSCAL( NV, ONE / TEMP, V, 1 )**** Increment op count OPST = OPST + NV*** END IF END IF 120 CONTINUE** Multiple-shift QR step* DO 140 K = L, 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. NR is the order of G.* NR = MIN( NS+1, I-K+1 ) IF( K.GT.L ) $ CALL DCOPY( NR, H( K, K-1 ), 1, V, 1 ) CALL DLARFG( NR, V( 1 ), V( 2 ), 1, TAU )**** Increment op count OPST = OPST + 3*NR + 9*** IF( K.GT.L ) THEN H( K, K-1 ) = V( 1 ) DO 130 II = K + 1, I H( II, K-1 ) = ZERO 130 CONTINUE END IF V( 1 ) = ONE** Apply G from the left to transform the rows of the matrix in* columns K to I2.* CALL DLARFX( 'Left', NR, I2-K+1, V, TAU, H( K, K ), LDH, $ WORK )** Apply G from the right to transform the columns of the* matrix in rows I1 to min(K+NR,I).* CALL DLARFX( 'Right', MIN( K+NR, I )-I1+1, NR, V, TAU, $ H( I1, K ), LDH, WORK )**** Increment op count OPS = OPS + ( 4*NR-2 )*( I2-I1+2+MIN( NR, I-K ) )**** IF( WANTZ ) THEN** Accumulate transformations in the matrix Z* CALL DLARFX( 'Right', NH, NR, V, TAU, Z( ILO, K ), LDZ, $ WORK )**** Increment op count OPS = OPS + ( 4*NR-2 )*NH*** END IF 140 CONTINUE* 150 CONTINUE** Failure to converge in remaining number of iterations* INFO = I RETURN* 160 CONTINUE** A submatrix of order <= MAXB in rows and columns L to I has split* off. Use the double-shift QR algorithm to handle it.* CALL DLAHQR( WANTT, WANTZ, N, L, I, H, LDH, WR, WI, ILO, IHI, Z, $ LDZ, INFO ) IF( INFO.GT.0 ) $ RETURN** Decrement number of remaining iterations, and return to start of* the main loop with a new value of I.* ITN = ITN - ITS I = L - 1 GO TO 50* 170 CONTINUE**** Compute final op count OPS = OPS + OPST*** WORK( 1 ) = MAX( 1, N ) RETURN** End of DHSEQR* END
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -