📄 shgeqz.f
字号:
RETURN ELSE IF( LQUERY ) THEN RETURN END IF** Quick return if possible* IF( N.LE.0 ) THEN WORK( 1 ) = REAL( 1 )* --------------------- Begin Timing Code ----------------------- ITCNT = ZERO* ---------------------- End Timing Code ------------------------ RETURN END IF** Initialize Q and Z* IF( ICOMPQ.EQ.3 ) $ CALL SLASET( 'Full', N, N, ZERO, ONE, Q, LDQ ) IF( ICOMPZ.EQ.3 ) $ CALL SLASET( 'Full', N, N, ZERO, ONE, Z, LDZ )** Machine Constants* IN = IHI + 1 - ILO SAFMIN = SLAMCH( 'S' ) SAFMAX = ONE / SAFMIN ULP = SLAMCH( 'E' )*SLAMCH( 'B' ) ANORM = SLANHS( 'F', IN, A( ILO, ILO ), LDA, WORK ) BNORM = SLANHS( 'F', IN, B( ILO, ILO ), LDB, WORK ) ATOL = MAX( SAFMIN, ULP*ANORM ) BTOL = MAX( SAFMIN, ULP*BNORM ) ASCALE = ONE / MAX( SAFMIN, ANORM ) BSCALE = ONE / MAX( SAFMIN, BNORM )** Set Eigenvalues IHI+1:N* DO 30 J = IHI + 1, N IF( B( J, J ).LT.ZERO ) THEN IF( ILSCHR ) THEN DO 10 JR = 1, J A( JR, J ) = -A( JR, J ) B( JR, J ) = -B( JR, J ) 10 CONTINUE ELSE A( J, J ) = -A( J, J ) B( J, J ) = -B( J, J ) END IF IF( ILZ ) THEN DO 20 JR = 1, N Z( JR, J ) = -Z( JR, J ) 20 CONTINUE END IF END IF ALPHAR( J ) = A( J, J ) ALPHAI( J ) = ZERO BETA( J ) = B( J, J ) 30 CONTINUE** ---------------------- Begin Timing Code -------------------------* Count ops for norms, etc. OPST = ZERO OPS = OPS + REAL( 2*N**2+6*N )* ----------------------- End Timing Code --------------------------*** If IHI < ILO, skip QZ steps* IF( IHI.LT.ILO ) $ GO TO 380** MAIN QZ ITERATION LOOP** Initialize dynamic indices** Eigenvalues ILAST+1:N have been found.* Column operations modify rows IFRSTM:whatever.* Row operations modify columns whatever:ILASTM.** If only eigenvalues are being computed, then* IFRSTM is the row of the last splitting row above row ILAST;* this is always at least ILO.* IITER counts iterations since the last eigenvalue was found,* to tell when to use an extraordinary shift.* MAXIT is the maximum number of QZ sweeps allowed.* ILAST = IHI IF( ILSCHR ) THEN IFRSTM = 1 ILASTM = N ELSE IFRSTM = ILO ILASTM = IHI END IF IITER = 0 ESHIFT = ZERO MAXIT = 30*( IHI-ILO+1 )* DO 360 JITER = 1, MAXIT** Split the matrix if possible.** Two tests:* 1: A(j,j-1)=0 or j=ILO* 2: B(j,j)=0* IF( ILAST.EQ.ILO ) THEN** Special case: j=ILAST* GO TO 80 ELSE IF( ABS( A( ILAST, ILAST-1 ) ).LE.ATOL ) THEN A( ILAST, ILAST-1 ) = ZERO GO TO 80 END IF END IF* IF( ABS( B( ILAST, ILAST ) ).LE.BTOL ) THEN B( ILAST, ILAST ) = ZERO GO TO 70 END IF** General case: j<ILAST* DO 60 J = ILAST - 1, ILO, -1** Test 1: for A(j,j-1)=0 or j=ILO* IF( J.EQ.ILO ) THEN ILAZRO = .TRUE. ELSE IF( ABS( A( J, J-1 ) ).LE.ATOL ) THEN A( J, J-1 ) = ZERO ILAZRO = .TRUE. ELSE ILAZRO = .FALSE. END IF END IF** Test 2: for B(j,j)=0* IF( ABS( B( J, J ) ).LT.BTOL ) THEN B( J, J ) = ZERO** Test 1a: Check for 2 consecutive small subdiagonals in A* ILAZR2 = .FALSE. IF( .NOT.ILAZRO ) THEN TEMP = ABS( A( J, J-1 ) ) TEMP2 = ABS( A( 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( A( 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 = A( JCH, JCH ) CALL SLARTG( TEMP, A( JCH+1, JCH ), C, S, $ A( JCH, JCH ) ) A( JCH+1, JCH ) = ZERO CALL SROT( ILASTM-JCH, A( JCH, JCH+1 ), LDA, $ A( JCH+1, JCH+1 ), LDA, C, S ) CALL SROT( ILASTM-JCH, B( JCH, JCH+1 ), LDB, $ B( JCH+1, JCH+1 ), LDB, C, S ) IF( ILQ ) $ CALL SROT( N, Q( 1, JCH ), 1, Q( 1, JCH+1 ), 1, $ C, S ) IF( ILAZR2 ) $ A( JCH, JCH-1 ) = A( JCH, JCH-1 )*C ILAZR2 = .FALSE.** --------------- Begin Timing Code ----------------- OPST = OPST + REAL( 7+12*( ILASTM-JCH )+6*NQ )* ---------------- End Timing Code ------------------* IF( ABS( B( 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 B( JCH+1, JCH+1 ) = ZERO 40 CONTINUE GO TO 70 ELSE** Only test 2 passed -- chase the zero to B(ILAST,ILAST)* Then process as in the case B(ILAST,ILAST)=0* DO 50 JCH = J, ILAST - 1 TEMP = B( JCH, JCH+1 ) CALL SLARTG( TEMP, B( JCH+1, JCH+1 ), C, S, $ B( JCH, JCH+1 ) ) B( JCH+1, JCH+1 ) = ZERO IF( JCH.LT.ILASTM-1 ) $ CALL SROT( ILASTM-JCH-1, B( JCH, JCH+2 ), LDB, $ B( JCH+1, JCH+2 ), LDB, C, S ) CALL SROT( ILASTM-JCH+2, A( JCH, JCH-1 ), LDA, $ A( JCH+1, JCH-1 ), LDA, C, S ) IF( ILQ ) $ CALL SROT( N, Q( 1, JCH ), 1, Q( 1, JCH+1 ), 1, $ C, S ) TEMP = A( JCH+1, JCH ) CALL SLARTG( TEMP, A( JCH+1, JCH-1 ), C, S, $ A( JCH+1, JCH ) ) A( JCH+1, JCH-1 ) = ZERO CALL SROT( JCH+1-IFRSTM, A( IFRSTM, JCH ), 1, $ A( IFRSTM, JCH-1 ), 1, C, S ) CALL SROT( JCH-IFRSTM, B( IFRSTM, JCH ), 1, $ B( IFRSTM, JCH-1 ), 1, C, S ) IF( ILZ ) $ CALL SROT( N, Z( 1, JCH ), 1, Z( 1, JCH-1 ), 1, $ C, S ) 50 CONTINUE** ---------------- Begin Timing Code ------------------- OPST = OPST + REAL( 26+12*( ILASTM-IFRSTM )+6* $ ( NQ+NZ ) )*REAL( ILAST-J )* ----------------- End Timing Code --------------------* 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** B(ILAST,ILAST)=0 -- clear A(ILAST,ILAST-1) to split off a* 1x1 block.* 70 CONTINUE TEMP = A( ILAST, ILAST ) CALL SLARTG( TEMP, A( ILAST, ILAST-1 ), C, S, $ A( ILAST, ILAST ) ) A( ILAST, ILAST-1 ) = ZERO CALL SROT( ILAST-IFRSTM, A( IFRSTM, ILAST ), 1, $ A( IFRSTM, ILAST-1 ), 1, C, S ) CALL SROT( ILAST-IFRSTM, B( IFRSTM, ILAST ), 1, $ B( IFRSTM, ILAST-1 ), 1, C, S ) IF( ILZ ) $ CALL SROT( N, Z( 1, ILAST ), 1, Z( 1, ILAST-1 ), 1, C, S )** --------------------- Begin Timing Code ----------------------- OPST = OPST + REAL( 7+12*( ILAST-IFRSTM )+6*NZ )* ---------------------- End Timing Code ------------------------*** A(ILAST,ILAST-1)=0 -- Standardize B, set ALPHAR, ALPHAI,* and BETA* 80 CONTINUE IF( B( ILAST, ILAST ).LT.ZERO ) THEN IF( ILSCHR ) THEN DO 90 J = IFRSTM, ILAST A( J, ILAST ) = -A( J, ILAST ) B( J, ILAST ) = -B( J, ILAST ) 90 CONTINUE ELSE A( ILAST, ILAST ) = -A( ILAST, ILAST ) B( ILAST, ILAST ) = -B( 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 ) = A( ILAST, ILAST ) ALPHAI( ILAST ) = ZERO BETA( ILAST ) = B( 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* B(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.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -