📄 shgeqz.f
字号:
*
* Special case: j=ILAST
*
GO TO 80
ELSE
IF( ABS( H( ILAST, ILAST-1 ) ).LE.ATOL ) THEN
H( ILAST, ILAST-1 ) = ZERO
GO TO 80
END IF
END IF
*
IF( ABS( T( ILAST, ILAST ) ).LE.BTOL ) THEN
T( ILAST, ILAST ) = ZERO
GO TO 70
END IF
*
* General case: j<ILAST
*
DO 60 J = ILAST - 1, ILO, -1
*
* Test 1: for H(j,j-1)=0 or j=ILO
*
IF( J.EQ.ILO ) THEN
ILAZRO = .TRUE.
ELSE
IF( ABS( H( J, J-1 ) ).LE.ATOL ) THEN
H( J, J-1 ) = ZERO
ILAZRO = .TRUE.
ELSE
ILAZRO = .FALSE.
END IF
END IF
*
* Test 2: for T(j,j)=0
*
IF( ABS( T( J, J ) ).LT.BTOL ) THEN
T( J, J ) = ZERO
*
* Test 1a: Check for 2 consecutive small subdiagonals in A
*
ILAZR2 = .FALSE.
IF( .NOT.ILAZRO ) THEN
TEMP = ABS( H( J, J-1 ) )
TEMP2 = ABS( H( J, J ) )
TEMPR = MAX( TEMP, TEMP2 )
IF( TEMPR.LT.ONE .AND. TEMPR.NE.ZERO ) THEN
TEMP = TEMP / TEMPR
TEMP2 = TEMP2 / TEMPR
END IF
IF( TEMP*( ASCALE*ABS( H( J+1, J ) ) ).LE.TEMP2*
$ ( ASCALE*ATOL ) )ILAZR2 = .TRUE.
END IF
*
* If both tests pass (1 & 2), i.e., the leading diagonal
* element of B in the block is zero, split a 1x1 block off
* at the top. (I.e., at the J-th row/column) The leading
* diagonal element of the remainder can also be zero, so
* this may have to be done repeatedly.
*
IF( ILAZRO .OR. ILAZR2 ) THEN
DO 40 JCH = J, ILAST - 1
TEMP = H( JCH, JCH )
CALL SLARTG( TEMP, H( JCH+1, JCH ), C, S,
$ H( JCH, JCH ) )
H( JCH+1, JCH ) = ZERO
CALL SROT( ILASTM-JCH, H( JCH, JCH+1 ), LDH,
$ H( JCH+1, JCH+1 ), LDH, C, S )
CALL SROT( ILASTM-JCH, T( JCH, JCH+1 ), LDT,
$ T( JCH+1, JCH+1 ), LDT, C, S )
IF( ILQ )
$ CALL SROT( N, Q( 1, JCH ), 1, Q( 1, JCH+1 ), 1,
$ C, S )
IF( ILAZR2 )
$ H( JCH, JCH-1 ) = H( JCH, JCH-1 )*C
ILAZR2 = .FALSE.
IF( ABS( T( JCH+1, JCH+1 ) ).GE.BTOL ) THEN
IF( JCH+1.GE.ILAST ) THEN
GO TO 80
ELSE
IFIRST = JCH + 1
GO TO 110
END IF
END IF
T( JCH+1, JCH+1 ) = ZERO
40 CONTINUE
GO TO 70
ELSE
*
* Only test 2 passed -- chase the zero to T(ILAST,ILAST)
* Then process as in the case T(ILAST,ILAST)=0
*
DO 50 JCH = J, ILAST - 1
TEMP = T( JCH, JCH+1 )
CALL SLARTG( TEMP, T( JCH+1, JCH+1 ), C, S,
$ T( JCH, JCH+1 ) )
T( JCH+1, JCH+1 ) = ZERO
IF( JCH.LT.ILASTM-1 )
$ CALL SROT( ILASTM-JCH-1, T( JCH, JCH+2 ), LDT,
$ T( JCH+1, JCH+2 ), LDT, C, S )
CALL SROT( ILASTM-JCH+2, H( JCH, JCH-1 ), LDH,
$ H( JCH+1, JCH-1 ), LDH, C, S )
IF( ILQ )
$ CALL SROT( N, Q( 1, JCH ), 1, Q( 1, JCH+1 ), 1,
$ C, S )
TEMP = H( JCH+1, JCH )
CALL SLARTG( TEMP, H( JCH+1, JCH-1 ), C, S,
$ H( JCH+1, JCH ) )
H( JCH+1, JCH-1 ) = ZERO
CALL SROT( JCH+1-IFRSTM, H( IFRSTM, JCH ), 1,
$ H( IFRSTM, JCH-1 ), 1, C, S )
CALL SROT( JCH-IFRSTM, T( IFRSTM, JCH ), 1,
$ T( IFRSTM, JCH-1 ), 1, C, S )
IF( ILZ )
$ CALL SROT( N, Z( 1, JCH ), 1, Z( 1, JCH-1 ), 1,
$ C, S )
50 CONTINUE
GO TO 70
END IF
ELSE IF( ILAZRO ) THEN
*
* Only test 1 passed -- work on J:ILAST
*
IFIRST = J
GO TO 110
END IF
*
* Neither test passed -- try next J
*
60 CONTINUE
*
* (Drop-through is "impossible")
*
INFO = N + 1
GO TO 420
*
* T(ILAST,ILAST)=0 -- clear H(ILAST,ILAST-1) to split off a
* 1x1 block.
*
70 CONTINUE
TEMP = H( ILAST, ILAST )
CALL SLARTG( TEMP, H( ILAST, ILAST-1 ), C, S,
$ H( ILAST, ILAST ) )
H( ILAST, ILAST-1 ) = ZERO
CALL SROT( ILAST-IFRSTM, H( IFRSTM, ILAST ), 1,
$ H( IFRSTM, ILAST-1 ), 1, C, S )
CALL SROT( ILAST-IFRSTM, T( IFRSTM, ILAST ), 1,
$ T( IFRSTM, ILAST-1 ), 1, C, S )
IF( ILZ )
$ CALL SROT( N, Z( 1, ILAST ), 1, Z( 1, ILAST-1 ), 1, C, S )
*
* H(ILAST,ILAST-1)=0 -- Standardize B, set ALPHAR, ALPHAI,
* and BETA
*
80 CONTINUE
IF( T( ILAST, ILAST ).LT.ZERO ) THEN
IF( ILSCHR ) THEN
DO 90 J = IFRSTM, ILAST
H( J, ILAST ) = -H( J, ILAST )
T( J, ILAST ) = -T( J, ILAST )
90 CONTINUE
ELSE
H( ILAST, ILAST ) = -H( ILAST, ILAST )
T( ILAST, ILAST ) = -T( ILAST, ILAST )
END IF
IF( ILZ ) THEN
DO 100 J = 1, N
Z( J, ILAST ) = -Z( J, ILAST )
100 CONTINUE
END IF
END IF
ALPHAR( ILAST ) = H( ILAST, ILAST )
ALPHAI( ILAST ) = ZERO
BETA( ILAST ) = T( ILAST, ILAST )
*
* Go to next block -- exit if finished.
*
ILAST = ILAST - 1
IF( ILAST.LT.ILO )
$ GO TO 380
*
* Reset counters
*
IITER = 0
ESHIFT = ZERO
IF( .NOT.ILSCHR ) THEN
ILASTM = ILAST
IF( IFRSTM.GT.ILAST )
$ IFRSTM = ILO
END IF
GO TO 350
*
* QZ step
*
* This iteration only involves rows/columns IFIRST:ILAST. We
* assume IFIRST < ILAST, and that the diagonal of B is non-zero.
*
110 CONTINUE
IITER = IITER + 1
IF( .NOT.ILSCHR ) THEN
IFRSTM = IFIRST
END IF
*
* Compute single shifts.
*
* At this point, IFIRST < ILAST, and the diagonal elements of
* T(IFIRST:ILAST,IFIRST,ILAST) are larger than BTOL (in
* magnitude)
*
IF( ( IITER / 10 )*10.EQ.IITER ) THEN
*
* Exceptional shift. Chosen for no particularly good reason.
* (Single shift only.)
*
IF( ( REAL( MAXIT )*SAFMIN )*ABS( H( ILAST-1, ILAST ) ).LT.
$ ABS( T( ILAST-1, ILAST-1 ) ) ) THEN
ESHIFT = ESHIFT + H( ILAST-1, ILAST ) /
$ T( ILAST-1, ILAST-1 )
ELSE
ESHIFT = ESHIFT + ONE / ( SAFMIN*REAL( MAXIT ) )
END IF
S1 = ONE
WR = ESHIFT
*
ELSE
*
* Shifts based on the generalized eigenvalues of the
* bottom-right 2x2 block of A and B. The first eigenvalue
* returned by SLAG2 is the Wilkinson shift (AEP p.512),
*
CALL SLAG2( H( ILAST-1, ILAST-1 ), LDH,
$ T( ILAST-1, ILAST-1 ), LDT, SAFMIN*SAFETY, S1,
$ S2, WR, WR2, WI )
*
TEMP = MAX( S1, SAFMIN*MAX( ONE, ABS( WR ), ABS( WI ) ) )
IF( WI.NE.ZERO )
$ GO TO 200
END IF
*
* Fiddle with shift to avoid overflow
*
TEMP = MIN( ASCALE, ONE )*( HALF*SAFMAX )
IF( S1.GT.TEMP ) THEN
SCALE = TEMP / S1
ELSE
SCALE = ONE
END IF
*
TEMP = MIN( BSCALE, ONE )*( HALF*SAFMAX )
IF( ABS( WR ).GT.TEMP )
$ SCALE = MIN( SCALE, TEMP / ABS( WR ) )
S1 = SCALE*S1
WR = SCALE*WR
*
* Now check for two consecutive small subdiagonals.
*
DO 120 J = ILAST - 1, IFIRST + 1, -1
ISTART = J
TEMP = ABS( S1*H( J, J-1 ) )
TEMP2 = ABS( S1*H( J, J )-WR*T( J, J ) )
TEMPR = MAX( TEMP, TEMP2 )
IF( TEMPR.LT.ONE .AND. TEMPR.NE.ZERO ) THEN
TEMP = TEMP / TEMPR
TEMP2 = TEMP2 / TEMPR
END IF
IF( ABS( ( ASCALE*H( J+1, J ) )*TEMP ).LE.( ASCALE*ATOL )*
$ TEMP2 )GO TO 130
120 CONTINUE
*
ISTART = IFIRST
130 CONTINUE
*
* Do an implicit single-shift QZ sweep.
*
* Initial Q
*
TEMP = S1*H( ISTART, ISTART ) - WR*T( ISTART, ISTART )
TEMP2 = S1*H( ISTART+1, ISTART )
CALL SLARTG( TEMP, TEMP2, C, S, TEMPR )
*
* Sweep
*
DO 190 J = ISTART, ILAST - 1
IF( J.GT.ISTART ) THEN
TEMP = H( J, J-1 )
CALL SLARTG( TEMP, H( J+1, J-1 ), C, S, H( J, J-1 ) )
H( J+1, J-1 ) = ZERO
END IF
*
DO 140 JC = J, ILASTM
TEMP = C*H( J, JC ) + S*H( J+1, JC )
H( J+1, JC ) = -S*H( J, JC ) + C*H( J+1, JC )
H( J, JC ) = TEMP
TEMP2 = C*T( J, JC ) + S*T( J+1, JC )
T( J+1, JC ) = -S*T( J, JC ) + C*T( J+1, JC )
T( J, JC ) = TEMP2
140 CONTINUE
IF( ILQ ) THEN
DO 150 JR = 1, N
TEMP = C*Q( JR, J ) + S*Q( JR, J+1 )
Q( JR, J+1 ) = -S*Q( JR, J ) + C*Q( JR, J+1 )
Q( JR, J ) = TEMP
150 CONTINUE
END IF
*
TEMP = T( J+1, J+1 )
CALL SLARTG( TEMP, T( J+1, J ), C, S, T( J+1, J+1 ) )
T( J+1, J ) = ZERO
*
DO 160 JR = IFRSTM, MIN( J+2, ILAST )
TEMP = C*H( JR, J+1 ) + S*H( JR, J )
H( JR, J ) = -S*H( JR, J+1 ) + C*H( JR, J )
H( JR, J+1 ) = TEMP
160 CONTINUE
DO 170 JR = IFRSTM, J
TEMP = C*T( JR, J+1 ) + S*T( JR, J )
T( JR, J ) = -S*T( JR, J+1 ) + C*T( JR, J )
T( JR, J+1 ) = TEMP
170 CONTINUE
IF( ILZ ) THEN
DO 180 JR = 1, N
TEMP = C*Z( JR, J+1 ) + S*Z( JR, J )
Z( JR, J ) = -S*Z( JR, J+1 ) + C*Z( JR, J )
Z( JR, J+1 ) = TEMP
180 CONTINUE
END IF
190 CONTINUE
*
GO TO 350
*
* Use Francis double-shift
*
* Note: the Francis double-shift should work with real shifts,
* but only if the block is at least 3x3.
* This code may break if this point is reached with
* a 2x2 block with real eigenvalues.
*
200 CONTINUE
IF( IFIRST+1.EQ.ILAST ) THEN
*
* Special case -- 2x2 block with complex eigenvectors
*
* Step 1: Standardize, that is, rotate so that
*
* ( B11 0 )
* B = ( ) with B11 non-negative.
* ( 0 B22 )
*
CALL SLASV2( T( ILAST-1, ILAST-1 ), T( ILAST-1, ILAST ),
$ T( ILAST, ILAST ), B22, B11, SR, CR, SL, CL )
*
IF( B11.LT.ZERO ) THEN
CR = -CR
SR = -SR
B11 = -B11
B22 = -B22
END IF
*
CALL SROT( ILASTM+1-IFIRST, H( ILAST-1, ILAST-1 ), LDH,
$ H( ILAST, ILAST-1 ), LDH, CL, SL )
CALL SROT( ILAST+1-IFRSTM, H( IFRSTM, ILAST-1 ), 1,
$ H( IFRSTM, ILAST ), 1, CR, SR )
*
IF( ILAST.LT.ILASTM )
$ CALL SROT( ILASTM-ILAST, T( ILAST-1, ILAST+1 ), LDT,
$ T( ILAST, ILAST+1 ), LDH, CL, SL )
IF( IFRSTM.LT.ILAST-1 )
$ CALL SROT( IFIRST-IFRSTM, T( IFRSTM, ILAST-1 ), 1,
$ T( IFRSTM, ILAST ), 1, CR, SR )
*
IF( ILQ )
$ CALL SROT( N, Q( 1, ILAST-1 ), 1, Q( 1, ILAST ), 1, CL,
$ SL )
IF( ILZ )
$ CALL SROT( N, Z( 1, ILAST-1 ), 1, Z( 1, ILAST ), 1, CR,
$ SR )
*
T( ILAST-1, ILAST-1 ) = B11
T( ILAST-1, ILAST ) = ZERO
T( ILAST, ILAST-1 ) = ZERO
T( ILAST, ILAST ) = B22
*
* If B22 is negative, negate column ILAST
*
IF( B22.LT.ZERO ) THEN
DO 210 J = IFRSTM, ILAST
H( J, ILAST ) = -H( J, ILAST )
T( J, ILAST ) = -T( J, ILAST )
210 CONTINUE
*
IF( ILZ ) THEN
DO 220 J = 1, N
Z( J, ILAST ) = -Z( J, ILAST )
220 CONTINUE
END IF
END IF
*
* Step 2: Compute ALPHAR, ALPHAI, and BETA (see refs.)
*
* Recompute shift
*
CALL SLAG2( H( ILAST-1, ILAST-1 ), LDH,
$ T( ILAST-1, ILAST-1 ), LDT, SAFMIN*SAFETY, S1,
$ TEMP, WR, TEMP2, WI )
*
* If standardization has perturbed the shift onto real line,
* do another (real single-shift) QR step.
*
IF( WI.EQ.ZERO )
$ GO TO 350
S1INV = ONE / S1
*
* Do EISPACK (QZVAL) computation of alpha and beta
*
A11 = H( ILAST-1, ILAST-1 )
A21 = H( ILAST, ILAST-1 )
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -