📄 dsyevd.f
字号:
60 CONTINUE 70 CONTINUE DO 80 I = 1, K W( I ) = SIGN( SQRT( -W( I ) ), S( I, 1 ) ) 80 CONTINUE** Compute eigenvectors of the modified rank-1 modification.* DO 110 J = 1, K DO 90 I = 1, K Q( I, J ) = W( I ) / Q( I, J ) 90 CONTINUE TEMP = DNRM2( K, Q( 1, J ), 1 ) DO 100 I = 1, K JC = INDXC( I ) S( I, J ) = Q( JC, J ) / TEMP 100 CONTINUE 110 CONTINUE** Compute the updated eigenvectors.* 120 CONTINUE* PARTS = 0 IF( CTOT( 1 ).GT.0 ) THEN PARTS = PARTS + 1 CALL DGEMM( 'N', 'N', CUTPNT, KTEMP, CTOT( 1 ), ONE, $ Q2( 1, 1 ), LDQ2, S( 1, KSTART ), LDS, ZERO, $ Q( 1, KSTART ), LDQ ) END IF IF( CTOT( 2 ).GT.0 ) THEN PARTS = PARTS + 2 CALL DGEMM( 'N', 'N', N-CUTPNT, KTEMP, CTOT( 2 ), ONE, $ Q2( 1+CUTPNT, 1+CTOT( 1 ) ), LDQ2, $ S( 1+CTOT( 1 ), KSTART ), LDS, ZERO, $ Q( 1+CUTPNT, KSTART ), LDQ ) END IF IF( PARTS.EQ.1 ) $ CALL DLASET( 'A', N-CUTPNT, KTEMP, ZERO, ZERO, $ Q( 1+CUTPNT, KSTART ), LDQ ) IF( PARTS.EQ.2 ) $ CALL DLASET( 'A', CUTPNT, KTEMP, ZERO, ZERO, Q( 1, KSTART ), $ LDQ ) IF( CTOT( 3 ).GT.0 ) THEN IF( PARTS.GT.0 ) THEN CALL DGEMM( 'N', 'N', N, KTEMP, CTOT( 3 ), ONE, $ Q2( 1, 1+CTOT( 1 )+CTOT( 2 ) ), LDQ2, $ S( 1+CTOT( 1 )+CTOT( 2 ), KSTART ), LDS, ONE, $ Q( 1, KSTART ), LDQ ) ELSE CALL DGEMM( 'N', 'N', N, KTEMP, CTOT( 3 ), ONE, $ Q2( 1, 1+CTOT( 1 )+CTOT( 2 ) ), LDQ2, $ S( 1+CTOT( 1 )+CTOT( 2 ), KSTART ), LDS, ZERO, $ Q( 1, KSTART ), LDQ ) END IF END IF* 130 CONTINUE RETURN** End of DLAED3* END! ---------------------------------------------------------------------- SUBROUTINE DLAED4( N, I, D, Z, DELTA, RHO, DLAM, INFO )! ---------------------------------------------------------------------- Use numerics Implicit None** -- LAPACK routine (version 2.0) --* Univ. of Tennessee, Oak Ridge National Lab, Argonne National Lab,* Courant Institute, NAG Ltd., and Rice University* September 30, 1994** .. Scalar Arguments .. INTEGER I, INFO, N Real(l_) DLAM, RHO* ..* .. Array Arguments .. Real(l_) D( * ), DELTA( * ), Z( * )* ..** Purpose* =======** This subroutine computes the I-th updated eigenvalue of a symmetric* rank-one modification to a diagonal matrix whose elements are* given in the array d, and that** D(i) < D(j) for i < j** and that RHO > 0. This is arranged by the calling routine, and is* no loss in generality. The rank-one modified system is thus** diag( D ) + RHO * Z * Z_transpose.** where we assume the Euclidean norm of Z is 1.** The method consists of approximating the rational functions in the* secular equation by simpler interpolating rational functions.** Arguments* =========** N (input) INTEGER* The length of all arrays.** I (input) INTEGER* The index of the eigenvalue to be computed. 1 <= I <= N.** D (input) Real(l_) array, dimension (N)* The original eigenvalues. It is assumed that they are in* order, D(I) < D(J) for I < J.** Z (input) Real(l_) array, dimension (N)* The components of the updating vector.** DELTA (output) Real(l_) array, dimension (N)* If N .ne. 1, DELTA contains (D(j) - lambda_I) in its j-th* component. If N = 1, then DELTA(1) = 1. The vector DELTA* contains the information necessary to construct the* eigenvectors.** RHO (input) Real(l_)* The scalar in the symmetric updating formula.** DLAM (output) Real(l_)* The computed lambda_I, the I-th updated eigenvalue.** INFO (output) INTEGER* = 0: successful exit* > 0: if INFO = 1, the updating process failed.** Internal Parameters* ===================** Logical variable ORGATI (origin-at-i?) is used for distinguishing* whether D(i) or D(i+1) is treated as the origin.** ORGATI = .true. origin at i* ORGATI = .false. origin at i+1** Logical variable SWTCH3 (switch-for-3-poles?) is for noting* if we are working with THREE poles!** MAXIT is the maximum number of iterations allowed for each* eigenvalue.** =====================================================================** .. Parameters .. INTEGER MAXIT PARAMETER ( MAXIT = 20 ) Real(l_) ZERO, ONE, TWO, THREE, FOUR, EIGHT, TEN PARAMETER ( ZERO = 0.0_l_, ONE = 1.0_l_, TWO = 2.0_l_, $ THREE = 3.0_l_, FOUR = 4.0_l_, EIGHT = 8.0_l_, $ TEN = 10.0_l_ )* ..* .. Local Scalars .. LOGICAL ORGATI, SWTCH, SWTCH3 INTEGER II, IIM1, IIP1, IP1, ITER, J, NITER Real(l_) A, B, C, DEL, DPHI, DPSI, DW, EPS, ERRETM, ETA, $ PHI, PREW, PSI, RHOINV, TAU, TEMP, TEMP1, W* ..* .. Local Arrays .. Real(l_) ZZ( 3 )* ..* .. External Functions .. Real(l_) DLAMCH EXTERNAL DLAMCH* ..* .. External Subroutines .. EXTERNAL DLAED5, DLAED6* ..* .. Intrinsic Functions .. INTRINSIC ABS, SQRT* ..* .. Executable Statements ..** Since this routine is called in an inner loop, we do no argument* checking.** Quick return for N=1 and 2.* INFO = 0 IF( N.EQ.1 ) THEN** Presumably, I=1 upon entry* DLAM = D( 1 ) + RHO*Z( 1 )*Z( 1 ) DELTA( 1 ) = ONE RETURN END IF IF( N.EQ.2 ) THEN CALL DLAED5( I, D, Z, DELTA, RHO, DLAM ) RETURN END IF** Compute machine epsilon* EPS = DLAMCH( 'Epsilon' ) RHOINV = ONE / RHO** The case I = N* IF( I.EQ.N ) THEN** Initialize some basic variables* II = N - 1 NITER = 1** Calculate initial guess* TEMP = RHO / TWO** If ||Z||_2 is not one, then TEMP should be set to* RHO * ||Z||_2^2 / TWO* DO 10 J = 1, N DELTA( J ) = ( D( J )-D( I ) ) - TEMP 10 CONTINUE* PSI = ZERO DO 20 J = 1, N - 2 PSI = PSI + Z( J )*Z( J ) / DELTA( J ) 20 CONTINUE* C = RHOINV + PSI W = C + Z( II )*Z( II ) / DELTA( II ) + $ Z( N )*Z( N ) / DELTA( N )* IF( W.LE.ZERO ) THEN TEMP = Z( N-1 )*Z( N-1 ) / ( D( N )-D( N-1 )+RHO ) + $ Z( N )*Z( N ) / RHO IF( C.LE.TEMP ) THEN TAU = RHO ELSE DEL = D( N ) - D( N-1 ) A = -C*DEL + Z( N-1 )*Z( N-1 ) + Z( N )*Z( N ) B = Z( N )*Z( N )*DEL IF( A.LT.ZERO ) THEN TAU = TWO*B / ( SQRT( A*A+FOUR*B*C )-A ) ELSE TAU = ( A+SQRT( A*A+FOUR*B*C ) ) / ( TWO*C ) END IF END IF** It can be proved that* D(N)+RHO/2 <= LAMBDA(N) < D(N)+TAU <= D(N)+RHO* ELSE DEL = D( N ) - D( N-1 ) A = -C*DEL + Z( N-1 )*Z( N-1 ) + Z( N )*Z( N ) B = Z( N )*Z( N )*DEL IF( A.LT.ZERO ) THEN TAU = TWO*B / ( SQRT( A*A+FOUR*B*C )-A ) ELSE TAU = ( A+SQRT( A*A+FOUR*B*C ) ) / ( TWO*C ) END IF** It can be proved that* D(N) < D(N)+TAU < LAMBDA(N) < D(N)+RHO/2* END IF* DO 30 J = 1, N DELTA( J ) = ( D( J )-D( I ) ) - TAU 30 CONTINUE** Evaluate PSI and the derivative DPSI* DPSI = ZERO PSI = ZERO ERRETM = ZERO DO 40 J = 1, II TEMP = Z( J ) / DELTA( J ) PSI = PSI + Z( J )*TEMP DPSI = DPSI + TEMP*TEMP ERRETM = ERRETM + PSI 40 CONTINUE ERRETM = ABS( ERRETM )** Evaluate PHI and the derivative DPHI* TEMP = Z( N ) / DELTA( N ) PHI = Z( N )*TEMP DPHI = TEMP*TEMP ERRETM = EIGHT*( -PHI-PSI ) + ERRETM - PHI + RHOINV + $ ABS( TAU )*( DPSI+DPHI )* W = RHOINV + PHI + PSI** Test for convergence* IF( ABS( W ).LE.EPS*ERRETM ) THEN DLAM = D( I ) + TAU GO TO 250 END IF** Calculate the new step* NITER = NITER + 1 C = W - DELTA( N-1 )*DPSI - DELTA( N )*DPHI A = ( DELTA( N-1 )+DELTA( N ) )*W - $ DELTA( N-1 )*DELTA( N )*( DPSI+DPHI ) B = DELTA( N-1 )*DELTA( N )*W IF( C.LT.ZERO ) $ C = ABS( C ) IF( C.EQ.ZERO ) THEN* ETA = B/A ETA = RHO - TAU ELSE IF( A.GE.ZERO ) THEN ETA = ( A+SQRT( ABS( A*A-FOUR*B*C ) ) ) / ( TWO*C ) ELSE ETA = TWO*B / ( A-SQRT( ABS( A*A-FOUR*B*C ) ) ) END IF** Note, eta should be positive if w is negative, and* eta should be negative otherwise. However,* if for some reason caused by roundoff, eta*w > 0,* we simply use one Newton step instead. This way* will guarantee eta*w < 0.* IF( W*ETA.GT.ZERO ) $ ETA = -W / ( DPSI+DPHI ) TEMP = TAU + ETA IF( TEMP.GT.RHO ) $ ETA = RHO - TAU DO 50 J = 1, N DELTA( J ) = DELTA( J ) - ETA 50 CONTINUE* TAU = TAU + ETA** Evaluate PSI and the derivative DPSI* DPSI = ZERO PSI = ZERO ERRETM = ZERO DO 60 J = 1, II TEMP = Z( J ) / DELTA( J ) PSI = PSI + Z( J )*TEMP DPSI = DPSI + TEMP*TEMP ERRETM = ERRETM + PSI 60 CONTINUE ERRETM = ABS( ERRETM )** Evaluate PHI and the derivative DPHI* TEMP = Z( N ) / DELTA( N ) PHI = Z( N )*TEMP DPHI = TEMP*TEMP ERRETM = EIGHT*( -PHI-PSI ) + ERRETM - PHI + RHOINV + $ ABS( TAU )*( DPSI+DPHI )* W = RHOINV + PHI + PSI** Main loop to update the values of the array DELTA* ITER = NITER + 1* DO 90 NITER = ITER, MAXIT** Test for convergence* IF( ABS( W ).LE.EPS*ERRETM ) THEN DLAM = D( I ) + TAU GO TO 250 END IF** Calculate the new step* C = W - DELTA( N-1 )*DPSI - DELTA( N )*DPHI A = ( DELTA( N-1 )+DELTA( N ) )*W - $ DELTA( N-1 )*DELTA( N )*( DPSI+DPHI ) B = DELTA( N-1 )*DELTA( N )*W IF( A.GE.ZERO ) THEN ETA = ( A+SQRT( ABS( A*A-FOUR*B*C ) ) ) / ( TWO*C ) ELSE ETA = TWO*B / ( A-SQRT( ABS( A*A-FOUR*B*C ) ) ) END IF** Note, eta should be positive if w is negative, and* eta should be negative otherwise. However,* if for some reason caused by roundoff, eta*w > 0,* we simply use one Newton step instead. This way* will guarantee eta*w < 0.* IF( W*ETA.GT.ZERO ) $ ETA = -W / ( DPSI+DPHI ) TEMP = TAU + ETA IF( TEMP.LE.ZERO ) $ ETA = ETA / TWO DO 70 J = 1, N DELTA( J ) = DELTA( J ) - ETA 70 CONTINUE* TAU = TAU + ETA** Evaluate PSI and the derivative DPSI* DPSI = ZERO PSI = ZERO ERRETM = ZERO DO 80 J = 1, II TEM
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -