diff options
author | jason <jason@8a072113-8704-0410-8d35-dd094bca7971> | 2008-10-28 01:38:50 +0000 |
---|---|---|
committer | jason <jason@8a072113-8704-0410-8d35-dd094bca7971> | 2008-10-28 01:38:50 +0000 |
commit | baba851215b44ac3b60b9248eb02bcce7eb76247 (patch) | |
tree | 8c0f5c006875532a30d4409f5e94b0f310ff00a7 /SRC/slaed4.f | |
download | lapack-baba851215b44ac3b60b9248eb02bcce7eb76247.tar.gz lapack-baba851215b44ac3b60b9248eb02bcce7eb76247.tar.bz2 lapack-baba851215b44ac3b60b9248eb02bcce7eb76247.zip |
Move LAPACK trunk into position.
Diffstat (limited to 'SRC/slaed4.f')
-rw-r--r-- | SRC/slaed4.f | 844 |
1 files changed, 844 insertions, 0 deletions
diff --git a/SRC/slaed4.f b/SRC/slaed4.f new file mode 100644 index 00000000..dbb1e202 --- /dev/null +++ b/SRC/slaed4.f @@ -0,0 +1,844 @@ + SUBROUTINE SLAED4( N, I, D, Z, DELTA, RHO, DLAM, INFO ) +* +* -- LAPACK routine (version 3.1) -- +* Univ. of Tennessee, Univ. of California Berkeley and NAG Ltd.. +* November 2006 +* +* .. Scalar Arguments .. + INTEGER I, INFO, N + REAL DLAM, RHO +* .. +* .. Array Arguments .. + REAL 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 array, dimension (N) +* The original eigenvalues. It is assumed that they are in +* order, D(I) < D(J) for I < J. +* +* Z (input) REAL array, dimension (N) +* The components of the updating vector. +* +* DELTA (output) REAL array, dimension (N) +* If N .GT. 2, DELTA contains (D(j) - lambda_I) in its j-th +* component. If N = 1, then DELTA(1) = 1. If N = 2, see SLAED5 +* for detail. The vector DELTA contains the information necessary +* to construct the eigenvectors by SLAED3 and SLAED9. +* +* RHO (input) REAL +* The scalar in the symmetric updating formula. +* +* DLAM (output) REAL +* 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. +* +* Further Details +* =============== +* +* Based on contributions by +* Ren-Cang Li, Computer Science Division, University of California +* at Berkeley, USA +* +* ===================================================================== +* +* .. Parameters .. + INTEGER MAXIT + PARAMETER ( MAXIT = 30 ) + REAL ZERO, ONE, TWO, THREE, FOUR, EIGHT, TEN + PARAMETER ( ZERO = 0.0E0, ONE = 1.0E0, TWO = 2.0E0, + $ THREE = 3.0E0, FOUR = 4.0E0, EIGHT = 8.0E0, + $ TEN = 10.0E0 ) +* .. +* .. Local Scalars .. + LOGICAL ORGATI, SWTCH, SWTCH3 + INTEGER II, IIM1, IIP1, IP1, ITER, J, NITER + REAL A, B, C, DEL, DLTLB, DLTUB, DPHI, DPSI, DW, + $ EPS, ERRETM, ETA, MIDPT, PHI, PREW, PSI, + $ RHOINV, TAU, TEMP, TEMP1, W +* .. +* .. Local Arrays .. + REAL ZZ( 3 ) +* .. +* .. External Functions .. + REAL SLAMCH + EXTERNAL SLAMCH +* .. +* .. External Subroutines .. + EXTERNAL SLAED5, SLAED6 +* .. +* .. Intrinsic Functions .. + INTRINSIC 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 +* + DLAM = D( 1 ) + RHO*Z( 1 )*Z( 1 ) + DELTA( 1 ) = ONE + RETURN + END IF + IF( N.EQ.2 ) THEN + CALL SLAED5( I, D, Z, DELTA, RHO, DLAM ) + RETURN + END IF +* +* Compute machine epsilon +* + EPS = SLAMCH( '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 +* + MIDPT = 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 ) ) - MIDPT + 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 +* + DLTLB = MIDPT + DLTUB = 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 +* + DLTLB = ZERO + DLTUB = MIDPT + 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 +* + IF( W.LE.ZERO ) THEN + DLTLB = MAX( DLTLB, TAU ) + ELSE + DLTUB = MIN( DLTUB, TAU ) + 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 + ETA = DLTUB - 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.DLTUB .OR. TEMP.LT.DLTLB ) THEN + IF( W.LT.ZERO ) THEN + ETA = ( DLTUB-TAU ) / TWO + ELSE + ETA = ( DLTLB-TAU ) / TWO + END IF + END IF + 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 +* + IF( W.LE.ZERO ) THEN + DLTLB = MAX( DLTLB, TAU ) + ELSE + DLTUB = MIN( DLTUB, TAU ) + 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.GT.DLTUB .OR. TEMP.LT.DLTLB ) THEN + IF( W.LT.ZERO ) THEN + ETA = ( DLTUB-TAU ) / TWO + ELSE + ETA = ( DLTLB-TAU ) / TWO + END IF + END IF + 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 + TEMP = Z( J ) / DELTA( J ) + PSI = PSI + Z( J )*TEMP + DPSI = DPSI + TEMP*TEMP + ERRETM = ERRETM + PSI + 80 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 + 90 CONTINUE +* +* Return with INFO = 1, NITER = MAXIT and not converged +* + INFO = 1 + DLAM = D( I ) + TAU + GO TO 250 +* +* End for the case I = N +* + ELSE +* +* The case for I < N +* + NITER = 1 + IP1 = I + 1 +* +* Calculate initial guess +* + DEL = D( IP1 ) - D( I ) + MIDPT = DEL / TWO + DO 100 J = 1, N + DELTA( J ) = ( D( J )-D( I ) ) - MIDPT + 100 CONTINUE +* + PSI = ZERO + DO 110 J = 1, I - 1 + PSI = PSI + Z( J )*Z( J ) / DELTA( J ) + 110 CONTINUE +* + PHI = ZERO + DO 120 J = N, I + 2, -1 + PHI = PHI + Z( J )*Z( J ) / DELTA( J ) + 120 CONTINUE + C = RHOINV + PSI + PHI + W = C + Z( I )*Z( I ) / DELTA( I ) + + $ Z( IP1 )*Z( IP1 ) / DELTA( IP1 ) +* + IF( W.GT.ZERO ) THEN +* +* d(i)< the ith eigenvalue < (d(i)+d(i+1))/2 +* +* We choose d(i) as origin. +* + ORGATI = .TRUE. + A = C*DEL + Z( I )*Z( I ) + Z( IP1 )*Z( IP1 ) + B = Z( I )*Z( I )*DEL + IF( A.GT.ZERO ) THEN + TAU = TWO*B / ( A+SQRT( ABS( A*A-FOUR*B*C ) ) ) + ELSE + TAU = ( A-SQRT( ABS( A*A-FOUR*B*C ) ) ) / ( TWO*C ) + END IF + DLTLB = ZERO + DLTUB = MIDPT + ELSE +* +* (d(i)+d(i+1))/2 <= the ith eigenvalue < d(i+1) +* +* We choose d(i+1) as origin. +* + ORGATI = .FALSE. + A = C*DEL - Z( I )*Z( I ) - Z( IP1 )*Z( IP1 ) + B = Z( IP1 )*Z( IP1 )*DEL + IF( A.LT.ZERO ) THEN + TAU = TWO*B / ( A-SQRT( ABS( A*A+FOUR*B*C ) ) ) + ELSE + TAU = -( A+SQRT( ABS( A*A+FOUR*B*C ) ) ) / ( TWO*C ) + END IF + DLTLB = -MIDPT + DLTUB = ZERO + END IF +* + IF( ORGATI ) THEN + DO 130 J = 1, N + DELTA( J ) = ( D( J )-D( I ) ) - TAU + 130 CONTINUE + ELSE + DO 140 J = 1, N + DELTA( J ) = ( D( J )-D( IP1 ) ) - TAU + 140 CONTINUE + END IF + IF( ORGATI ) THEN + II = I + ELSE + II = I + 1 + END IF + IIM1 = II - 1 + IIP1 = II + 1 +* +* Evaluate PSI and the derivative DPSI +* + DPSI = ZERO + PSI = ZERO + ERRETM = ZERO + DO 150 J = 1, IIM1 + TEMP = Z( J ) / DELTA( J ) + PSI = PSI + Z( J )*TEMP + DPSI = DPSI + TEMP*TEMP + ERRETM = ERRETM + PSI + 150 CONTINUE + ERRETM = ABS( ERRETM ) +* +* Evaluate PHI and the derivative DPHI +* + DPHI = ZERO + PHI = ZERO + DO 160 J = N, IIP1, -1 + TEMP = Z( J ) / DELTA( J ) + PHI = PHI + Z( J )*TEMP + DPHI = DPHI + TEMP*TEMP + ERRETM = ERRETM + PHI + 160 CONTINUE +* + W = RHOINV + PHI + PSI +* +* W is the value of the secular function with +* its ii-th element removed. +* + SWTCH3 = .FALSE. + IF( ORGATI ) THEN + IF( W.LT.ZERO ) + $ SWTCH3 = .TRUE. + ELSE + IF( W.GT.ZERO ) + $ SWTCH3 = .TRUE. + END IF + IF( II.EQ.1 .OR. II.EQ.N ) + $ SWTCH3 = .FALSE. +* + TEMP = Z( II ) / DELTA( II ) + DW = DPSI + DPHI + TEMP*TEMP + TEMP = Z( II )*TEMP + W = W + TEMP + ERRETM = EIGHT*( PHI-PSI ) + ERRETM + TWO*RHOINV + + $ THREE*ABS( TEMP ) + ABS( TAU )*DW +* +* Test for convergence +* + IF( ABS( W ).LE.EPS*ERRETM ) THEN + IF( ORGATI ) THEN + DLAM = D( I ) + TAU + ELSE + DLAM = D( IP1 ) + TAU + END IF + GO TO 250 + END IF +* + IF( W.LE.ZERO ) THEN + DLTLB = MAX( DLTLB, TAU ) + ELSE + DLTUB = MIN( DLTUB, TAU ) + END IF +* +* Calculate the new step +* + NITER = NITER + 1 + IF( .NOT.SWTCH3 ) THEN + IF( ORGATI ) THEN + C = W - DELTA( IP1 )*DW - ( D( I )-D( IP1 ) )* + $ ( Z( I ) / DELTA( I ) )**2 + ELSE + C = W - DELTA( I )*DW - ( D( IP1 )-D( I ) )* + $ ( Z( IP1 ) / DELTA( IP1 ) )**2 + END IF + A = ( DELTA( I )+DELTA( IP1 ) )*W - + $ DELTA( I )*DELTA( IP1 )*DW + B = DELTA( I )*DELTA( IP1 )*W + IF( C.EQ.ZERO ) THEN + IF( A.EQ.ZERO ) THEN + IF( ORGATI ) THEN + A = Z( I )*Z( I ) + DELTA( IP1 )*DELTA( IP1 )* + $ ( DPSI+DPHI ) + ELSE + A = Z( IP1 )*Z( IP1 ) + DELTA( I )*DELTA( I )* + $ ( DPSI+DPHI ) + END IF + END IF + ETA = B / A + ELSE IF( A.LE.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 + ELSE +* +* Interpolation using THREE most relevant poles +* + TEMP = RHOINV + PSI + PHI + IF( ORGATI ) THEN + TEMP1 = Z( IIM1 ) / DELTA( IIM1 ) + TEMP1 = TEMP1*TEMP1 + C = TEMP - DELTA( IIP1 )*( DPSI+DPHI ) - + $ ( D( IIM1 )-D( IIP1 ) )*TEMP1 + ZZ( 1 ) = Z( IIM1 )*Z( IIM1 ) + ZZ( 3 ) = DELTA( IIP1 )*DELTA( IIP1 )* + $ ( ( DPSI-TEMP1 )+DPHI ) + ELSE + TEMP1 = Z( IIP1 ) / DELTA( IIP1 ) + TEMP1 = TEMP1*TEMP1 + C = TEMP - DELTA( IIM1 )*( DPSI+DPHI ) - + $ ( D( IIP1 )-D( IIM1 ) )*TEMP1 + ZZ( 1 ) = DELTA( IIM1 )*DELTA( IIM1 )* + $ ( DPSI+( DPHI-TEMP1 ) ) + ZZ( 3 ) = Z( IIP1 )*Z( IIP1 ) + END IF + ZZ( 2 ) = Z( II )*Z( II ) + CALL SLAED6( NITER, ORGATI, C, DELTA( IIM1 ), ZZ, W, ETA, + $ INFO ) + IF( INFO.NE.0 ) + $ GO TO 250 + 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.GE.ZERO ) + $ ETA = -W / DW + TEMP = TAU + ETA + IF( TEMP.GT.DLTUB .OR. TEMP.LT.DLTLB ) THEN + IF( W.LT.ZERO ) THEN + ETA = ( DLTUB-TAU ) / TWO + ELSE + ETA = ( DLTLB-TAU ) / TWO + END IF + END IF +* + PREW = W +* + DO 180 J = 1, N + DELTA( J ) = DELTA( J ) - ETA + 180 CONTINUE +* +* Evaluate PSI and the derivative DPSI +* + DPSI = ZERO + PSI = ZERO + ERRETM = ZERO + DO 190 J = 1, IIM1 + TEMP = Z( J ) / DELTA( J ) + PSI = PSI + Z( J )*TEMP + DPSI = DPSI + TEMP*TEMP + ERRETM = ERRETM + PSI + 190 CONTINUE + ERRETM = ABS( ERRETM ) +* +* Evaluate PHI and the derivative DPHI +* + DPHI = ZERO + PHI = ZERO + DO 200 J = N, IIP1, -1 + TEMP = Z( J ) / DELTA( J ) + PHI = PHI + Z( J )*TEMP + DPHI = DPHI + TEMP*TEMP + ERRETM = ERRETM + PHI + 200 CONTINUE +* + TEMP = Z( II ) / DELTA( II ) + DW = DPSI + DPHI + TEMP*TEMP + TEMP = Z( II )*TEMP + W = RHOINV + PHI + PSI + TEMP + ERRETM = EIGHT*( PHI-PSI ) + ERRETM + TWO*RHOINV + + $ THREE*ABS( TEMP ) + ABS( TAU+ETA )*DW +* + SWTCH = .FALSE. + IF( ORGATI ) THEN + IF( -W.GT.ABS( PREW ) / TEN ) + $ SWTCH = .TRUE. + ELSE + IF( W.GT.ABS( PREW ) / TEN ) + $ SWTCH = .TRUE. + END IF +* + TAU = TAU + ETA +* +* Main loop to update the values of the array DELTA +* + ITER = NITER + 1 +* + DO 240 NITER = ITER, MAXIT +* +* Test for convergence +* + IF( ABS( W ).LE.EPS*ERRETM ) THEN + IF( ORGATI ) THEN + DLAM = D( I ) + TAU + ELSE + DLAM = D( IP1 ) + TAU + END IF + GO TO 250 + END IF +* + IF( W.LE.ZERO ) THEN + DLTLB = MAX( DLTLB, TAU ) + ELSE + DLTUB = MIN( DLTUB, TAU ) + END IF +* +* Calculate the new step +* + IF( .NOT.SWTCH3 ) THEN + IF( .NOT.SWTCH ) THEN + IF( ORGATI ) THEN + C = W - DELTA( IP1 )*DW - + $ ( D( I )-D( IP1 ) )*( Z( I ) / DELTA( I ) )**2 + ELSE + C = W - DELTA( I )*DW - ( D( IP1 )-D( I ) )* + $ ( Z( IP1 ) / DELTA( IP1 ) )**2 + END IF + ELSE + TEMP = Z( II ) / DELTA( II ) + IF( ORGATI ) THEN + DPSI = DPSI + TEMP*TEMP + ELSE + DPHI = DPHI + TEMP*TEMP + END IF + C = W - DELTA( I )*DPSI - DELTA( IP1 )*DPHI + END IF + A = ( DELTA( I )+DELTA( IP1 ) )*W - + $ DELTA( I )*DELTA( IP1 )*DW + B = DELTA( I )*DELTA( IP1 )*W + IF( C.EQ.ZERO ) THEN + IF( A.EQ.ZERO ) THEN + IF( .NOT.SWTCH ) THEN + IF( ORGATI ) THEN + A = Z( I )*Z( I ) + DELTA( IP1 )* + $ DELTA( IP1 )*( DPSI+DPHI ) + ELSE + A = Z( IP1 )*Z( IP1 ) + + $ DELTA( I )*DELTA( I )*( DPSI+DPHI ) + END IF + ELSE + A = DELTA( I )*DELTA( I )*DPSI + + $ DELTA( IP1 )*DELTA( IP1 )*DPHI + END IF + END IF + ETA = B / A + ELSE IF( A.LE.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 + ELSE +* +* Interpolation using THREE most relevant poles +* + TEMP = RHOINV + PSI + PHI + IF( SWTCH ) THEN + C = TEMP - DELTA( IIM1 )*DPSI - DELTA( IIP1 )*DPHI + ZZ( 1 ) = DELTA( IIM1 )*DELTA( IIM1 )*DPSI + ZZ( 3 ) = DELTA( IIP1 )*DELTA( IIP1 )*DPHI + ELSE + IF( ORGATI ) THEN + TEMP1 = Z( IIM1 ) / DELTA( IIM1 ) + TEMP1 = TEMP1*TEMP1 + C = TEMP - DELTA( IIP1 )*( DPSI+DPHI ) - + $ ( D( IIM1 )-D( IIP1 ) )*TEMP1 + ZZ( 1 ) = Z( IIM1 )*Z( IIM1 ) + ZZ( 3 ) = DELTA( IIP1 )*DELTA( IIP1 )* + $ ( ( DPSI-TEMP1 )+DPHI ) + ELSE + TEMP1 = Z( IIP1 ) / DELTA( IIP1 ) + TEMP1 = TEMP1*TEMP1 + C = TEMP - DELTA( IIM1 )*( DPSI+DPHI ) - + $ ( D( IIP1 )-D( IIM1 ) )*TEMP1 + ZZ( 1 ) = DELTA( IIM1 )*DELTA( IIM1 )* + $ ( DPSI+( DPHI-TEMP1 ) ) + ZZ( 3 ) = Z( IIP1 )*Z( IIP1 ) + END IF + END IF + CALL SLAED6( NITER, ORGATI, C, DELTA( IIM1 ), ZZ, W, ETA, + $ INFO ) + IF( INFO.NE.0 ) + $ GO TO 250 + 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.GE.ZERO ) + $ ETA = -W / DW + TEMP = TAU + ETA + IF( TEMP.GT.DLTUB .OR. TEMP.LT.DLTLB ) THEN + IF( W.LT.ZERO ) THEN + ETA = ( DLTUB-TAU ) / TWO + ELSE + ETA = ( DLTLB-TAU ) / TWO + END IF + END IF +* + DO 210 J = 1, N + DELTA( J ) = DELTA( J ) - ETA + 210 CONTINUE +* + TAU = TAU + ETA + PREW = W +* +* Evaluate PSI and the derivative DPSI +* + DPSI = ZERO + PSI = ZERO + ERRETM = ZERO + DO 220 J = 1, IIM1 + TEMP = Z( J ) / DELTA( J ) + PSI = PSI + Z( J )*TEMP + DPSI = DPSI + TEMP*TEMP + ERRETM = ERRETM + PSI + 220 CONTINUE + ERRETM = ABS( ERRETM ) +* +* Evaluate PHI and the derivative DPHI +* + DPHI = ZERO + PHI = ZERO + DO 230 J = N, IIP1, -1 + TEMP = Z( J ) / DELTA( J ) + PHI = PHI + Z( J )*TEMP + DPHI = DPHI + TEMP*TEMP + ERRETM = ERRETM + PHI + 230 CONTINUE +* + TEMP = Z( II ) / DELTA( II ) + DW = DPSI + DPHI + TEMP*TEMP + TEMP = Z( II )*TEMP + W = RHOINV + PHI + PSI + TEMP + ERRETM = EIGHT*( PHI-PSI ) + ERRETM + TWO*RHOINV + + $ THREE*ABS( TEMP ) + ABS( TAU )*DW + IF( W*PREW.GT.ZERO .AND. ABS( W ).GT.ABS( PREW ) / TEN ) + $ SWTCH = .NOT.SWTCH +* + 240 CONTINUE +* +* Return with INFO = 1, NITER = MAXIT and not converged +* + INFO = 1 + IF( ORGATI ) THEN + DLAM = D( I ) + TAU + ELSE + DLAM = D( IP1 ) + TAU + END IF +* + END IF +* + 250 CONTINUE +* + RETURN +* +* End of SLAED4 +* + END |