📄 dlasd4.f
字号:
SUBROUTINE DLASD4( N, I, D, Z, DELTA, RHO, SIGMA, WORK, INFO )** -- LAPACK auxiliary routine (instrumented to count ops, version 3.0) --* Univ. of Tennessee, Oak Ridge National Lab, Argonne National Lab,* Courant Institute, NAG Ltd., and Rice University* October 31, 1999** .. Scalar Arguments .. INTEGER I, INFO, N DOUBLE PRECISION RHO, SIGMA* ..* .. Array Arguments .. DOUBLE PRECISION D( * ), DELTA( * ), WORK( * ), Z( * )* ..* .. Common block to return operation count .. COMMON / LATIME / OPS, ITCNT* ..* .. Scalars in Common .. DOUBLE PRECISION ITCNT, OPS* ..** Purpose* =======** This subroutine computes the square root of the I-th updated* eigenvalue of a positive symmetric rank-one modification to* a positive diagonal matrix whose entries are given as the squares* of the corresponding entries in the array d, and that** 0 <= 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 ) * 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) DOUBLE PRECISION array, dimension ( N )* The original eigenvalues. It is assumed that they are in* order, 0 <= D(I) < D(J) for I < J.** Z (input) DOUBLE PRECISION array, dimension ( N )* The components of the updating vector.** DELTA (output) DOUBLE PRECISION array, dimension ( N )* If N .ne. 1, DELTA contains (D(j) - sigma_I) in its j-th* component. If N = 1, then DELTA(1) = 1. The vector DELTA* contains the information necessary to construct the* (singular) eigenvectors.** RHO (input) DOUBLE PRECISION* The scalar in the symmetric updating formula.** SIGMA (output) DOUBLE PRECISION* The computed lambda_I, the I-th updated eigenvalue.** WORK (workspace) DOUBLE PRECISION array, dimension ( N )* If N .ne. 1, WORK contains (D(j) + sigma_I) in its j-th* component. If N = 1, then WORK( 1 ) = 1.** 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.** Further Details* ===============** Based on contributions by* Ren-Cang Li, Computer Science Division, University of California* at Berkeley, USA** =====================================================================** .. Parameters .. INTEGER MAXIT PARAMETER ( MAXIT = 20 ) DOUBLE PRECISION ZERO, ONE, TWO, THREE, FOUR, EIGHT, TEN PARAMETER ( ZERO = 0.0D0, ONE = 1.0D0, TWO = 2.0D0, $ THREE = 3.0D0, FOUR = 4.0D0, EIGHT = 8.0D0, $ TEN = 10.0D0 )* ..* .. Local Scalars .. LOGICAL ORGATI, SWTCH, SWTCH3 INTEGER II, IIM1, IIP1, IP1, ITER, J, NITER DOUBLE PRECISION A, B, C, DELSQ, DELSQ2, DPHI, DPSI, DTIIM, $ DTIIP, DTIPSQ, DTISQ, DTNSQ, DTNSQ1, DW, EPS, $ ERRETM, ETA, PHI, PREW, PSI, RHOINV, SG2LB, $ SG2UB, TAU, TEMP, TEMP1, TEMP2, W* ..* .. Local Arrays .. DOUBLE PRECISION DD( 3 ), ZZ( 3 )* ..* .. External Subroutines .. EXTERNAL DLAED6, DLASD5* ..* .. External Functions .. DOUBLE PRECISION DLAMCH EXTERNAL DLAMCH* ..* .. Intrinsic Functions .. INTRINSIC DBLE, ABS, MAX, MIN, 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* OPS = OPS + DBLE( 5 ) SIGMA = SQRT( D( 1 )*D( 1 )+RHO*Z( 1 )*Z( 1 ) ) DELTA( 1 ) = ONE WORK( 1 ) = ONE RETURN END IF IF( N.EQ.2 ) THEN CALL DLASD5( I, D, Z, DELTA, RHO, SIGMA, WORK ) RETURN END IF** Compute machine epsilon* EPS = DLAMCH( 'Epsilon' ) OPS = OPS + DBLE( 1 ) RHOINV = ONE / RHO** The case I = N* IF( I.EQ.N ) THEN** Initialize some basic variables* II = N - 1 NITER = 1** Calculate initial guess* OPS = OPS + DBLE( 1 ) TEMP = RHO / TWO** If ||Z||_2 is not one, then TEMP should be set to* RHO * ||Z||_2^2 / TWO* OPS = OPS + DBLE( 5 + 4*N ) TEMP1 = TEMP / ( D( N )+SQRT( D( N )*D( N )+TEMP ) ) DO 10 J = 1, N WORK( J ) = D( J ) + D( N ) + TEMP1 DELTA( J ) = ( D( J )-D( N ) ) - TEMP1 10 CONTINUE* PSI = ZERO OPS = OPS + DBLE( 4*( N-2 ) ) DO 20 J = 1, N - 2 PSI = PSI + Z( J )*Z( J ) / ( DELTA( J )*WORK( J ) ) 20 CONTINUE* OPS = OPS + DBLE( 9 ) C = RHOINV + PSI W = C + Z( II )*Z( II ) / ( DELTA( II )*WORK( II ) ) + $ Z( N )*Z( N ) / ( DELTA( N )*WORK( N ) )* IF( W.LE.ZERO ) THEN OPS = OPS + DBLE( 14 ) TEMP1 = SQRT( D( N )*D( N )+RHO ) TEMP = Z( N-1 )*Z( N-1 ) / ( ( D( N-1 )+TEMP1 )* $ ( D( N )-D( N-1 )+RHO / ( D( N )+TEMP1 ) ) ) + $ Z( N )*Z( N ) / RHO** The following TAU is to approximate* SIGMA_n^2 - D( N )*D( N )* IF( C.LE.TEMP ) THEN TAU = RHO ELSE OPS = OPS + DBLE( 10 ) DELSQ = ( D( N )-D( N-1 ) )*( D( N )+D( N-1 ) ) A = -C*DELSQ + Z( N-1 )*Z( N-1 ) + Z( N )*Z( N ) B = Z( N )*Z( N )*DELSQ IF( A.LT.ZERO ) THEN OPS = OPS + DBLE( 8 ) TAU = TWO*B / ( SQRT( A*A+FOUR*B*C )-A ) ELSE OPS = OPS + DBLE( 8 ) TAU = ( A+SQRT( A*A+FOUR*B*C ) ) / ( TWO*C ) END IF END IF** It can be proved that* D(N)^2+RHO/2 <= SIGMA_n^2 < D(N)^2+TAU <= D(N)^2+RHO* ELSE OPS = OPS + DBLE( 10 ) DELSQ = ( D( N )-D( N-1 ) )*( D( N )+D( N-1 ) ) A = -C*DELSQ + Z( N-1 )*Z( N-1 ) + Z( N )*Z( N ) B = Z( N )*Z( N )*DELSQ** The following TAU is to approximate* SIGMA_n^2 - D( N )*D( N )* IF( A.LT.ZERO ) THEN OPS = OPS + DBLE( 8 ) TAU = TWO*B / ( SQRT( A*A+FOUR*B*C )-A ) ELSE OPS = OPS + DBLE( 8 ) TAU = ( A+SQRT( A*A+FOUR*B*C ) ) / ( TWO*C ) END IF** It can be proved that* D(N)^2 < D(N)^2+TAU < SIGMA(N)^2 < D(N)^2+RHO/2* END IF** The following ETA is to approximate SIGMA_n - D( N )* OPS = OPS + DBLE( 5 ) ETA = TAU / ( D( N )+SQRT( D( N )*D( N )+TAU ) )* OPS = OPS + DBLE( 1 + 4*N ) SIGMA = D( N ) + ETA DO 30 J = 1, N DELTA( J ) = ( D( J )-D( I ) ) - ETA WORK( J ) = D( J ) + D( I ) + ETA 30 CONTINUE** Evaluate PSI and the derivative DPSI* DPSI = ZERO PSI = ZERO ERRETM = ZERO OPS = OPS + DBLE( II*7 ) DO 40 J = 1, II TEMP = Z( J ) / ( DELTA( J )*WORK( J ) ) PSI = PSI + Z( J )*TEMP DPSI = DPSI + TEMP*TEMP ERRETM = ERRETM + PSI 40 CONTINUE ERRETM = ABS( ERRETM )** Evaluate PHI and the derivative DPHI* OPS = OPS + DBLE( 14 ) TEMP = Z( N ) / ( DELTA( N )*WORK( 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 GO TO 240 END IF** Calculate the new step* NITER = NITER + 1 OPS = OPS + DBLE( 14 ) DTNSQ1 = WORK( N-1 )*DELTA( N-1 ) DTNSQ = WORK( N )*DELTA( N ) C = W - DTNSQ1*DPSI - DTNSQ*DPHI A = ( DTNSQ+DTNSQ1 )*W - DTNSQ*DTNSQ1*( DPSI+DPHI ) B = DTNSQ*DTNSQ1*W IF( C.LT.ZERO ) $ C = ABS( C ) IF( C.EQ.ZERO ) THEN OPS = OPS + DBLE( 2 ) ETA = RHO - SIGMA*SIGMA ELSE IF( A.GE.ZERO ) THEN OPS = OPS + DBLE( 8 ) ETA = ( A+SQRT( ABS( A*A-FOUR*B*C ) ) ) / ( TWO*C ) ELSE OPS = OPS + DBLE( 8 ) 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.* OPS = OPS + DBLE( 1 ) IF( W*ETA.GT.ZERO ) THEN OPS = OPS + DBLE( 2 ) ETA = -W / ( DPSI+DPHI ) END IF TEMP = ETA - DTNSQ IF( TEMP.GT.RHO ) THEN OPS = OPS + DBLE( 1 ) ETA = RHO + DTNSQ END IF* OPS = OPS + DBLE( 6 + 2*N + 1 ) TAU = TAU + ETA ETA = ETA / ( SIGMA+SQRT( ETA+SIGMA*SIGMA ) ) DO 50 J = 1, N DELTA( J ) = DELTA( J ) - ETA
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -