📄 chgeqz.f
字号:
END IF** General case: j<ILAST* DO 40 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( ABS1( A( J, J-1 ) ).LE.ATOL ) THEN A( J, J-1 ) = CZERO 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 ) = CZERO** Test 1a: Check for 2 consecutive small subdiagonals in A* ILAZR2 = .FALSE. IF( .NOT.ILAZRO ) THEN IF( ABS1( A( J, J-1 ) )*( ASCALE*ABS1( A( J+1, $ J ) ) ).LE.ABS1( A( J, J ) )*( 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 20 JCH = J, ILAST - 1 CTEMP = A( JCH, JCH ) CALL CLARTG( CTEMP, A( JCH+1, JCH ), C, S, $ A( JCH, JCH ) ) A( JCH+1, JCH ) = CZERO CALL CROT( ILASTM-JCH, A( JCH, JCH+1 ), LDA, $ A( JCH+1, JCH+1 ), LDA, C, S ) CALL CROT( ILASTM-JCH, B( JCH, JCH+1 ), LDB, $ B( JCH+1, JCH+1 ), LDB, C, S ) IF( ILQ ) $ CALL CROT( N, Q( 1, JCH ), 1, Q( 1, JCH+1 ), 1, $ C, CONJG( S ) ) IF( ILAZR2 ) $ A( JCH, JCH-1 ) = A( JCH, JCH-1 )*C ILAZR2 = .FALSE.* --------------- Begin Timing Code ----------------- OPST = OPST + REAL( 32+40*( ILASTM-JCH )+20*NQ )* ---------------- End Timing Code ------------------ IF( ABS1( B( JCH+1, JCH+1 ) ).GE.BTOL ) THEN IF( JCH+1.GE.ILAST ) THEN GO TO 60 ELSE IFIRST = JCH + 1 GO TO 70 END IF END IF B( JCH+1, JCH+1 ) = CZERO 20 CONTINUE GO TO 50 ELSE** Only test 2 passed -- chase the zero to B(ILAST,ILAST)* Then process as in the case B(ILAST,ILAST)=0* DO 30 JCH = J, ILAST - 1 CTEMP = B( JCH, JCH+1 ) CALL CLARTG( CTEMP, B( JCH+1, JCH+1 ), C, S, $ B( JCH, JCH+1 ) ) B( JCH+1, JCH+1 ) = CZERO IF( JCH.LT.ILASTM-1 ) $ CALL CROT( ILASTM-JCH-1, B( JCH, JCH+2 ), LDB, $ B( JCH+1, JCH+2 ), LDB, C, S ) CALL CROT( ILASTM-JCH+2, A( JCH, JCH-1 ), LDA, $ A( JCH+1, JCH-1 ), LDA, C, S ) IF( ILQ ) $ CALL CROT( N, Q( 1, JCH ), 1, Q( 1, JCH+1 ), 1, $ C, CONJG( S ) ) CTEMP = A( JCH+1, JCH ) CALL CLARTG( CTEMP, A( JCH+1, JCH-1 ), C, S, $ A( JCH+1, JCH ) ) A( JCH+1, JCH-1 ) = CZERO CALL CROT( JCH+1-IFRSTM, A( IFRSTM, JCH ), 1, $ A( IFRSTM, JCH-1 ), 1, C, S ) CALL CROT( JCH-IFRSTM, B( IFRSTM, JCH ), 1, $ B( IFRSTM, JCH-1 ), 1, C, S ) IF( ILZ ) $ CALL CROT( N, Z( 1, JCH ), 1, Z( 1, JCH-1 ), 1, $ C, S ) 30 CONTINUE** ---------------- Begin Timing Code ------------------- OPST = OPST + REAL( 64+40*( ILASTM+1-IFRSTM )+20* $ ( NQ+NZ ) )*REAL( ILAST-J )* ----------------- End Timing Code --------------------* GO TO 50 END IF ELSE IF( ILAZRO ) THEN** Only test 1 passed -- work on J:ILAST* IFIRST = J GO TO 70 END IF** Neither test passed -- try next J* 40 CONTINUE** (Drop-through is "impossible")* INFO = 2*N + 1 GO TO 210** B(ILAST,ILAST)=0 -- clear A(ILAST,ILAST-1) to split off a* 1x1 block.* 50 CONTINUE CTEMP = A( ILAST, ILAST ) CALL CLARTG( CTEMP, A( ILAST, ILAST-1 ), C, S, $ A( ILAST, ILAST ) ) A( ILAST, ILAST-1 ) = CZERO CALL CROT( ILAST-IFRSTM, A( IFRSTM, ILAST ), 1, $ A( IFRSTM, ILAST-1 ), 1, C, S ) CALL CROT( ILAST-IFRSTM, B( IFRSTM, ILAST ), 1, $ B( IFRSTM, ILAST-1 ), 1, C, S ) IF( ILZ ) $ CALL CROT( N, Z( 1, ILAST ), 1, Z( 1, ILAST-1 ), 1, C, S )* --------------------- Begin Timing Code ----------------------- OPST = OPST + REAL( 32+40*( ILAST-IFRSTM )+20*NZ )* ---------------------- End Timing Code ------------------------** A(ILAST,ILAST-1)=0 -- Standardize B, set ALPHA and BETA* 60 CONTINUE ABSB = ABS( B( ILAST, ILAST ) ) IF( ABSB.GT.SAFMIN ) THEN SIGNBC = CONJG( B( ILAST, ILAST ) / ABSB ) B( ILAST, ILAST ) = ABSB IF( ILSCHR ) THEN CALL CSCAL( ILAST-IFRSTM, SIGNBC, B( IFRSTM, ILAST ), 1 ) CALL CSCAL( ILAST+1-IFRSTM, SIGNBC, A( IFRSTM, ILAST ), $ 1 )* ----------------- Begin Timing Code --------------------- OPST = OPST + REAL( 12*( ILAST-IFRSTM ) )* ------------------ End Timing Code ---------------------- ELSE A( ILAST, ILAST ) = A( ILAST, ILAST )*SIGNBC END IF IF( ILZ ) $ CALL CSCAL( N, SIGNBC, Z( 1, ILAST ), 1 )* ------------------- Begin Timing Code ---------------------- OPST = OPST + REAL( 6*NZ+13 )* -------------------- End Timing Code ----------------------- ELSE B( ILAST, ILAST ) = CZERO END IF ALPHA( ILAST ) = A( ILAST, ILAST ) BETA( ILAST ) = B( ILAST, ILAST )** Go to next block -- exit if finished.* ILAST = ILAST - 1 IF( ILAST.LT.ILO ) $ GO TO 190** Reset counters* IITER = 0 ESHIFT = CZERO IF( .NOT.ILSCHR ) THEN ILASTM = ILAST IF( IFRSTM.GT.ILAST ) $ IFRSTM = ILO END IF GO TO 160** QZ step** This iteration only involves rows/columns IFIRST:ILAST. We* assume IFIRST < ILAST, and that the diagonal of B is non-zero.* 70 CONTINUE IITER = IITER + 1 IF( .NOT.ILSCHR ) THEN IFRSTM = IFIRST END IF** Compute the Shift.** 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.NE.IITER ) THEN** The Wilkinson shift (AEP p.512), i.e., the eigenvalue of* the bottom-right 2x2 block of A inv(B) which is nearest to* the bottom-right element.** We factor B as U*D, where U has unit diagonals, and* compute (A*inv(D))*inv(U).* U12 = ( BSCALE*B( ILAST-1, ILAST ) ) / $ ( BSCALE*B( ILAST, ILAST ) ) AD11 = ( ASCALE*A( ILAST-1, ILAST-1 ) ) / $ ( BSCALE*B( ILAST-1, ILAST-1 ) ) AD21 = ( ASCALE*A( ILAST, ILAST-1 ) ) / $ ( BSCALE*B( ILAST-1, ILAST-1 ) ) AD12 = ( ASCALE*A( ILAST-1, ILAST ) ) / $ ( BSCALE*B( ILAST, ILAST ) ) AD22 = ( ASCALE*A( ILAST, ILAST ) ) / $ ( BSCALE*B( ILAST, ILAST ) ) ABI22 = AD22 - U12*AD21* T = HALF*( AD11+ABI22 ) RTDISC = SQRT( T**2+AD12*AD21-AD11*AD22 ) TEMP = REAL( T-ABI22 )*REAL( RTDISC ) + $ AIMAG( T-ABI22 )*AIMAG( RTDISC ) IF( TEMP.LE.ZERO ) THEN SHIFT = T + RTDISC ELSE SHIFT = T - RTDISC END IF** ------------------- Begin Timing Code ---------------------- OPST = OPST + REAL( 116 )* -------------------- End Timing Code -----------------------* ELSE** Exceptional shift. Chosen for no particularly good reason.* ESHIFT = ESHIFT + CONJG( ( ASCALE*A( ILAST-1, ILAST ) ) / $ ( BSCALE*B( ILAST-1, ILAST-1 ) ) ) SHIFT = ESHIFT** ------------------- Begin Timing Code ---------------------- OPST = OPST + REAL( 15 )* -------------------- End Timing Code -----------------------* END IF** Now check for two consecutive small subdiagonals.* DO 80 J = ILAST - 1, IFIRST + 1, -1 ISTART = J CTEMP = ASCALE*A( J, J ) - SHIFT*( BSCALE*B( J, J ) ) TEMP = ABS1( CTEMP ) TEMP2 = ASCALE*ABS1( A( J+1, J ) ) TEMPR = MAX( TEMP, TEMP2 ) IF( TEMPR.LT.ONE .AND. TEMPR.NE.ZERO ) THEN TEMP = TEMP / TEMPR TEMP2 = TEMP2 / TEMPR END IF IF( ABS1( A( J, J-1 ) )*TEMP2.LE.TEMP*ATOL ) $ GO TO 90 80 CONTINUE* ISTART = IFIRST CTEMP = ASCALE*A( IFIRST, IFIRST ) - $ SHIFT*( BSCALE*B( IFIRST, IFIRST ) )** --------------------- Begin Timing Code ----------------------- OPST = OPST - REAL( 6 )* ---------------------- End Timing Code ------------------------* 90 CONTINUE** Do an implicit-shift QZ sweep.** Initial Q* CTEMP2 = ASCALE*A( ISTART+1, ISTART )** --------------------- Begin Timing Code ----------------------- OPST = OPST + REAL( 2+( ILAST-ISTART )*18 )* ---------------------- End Timing Code ------------------------* CALL CLARTG( CTEMP, CTEMP2, C, S, CTEMP3 )** Sweep* DO 150 J = ISTART, ILAST - 1 IF( J.GT.ISTART ) THEN CTEMP = A( J, J-1 ) CALL CLARTG( CTEMP, A( J+1, J-1 ), C, S, A( J, J-1 ) ) A( J+1, J-1 ) = CZERO END IF* DO 100 JC = J, ILASTM CTEMP = C*A( J, JC ) + S*A( J+1, JC ) A( J+1, JC ) = -CONJG( S )*A( J, JC ) + C*A( J+1, JC ) A( J, JC ) = CTEMP CTEMP2 = C*B( J, JC ) + S*B( J+1, JC ) B( J+1, JC ) = -CONJG( S )*B( J, JC ) + C*B( J+1, JC ) B( J, JC ) = CTEMP2 100 CONTINUE IF( ILQ ) THEN DO 110 JR = 1, N CTEMP = C*Q( JR, J ) + CONJG( S )*Q( JR, J+1 ) Q( JR, J+1 ) = -S*Q( JR, J ) + C*Q( JR, J+1 ) Q( JR, J ) = CTEMP 110 CONTINUE END IF* CTEMP = B( J+1, J+1 ) CALL CLARTG( CTEMP, B( J+1, J ), C, S, B( J+1, J+1 ) ) B( J+1, J ) = CZERO* DO 120 JR = IFRSTM, MIN( J+2, ILAST ) CTEMP = C*A( JR, J+1 ) + S*A( JR, J ) A( JR, J ) = -CONJG( S )*A( JR, J+1 ) + C*A( JR, J ) A( JR, J+1 ) = CTEMP 120 CONTINUE DO 130 JR = IFRSTM, J CTEMP = C*B( JR, J+1 ) + S*B( JR, J ) B( JR, J ) = -CONJG( S )*B( JR, J+1 ) + C*B( JR, J ) B( JR, J+1 ) = CTEMP 130 CONTINUE IF( ILZ ) THEN DO 140 JR = 1, N CTEMP = C*Z( JR, J+1 ) + S*Z( JR, J ) Z( JR, J ) = -CONJG( S )*Z( JR, J+1 ) + C*Z( JR, J ) Z( JR, J+1 ) = CTEMP 140 CONTINUE END IF 150 CONTINUE** --------------------- Begin Timing Code ----------------------- OPST = OPST + ( REAL( ILAST-ISTART )* $ REAL( 120+64+40*( ILASTM-IFRSTM )+20*( NQ+NZ ) )-20 )* ---------------------- End Timing Code ------------------------* 160 CONTINUE** --------------------- Begin Timing Code -----------------------* End of iteration -- add in "small" contributions. OPS = OPS + OPST OPST = ZERO* ---------------------- End Timing Code ------------------------** 170 CONTINUE** Drop-through = non-convergence* 180 CONTINUE INFO = ILAST** ---------------------- Begin Timing Code ------------------------- OPS = OPS + OPST OPST = ZERO* ----------------------- End Timing Code --------------------------* GO TO 210** Successful completion of all QZ steps* 190 CONTINUE** Set Eigenvalues 1:ILO-1* DO 200 J = 1, ILO - 1 ABSB = ABS( B( J, J ) ) IF( ABSB.GT.SAFMIN ) THEN SIGNBC = CONJG( B( J, J ) / ABSB ) B( J, J ) = ABSB IF( ILSCHR ) THEN CALL CSCAL( J-1, SIGNBC, B( 1, J ), 1 ) CALL CSCAL( J, SIGNBC, A( 1, J ), 1 )* ----------------- Begin Timing Code --------------------- OPST = OPST + REAL( 12*( J-1 ) )* ------------------ End Timing Code ---------------------- ELSE A( J, J ) = A( J, J )*SIGNBC END IF IF( ILZ ) $ CALL CSCAL( N, SIGNBC, Z( 1, J ), 1 )* ------------------- Begin Timing Code ---------------------- OPST = OPST + REAL( 6*NZ+13 )* -------------------- End Timing Code ----------------------- ELSE B( J, J ) = CZERO END IF ALPHA( J ) = A( J, J ) BETA( J ) = B( J, J ) 200 CONTINUE** Normal Termination* INFO = 0** Exit (other than argument error) -- return optimal workspace size* 210 CONTINUE** ---------------------- Begin Timing Code ------------------------- OPS = OPS + OPST OPST = ZERO ITCNT = JITER* ----------------------- End Timing Code --------------------------* WORK( 1 ) = CMPLX( N ) RETURN** End of CHGEQZ* END
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -