📄 dtgevc.f
字号:
* (b) this would be the second of a complex pair.* Check for complex eigenvalue, so as to be sure of which* entry(-ies) of SELECT to look at -- if complex, SELECT(JE)* or SELECT(JE-1).* If this is a complex pair, the 2-by-2 diagonal block* corresponding to the eigenvalue is in rows/columns JE-1:JE* IF( ILCPLX ) THEN ILCPLX = .FALSE. GO TO 500 END IF NW = 1 IF( JE.GT.1 ) THEN IF( A( JE, JE-1 ).NE.ZERO ) THEN ILCPLX = .TRUE. NW = 2 END IF END IF IF( ILALL ) THEN ILCOMP = .TRUE. ELSE IF( ILCPLX ) THEN ILCOMP = SELECT( JE ) .OR. SELECT( JE-1 ) ELSE ILCOMP = SELECT( JE ) END IF IF( .NOT.ILCOMP ) $ GO TO 500** Decide if (a) singular pencil, (b) real eigenvalue, or* (c) complex eigenvalue.* IF( .NOT.ILCPLX ) THEN IF( ABS( A( JE, JE ) ).LE.SAFMIN .AND. $ ABS( B( JE, JE ) ).LE.SAFMIN ) THEN** Singular matrix pencil -- returns unit eigenvector* IEIG = IEIG - 1 DO 230 JR = 1, N VR( JR, IEIG ) = ZERO 230 CONTINUE VR( IEIG, IEIG ) = ONE GO TO 500 END IF END IF** Clear vector* DO 250 JW = 0, NW - 1 DO 240 JR = 1, N WORK( ( JW+2 )*N+JR ) = ZERO 240 CONTINUE 250 CONTINUE** Compute coefficients in ( a A - b B ) x = 0* a is ACOEF* b is BCOEFR + i*BCOEFI* IF( .NOT.ILCPLX ) THEN** Real eigenvalue* TEMP = ONE / MAX( ABS( A( JE, JE ) )*ASCALE, $ ABS( B( JE, JE ) )*BSCALE, SAFMIN ) SALFAR = ( TEMP*A( JE, JE ) )*ASCALE SBETA = ( TEMP*B( JE, JE ) )*BSCALE ACOEF = SBETA*ASCALE BCOEFR = SALFAR*BSCALE BCOEFI = ZERO** Scale to avoid underflow* SCALE = ONE LSA = ABS( SBETA ).GE.SAFMIN .AND. ABS( ACOEF ).LT.SMALL LSB = ABS( SALFAR ).GE.SAFMIN .AND. ABS( BCOEFR ).LT. $ SMALL IF( LSA ) $ SCALE = ( SMALL / ABS( SBETA ) )*MIN( ANORM, BIG ) IF( LSB ) $ SCALE = MAX( SCALE, ( SMALL / ABS( SALFAR ) )* $ MIN( BNORM, BIG ) ) IF( LSA .OR. LSB ) THEN SCALE = MIN( SCALE, ONE / $ ( SAFMIN*MAX( ONE, ABS( ACOEF ), $ ABS( BCOEFR ) ) ) ) IF( LSA ) THEN ACOEF = ASCALE*( SCALE*SBETA ) ELSE ACOEF = SCALE*ACOEF END IF IF( LSB ) THEN BCOEFR = BSCALE*( SCALE*SALFAR ) ELSE BCOEFR = SCALE*BCOEFR END IF END IF ACOEFA = ABS( ACOEF ) BCOEFA = ABS( BCOEFR )** First component is 1* WORK( 2*N+JE ) = ONE XMAX = ONE** Compute contribution from column JE of A and B to sum* (See "Further Details", above.)* DO 260 JR = 1, JE - 1 WORK( 2*N+JR ) = BCOEFR*B( JR, JE ) - $ ACOEF*A( JR, JE ) 260 CONTINUE ELSE** Complex eigenvalue* CALL DLAG2( A( JE-1, JE-1 ), LDA, B( JE-1, JE-1 ), LDB, $ SAFMIN*SAFETY, ACOEF, TEMP, BCOEFR, TEMP2, $ BCOEFI ) IF( BCOEFI.EQ.ZERO ) THEN INFO = JE - 1 RETURN END IF** Scale to avoid over/underflow* ACOEFA = ABS( ACOEF ) BCOEFA = ABS( BCOEFR ) + ABS( BCOEFI ) SCALE = ONE IF( ACOEFA*ULP.LT.SAFMIN .AND. ACOEFA.GE.SAFMIN ) $ SCALE = ( SAFMIN / ULP ) / ACOEFA IF( BCOEFA*ULP.LT.SAFMIN .AND. BCOEFA.GE.SAFMIN ) $ SCALE = MAX( SCALE, ( SAFMIN / ULP ) / BCOEFA ) IF( SAFMIN*ACOEFA.GT.ASCALE ) $ SCALE = ASCALE / ( SAFMIN*ACOEFA ) IF( SAFMIN*BCOEFA.GT.BSCALE ) $ SCALE = MIN( SCALE, BSCALE / ( SAFMIN*BCOEFA ) ) IF( SCALE.NE.ONE ) THEN ACOEF = SCALE*ACOEF ACOEFA = ABS( ACOEF ) BCOEFR = SCALE*BCOEFR BCOEFI = SCALE*BCOEFI BCOEFA = ABS( BCOEFR ) + ABS( BCOEFI ) END IF** Compute first two components of eigenvector* and contribution to sums* TEMP = ACOEF*A( JE, JE-1 ) TEMP2R = ACOEF*A( JE, JE ) - BCOEFR*B( JE, JE ) TEMP2I = -BCOEFI*B( JE, JE ) IF( ABS( TEMP ).GE.ABS( TEMP2R )+ABS( TEMP2I ) ) THEN WORK( 2*N+JE ) = ONE WORK( 3*N+JE ) = ZERO WORK( 2*N+JE-1 ) = -TEMP2R / TEMP WORK( 3*N+JE-1 ) = -TEMP2I / TEMP ELSE WORK( 2*N+JE-1 ) = ONE WORK( 3*N+JE-1 ) = ZERO TEMP = ACOEF*A( JE-1, JE ) WORK( 2*N+JE ) = ( BCOEFR*B( JE-1, JE-1 )-ACOEF* $ A( JE-1, JE-1 ) ) / TEMP WORK( 3*N+JE ) = BCOEFI*B( JE-1, JE-1 ) / TEMP END IF* XMAX = MAX( ABS( WORK( 2*N+JE ) )+ABS( WORK( 3*N+JE ) ), $ ABS( WORK( 2*N+JE-1 ) )+ABS( WORK( 3*N+JE-1 ) ) )** Compute contribution from columns JE and JE-1* of A and B to the sums.* CREALA = ACOEF*WORK( 2*N+JE-1 ) CIMAGA = ACOEF*WORK( 3*N+JE-1 ) CREALB = BCOEFR*WORK( 2*N+JE-1 ) - $ BCOEFI*WORK( 3*N+JE-1 ) CIMAGB = BCOEFI*WORK( 2*N+JE-1 ) + $ BCOEFR*WORK( 3*N+JE-1 ) CRE2A = ACOEF*WORK( 2*N+JE ) CIM2A = ACOEF*WORK( 3*N+JE ) CRE2B = BCOEFR*WORK( 2*N+JE ) - BCOEFI*WORK( 3*N+JE ) CIM2B = BCOEFI*WORK( 2*N+JE ) + BCOEFR*WORK( 3*N+JE ) DO 270 JR = 1, JE - 2 WORK( 2*N+JR ) = -CREALA*A( JR, JE-1 ) + $ CREALB*B( JR, JE-1 ) - $ CRE2A*A( JR, JE ) + CRE2B*B( JR, JE ) WORK( 3*N+JR ) = -CIMAGA*A( JR, JE-1 ) + $ CIMAGB*B( JR, JE-1 ) - $ CIM2A*A( JR, JE ) + CIM2B*B( JR, JE ) 270 CONTINUE END IF* DMIN = MAX( ULP*ACOEFA*ANORM, ULP*BCOEFA*BNORM, SAFMIN )** Columnwise triangular solve of (a A - b B) x = 0* IL2BY2 = .FALSE.* ------------------- Begin Timing Code ---------------------- OPST = ZERO IN2BY2 = 0* -------------------- End Timing Code ----------------------- DO 370 J = JE - NW, 1, -1* ------------------- Begin Timing Code ------------------- OPSSCA = DBLE( NW*JE+1 )* -------------------- End Timing Code --------------------** If a 2-by-2 block, is in position j-1:j, wait until* next iteration to process it (when it will be j:j+1)* IF( .NOT.IL2BY2 .AND. J.GT.1 ) THEN IF( A( J, J-1 ).NE.ZERO ) THEN IL2BY2 = .TRUE.* -------------- Begin Timing Code ----------------- IN2BY2 = IN2BY2 + 1* --------------- End Timing Code ------------------- GO TO 370 END IF END IF BDIAG( 1 ) = B( J, J ) IF( IL2BY2 ) THEN NA = 2 BDIAG( 2 ) = B( J+1, J+1 ) ELSE NA = 1 END IF** Compute x(j) (and x(j+1), if 2-by-2 block)* CALL DLALN2( .FALSE., NA, NW, DMIN, ACOEF, A( J, J ), $ LDA, BDIAG( 1 ), BDIAG( 2 ), WORK( 2*N+J ), $ N, BCOEFR, BCOEFI, SUM, 2, SCALE, TEMP, $ IINFO ) IF( SCALE.LT.ONE ) THEN* DO 290 JW = 0, NW - 1 DO 280 JR = 1, JE WORK( ( JW+2 )*N+JR ) = SCALE* $ WORK( ( JW+2 )*N+JR ) 280 CONTINUE 290 CONTINUE END IF XMAX = MAX( SCALE*XMAX, TEMP )* ------------------ Begin Timing Code ----------------- OPST = OPST + OPSSCA* ------------------- End Timing Code ------------------* DO 310 JW = 1, NW DO 300 JA = 1, NA WORK( ( JW+1 )*N+J+JA-1 ) = SUM( JA, JW ) 300 CONTINUE 310 CONTINUE** w = w + x(j)*(a A(*,j) - b B(*,j) ) with scaling* IF( J.GT.1 ) THEN** Check whether scaling is necessary for sum.* XSCALE = ONE / MAX( ONE, XMAX ) TEMP = ACOEFA*WORK( J ) + BCOEFA*WORK( N+J ) IF( IL2BY2 ) $ TEMP = MAX( TEMP, ACOEFA*WORK( J+1 )+BCOEFA* $ WORK( N+J+1 ) ) TEMP = MAX( TEMP, ACOEFA, BCOEFA ) IF( TEMP.GT.BIGNUM*XSCALE ) THEN* DO 330 JW = 0, NW - 1 DO 320 JR = 1, JE WORK( ( JW+2 )*N+JR ) = XSCALE* $ WORK( ( JW+2 )*N+JR ) 320 CONTINUE 330 CONTINUE XMAX = XMAX*XSCALE* ----------------- Begin Timing Code --------------- OPST = OPST + OPSSCA* ------------------ End Timing Code ---------------- END IF** Compute the contributions of the off-diagonals of* column j (and j+1, if 2-by-2 block) of A and B to the* sums.** DO 360 JA = 1, NA IF( ILCPLX ) THEN CREALA = ACOEF*WORK( 2*N+J+JA-1 ) CIMAGA = ACOEF*WORK( 3*N+J+JA-1 ) CREALB = BCOEFR*WORK( 2*N+J+JA-1 ) - $ BCOEFI*WORK( 3*N+J+JA-1 ) CIMAGB = BCOEFI*WORK( 2*N+J+JA-1 ) + $ BCOEFR*WORK( 3*N+J+JA-1 ) DO 340 JR = 1, J - 1 WORK( 2*N+JR ) = WORK( 2*N+JR ) - $ CREALA*A( JR, J+JA-1 ) + $ CREALB*B( JR, J+JA-1 ) WORK( 3*N+JR ) = WORK( 3*N+JR ) - $ CIMAGA*A( JR, J+JA-1 ) + $ CIMAGB*B( JR, J+JA-1 ) 340 CONTINUE ELSE CREALA = ACOEF*WORK( 2*N+J+JA-1 ) CREALB = BCOEFR*WORK( 2*N+J+JA-1 ) DO 350 JR = 1, J - 1 WORK( 2*N+JR ) = WORK( 2*N+JR ) - $ CREALA*A( JR, J+JA-1 ) + $ CREALB*B( JR, J+JA-1 ) 350 CONTINUE END IF 360 CONTINUE END IF* IL2BY2 = .FALSE. 370 CONTINUE** Copy eigenvector to VR, back transforming if* HOWMNY='B'.* IEIG = IEIG - NW IF( ILBACK ) THEN* DO 410 JW = 0, NW - 1 DO 380 JR = 1, N WORK( ( JW+4 )*N+JR ) = WORK( ( JW+2 )*N+1 )* $ VR( JR, 1 ) 380 CONTINUE** A series of compiler directives to defeat* vectorization for the next loop** DO 400 JC = 2, JE DO 390 JR = 1, N WORK( ( JW+4 )*N+JR ) = WORK( ( JW+4 )*N+JR ) + $ WORK( ( JW+2 )*N+JC )*VR( JR, JC ) 390 CONTINUE 400 CONTINUE 410 CONTINUE* DO 430 JW = 0, NW - 1 DO 420 JR = 1, N VR( JR, IEIG+JW ) = WORK( ( JW+4 )*N+JR ) 420 CONTINUE 430 CONTINUE* IEND = N ELSE DO 450 JW = 0, NW - 1 DO 440 JR = 1, N VR( JR, IEIG+JW ) = WORK( ( JW+2 )*N+JR ) 440 CONTINUE 450 CONTINUE* IEND = JE END IF** Scale eigenvector* XMAX = ZERO IF( ILCPLX ) THEN DO 460 J = 1, IEND XMAX = MAX( XMAX, ABS( VR( J, IEIG ) )+ $ ABS( VR( J, IEIG+1 ) ) ) 460 CONTINUE ELSE DO 470 J = 1, IEND XMAX = MAX( XMAX, ABS( VR( J, IEIG ) ) ) 470 CONTINUE END IF* IF( XMAX.GT.SAFMIN ) THEN XSCALE = ONE / XMAX DO 490 JW = 0, NW - 1 DO 480 JR = 1, IEND VR( JR, IEIG+JW ) = XSCALE*VR( JR, IEIG+JW ) 480 CONTINUE 490 CONTINUE END IF** ------------------- Begin Timing Code ----------------------* Opcounts for each eigenvector** Real Complex* Initialization 8--16 + 3*(JE-1) 71--87+16+14*(JE-2)** Solve (per iter) NA*(5 + 7*(NA-1)) NA*(17 + 17*(NA-1))* + scaling + scaling* column add (per iter)* 2 + 5*NA 2 + 11*NA* + 4*NA*(J-1) + 8*NA*(J-1)* + scaling + scaling* iteration: J=JE-1,...,1 J=JE-2,...,1** Back xform 2*N*JE - N 4*N*JE - 2*N* Scaling (w/back x.) N 3*N* Scaling (w/o back) JE 3*JE* IF( .NOT.ILCPLX ) THEN OPST = OPST + DBLE( ( 2*JE+11 )*( JE-1 )+12+8*IN2BY2 ) IF( ILBACK ) THEN OPST = OPST + DBLE( 2*N*JE ) ELSE OPST = OPST + DBLE( JE ) END IF ELSE OPST = OPST + DBLE( ( 4*JE+32 )*( JE-2 )+95+24*IN2BY2 ) IF( ILBACK ) THEN OPST = OPST + DBLE( 4*N*JE+N ) ELSE OPST = OPST + DBLE( 3*JE ) END IF END IF OPS = OPS + OPST** -------------------- End Timing Code -----------------------* 500 CONTINUE END IF* RETURN** End of DTGEVC* END
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -