📄 dhgeqz.f
字号:
* (Single shift only.)* IF( ( DBLE( MAXIT )*SAFMIN )*ABS( A( ILAST-1, ILAST ) ).LT. $ ABS( B( ILAST-1, ILAST-1 ) ) ) THEN ESHIFT = ESHIFT + A( ILAST-1, ILAST ) / $ B( ILAST-1, ILAST-1 ) ELSE ESHIFT = ESHIFT + ONE / ( SAFMIN*DBLE( MAXIT ) ) END IF S1 = ONE WR = ESHIFT** ------------------- Begin Timing Code ---------------------- OPST = OPST + DBLE( 4 )* -------------------- End Timing Code -----------------------* ELSE** Shifts based on the generalized eigenvalues of the* bottom-right 2x2 block of A and B. The first eigenvalue* returned by DLAG2 is the Wilkinson shift (AEP p.512),* CALL DLAG2( A( ILAST-1, ILAST-1 ), LDA, $ B( ILAST-1, ILAST-1 ), LDB, SAFMIN*SAFETY, S1, $ S2, WR, WR2, WI )* TEMP = MAX( S1, SAFMIN*MAX( ONE, ABS( WR ), ABS( WI ) ) )** ------------------- Begin Timing Code ---------------------- OPST = OPST + DBLE( 57 )* -------------------- End Timing Code -----------------------* 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*A( J, J-1 ) ) TEMP2 = ABS( S1*A( J, J )-WR*B( 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*A( 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*A( ISTART, ISTART ) - WR*B( ISTART, ISTART ) TEMP2 = S1*A( ISTART+1, ISTART ) CALL DLARTG( TEMP, TEMP2, C, S, TEMPR )** Sweep* DO 190 J = ISTART, ILAST - 1 IF( J.GT.ISTART ) THEN TEMP = A( J, J-1 ) CALL DLARTG( TEMP, A( J+1, J-1 ), C, S, A( J, J-1 ) ) A( J+1, J-1 ) = ZERO END IF* DO 140 JC = J, ILASTM TEMP = C*A( J, JC ) + S*A( J+1, JC ) A( J+1, JC ) = -S*A( J, JC ) + C*A( J+1, JC ) A( J, JC ) = TEMP TEMP2 = C*B( J, JC ) + S*B( J+1, JC ) B( J+1, JC ) = -S*B( J, JC ) + C*B( J+1, JC ) B( 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 = B( J+1, J+1 ) CALL DLARTG( TEMP, B( J+1, J ), C, S, B( J+1, J+1 ) ) B( J+1, J ) = ZERO* DO 160 JR = IFRSTM, MIN( J+2, ILAST ) TEMP = C*A( JR, J+1 ) + S*A( JR, J ) A( JR, J ) = -S*A( JR, J+1 ) + C*A( JR, J ) A( JR, J+1 ) = TEMP 160 CONTINUE DO 170 JR = IFRSTM, J TEMP = C*B( JR, J+1 ) + S*B( JR, J ) B( JR, J ) = -S*B( JR, J+1 ) + C*B( JR, J ) B( 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** --------------------- Begin Timing Code ----------------------- OPST = OPST + DBLE( 6+( ILAST-ISTART )* $ ( 8+14+36+12*( ILASTM-IFRSTM )+6*( NQ+NZ ) ) )* ---------------------- End Timing Code ------------------------* 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 DLASV2( B( ILAST-1, ILAST-1 ), B( ILAST-1, ILAST ), $ B( ILAST, ILAST ), B22, B11, SR, CR, SL, CL )* IF( B11.LT.ZERO ) THEN CR = -CR SR = -SR B11 = -B11 B22 = -B22 END IF* CALL DROT( ILASTM+1-IFIRST, A( ILAST-1, ILAST-1 ), LDA, $ A( ILAST, ILAST-1 ), LDA, CL, SL ) CALL DROT( ILAST+1-IFRSTM, A( IFRSTM, ILAST-1 ), 1, $ A( IFRSTM, ILAST ), 1, CR, SR )* IF( ILAST.LT.ILASTM ) $ CALL DROT( ILASTM-ILAST, B( ILAST-1, ILAST+1 ), LDB, $ B( ILAST, ILAST+1 ), LDA, CL, SL ) IF( IFRSTM.LT.ILAST-1 ) $ CALL DROT( IFIRST-IFRSTM, B( IFRSTM, ILAST-1 ), 1, $ B( IFRSTM, ILAST ), 1, CR, SR )* IF( ILQ ) $ CALL DROT( N, Q( 1, ILAST-1 ), 1, Q( 1, ILAST ), 1, CL, $ SL ) IF( ILZ ) $ CALL DROT( N, Z( 1, ILAST-1 ), 1, Z( 1, ILAST ), 1, CR, $ SR )* B( ILAST-1, ILAST-1 ) = B11 B( ILAST-1, ILAST ) = ZERO B( ILAST, ILAST-1 ) = ZERO B( ILAST, ILAST ) = B22** If B22 is negative, negate column ILAST* IF( B22.LT.ZERO ) THEN DO 210 J = IFRSTM, ILAST A( J, ILAST ) = -A( J, ILAST ) B( J, ILAST ) = -B( 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 DLAG2( A( ILAST-1, ILAST-1 ), LDA, $ B( ILAST-1, ILAST-1 ), LDB, SAFMIN*SAFETY, S1, $ TEMP, WR, TEMP2, WI )** ------------------- Begin Timing Code ---------------------- OPST = OPST + DBLE( 103+12*( ILASTM+ILAST-IFIRST-IFRSTM )+6* $ ( NQ+NZ ) )* -------------------- End Timing Code -----------------------** 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 = A( ILAST-1, ILAST-1 ) A21 = A( ILAST, ILAST-1 ) A12 = A( ILAST-1, ILAST ) A22 = A( ILAST, ILAST )** Compute complex Givens rotation on right* (Assume some element of C = (sA - wB) > unfl )* __* (sA - wB) ( CZ -SZ )* ( SZ CZ )* C11R = S1*A11 - WR*B11 C11I = -WI*B11 C12 = S1*A12 C21 = S1*A21 C22R = S1*A22 - WR*B22 C22I = -WI*B22* IF( ABS( C11R )+ABS( C11I )+ABS( C12 ).GT.ABS( C21 )+ $ ABS( C22R )+ABS( C22I ) ) THEN T = DLAPY3( C12, C11R, C11I ) CZ = C12 / T SZR = -C11R / T SZI = -C11I / T ELSE CZ = DLAPY2( C22R, C22I ) IF( CZ.LE.SAFMIN ) THEN CZ = ZERO SZR = ONE SZI = ZERO ELSE TEMPR = C22R / CZ TEMPI = C22I / CZ T = DLAPY2( CZ, C21 ) CZ = CZ / T SZR = -C21*TEMPR / T SZI = C21*TEMPI / T END IF END IF** Compute Givens rotation on left** ( CQ SQ )* ( __ ) A or B* ( -SQ CQ )* AN = ABS( A11 ) + ABS( A12 ) + ABS( A21 ) + ABS( A22 ) BN = ABS( B11 ) + ABS( B22 ) WABS = ABS( WR ) + ABS( WI ) IF( S1*AN.GT.WABS*BN ) THEN CQ = CZ*B11 SQR = SZR*B22 SQI = -SZI*B22 ELSE A1R = CZ*A11 + SZR*A12 A1I = SZI*A12 A2R = CZ*A21 + SZR*A22 A2I = SZI*A22 CQ = DLAPY2( A1R, A1I ) IF( CQ.LE.SAFMIN ) THEN CQ = ZERO SQR = ONE SQI = ZERO ELSE TEMPR = A1R / CQ TEMPI = A1I / CQ SQR = TEMPR*A2R + TEMPI*A2I SQI = TEMPI*A2R - TEMPR*A2I END IF END IF T = DLAPY3( CQ, SQR, SQI ) CQ = CQ / T SQR = SQR / T SQI = SQI / T** Compute diagonal elements of QBZ* TEMPR = SQR*SZR - SQI*SZI TEMPI = SQR*SZI + SQI*SZR B1R = CQ*CZ*B11 + TEMPR*B22 B1I = TEMPI*B22 B1A = DLAPY2( B1R, B1I ) B2R = CQ*CZ*B22 + TEMPR*B11 B2I = -TEMPI*B11 B2A = DLAPY2( B2R, B2I )** Normalize so beta > 0, and Im( alpha1 ) > 0* BETA( ILAST-1 ) = B1A BETA( ILAST ) = B2A ALPHAR( ILAST-1 ) = ( WR*B1A )*S1INV ALPHAI( ILAST-1 ) = ( WI*B1A )*S1INV ALPHAR( ILAST ) = ( WR*B2A )*S1INV ALPHAI( ILAST ) = -( WI*B2A )*S1INV** ------------------- Begin Timing Code ---------------------- OPST = OPST + DBLE( 93 )* -------------------- End Timing Code -----------------------** Step 3: Go to next block -- exit if finished.* ILAST = IFIRST - 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
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -