1       SUBROUTINE DLAED6( KNITER, ORGATI, RHO, D, Z, FINIT, TAU, INFO )
  2 *
  3 *  -- LAPACK routine (version 3.2) --
  4 *  -- LAPACK is a software package provided by Univ. of Tennessee,    --
  5 *  -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..--
  6 *     February 2007
  7 *
  8 *     .. Scalar Arguments ..
  9       LOGICAL            ORGATI
 10       INTEGER            INFO, KNITER
 11       DOUBLE PRECISION   FINIT, RHO, TAU
 12 *     ..
 13 *     .. Array Arguments ..
 14       DOUBLE PRECISION   D( 3 ), Z( 3 )
 15 *     ..
 16 *
 17 *  Purpose
 18 *  =======
 19 *
 20 *  DLAED6 computes the positive or negative root (closest to the origin)
 21 *  of
 22 *                   z(1)        z(2)        z(3)
 23 *  f(x) =   rho + --------- + ---------- + ---------
 24 *                  d(1)-x      d(2)-x      d(3)-x
 25 *
 26 *  It is assumed that
 27 *
 28 *        if ORGATI = .true. the root is between d(2) and d(3);
 29 *        otherwise it is between d(1) and d(2)
 30 *
 31 *  This routine will be called by DLAED4 when necessary. In most cases,
 32 *  the root sought is the smallest in magnitude, though it might not be
 33 *  in some extremely rare situations.
 34 *
 35 *  Arguments
 36 *  =========
 37 *
 38 *  KNITER       (input) INTEGER
 39 *               Refer to DLAED4 for its significance.
 40 *
 41 *  ORGATI       (input) LOGICAL
 42 *               If ORGATI is true, the needed root is between d(2) and
 43 *               d(3); otherwise it is between d(1) and d(2).  See
 44 *               DLAED4 for further details.
 45 *
 46 *  RHO          (input) DOUBLE PRECISION
 47 *               Refer to the equation f(x) above.
 48 *
 49 *  D            (input) DOUBLE PRECISION array, dimension (3)
 50 *               D satisfies d(1) < d(2) < d(3).
 51 *
 52 *  Z            (input) DOUBLE PRECISION array, dimension (3)
 53 *               Each of the elements in z must be positive.
 54 *
 55 *  FINIT        (input) DOUBLE PRECISION
 56 *               The value of f at 0. It is more accurate than the one
 57 *               evaluated inside this routine (if someone wants to do
 58 *               so).
 59 *
 60 *  TAU          (output) DOUBLE PRECISION
 61 *               The root of the equation f(x).
 62 *
 63 *  INFO         (output) INTEGER
 64 *               = 0: successful exit
 65 *               > 0: if INFO = 1, failure to converge
 66 *
 67 *  Further Details
 68 *  ===============
 69 *
 70 *  30/06/99: Based on contributions by
 71 *     Ren-Cang Li, Computer Science Division, University of California
 72 *     at Berkeley, USA
 73 *
 74 *  10/02/03: This version has a few statements commented out for thread
 75 *  safety (machine parameters are computed on each entry). SJH.
 76 *
 77 *  05/10/06: Modified from a new version of Ren-Cang Li, use
 78 *     Gragg-Thornton-Warner cubic convergent scheme for better stability.
 79 *
 80 *  =====================================================================
 81 *
 82 *     .. Parameters ..
 83       INTEGER            MAXIT
 84       PARAMETER          ( MAXIT = 40 )
 85       DOUBLE PRECISION   ZERO, ONE, TWO, THREE, FOUR, EIGHT
 86       PARAMETER          ( ZERO = 0.0D0, ONE = 1.0D0, TWO = 2.0D0,
 87      $                   THREE = 3.0D0, FOUR = 4.0D0, EIGHT = 8.0D0 )
 88 *     ..
 89 *     .. External Functions ..
 90       DOUBLE PRECISION   DLAMCH
 91       EXTERNAL           DLAMCH
 92 *     ..
 93 *     .. Local Arrays ..
 94       DOUBLE PRECISION   DSCALE( 3 ), ZSCALE( 3 )
 95 *     ..
 96 *     .. Local Scalars ..
 97       LOGICAL            SCALE
 98       INTEGER            I, ITER, NITER
 99       DOUBLE PRECISION   A, B, BASE, C, DDF, DF, EPS, ERRETM, ETA, F,
100      $                   FC, SCLFAC, SCLINV, SMALL1, SMALL2, SMINV1,
101      $                   SMINV2, TEMP, TEMP1, TEMP2, TEMP3, TEMP4, 
102      $                   LBD, UBD
103 *     ..
104 *     .. Intrinsic Functions ..
105       INTRINSIC          ABSINTLOGMAXMINSQRT
106 *     ..
107 *     .. Executable Statements ..
108 *
109       INFO = 0
110 *
111       IF( ORGATI ) THEN
112          LBD = D(2)
113          UBD = D(3)
114       ELSE
115          LBD = D(1)
116          UBD = D(2)
117       END IF
118       IF( FINIT .LT. ZERO )THEN
119          LBD = ZERO
120       ELSE
121          UBD = ZERO 
122       END IF
123 *
124       NITER = 1
125       TAU = ZERO
126       IF( KNITER.EQ.2 ) THEN
127          IF( ORGATI ) THEN
128             TEMP = ( D( 3 )-D( 2 ) ) / TWO
129             C = RHO + Z( 1 ) / ( ( D( 1 )-D( 2 ) )-TEMP )
130             A = C*( D( 2 )+D( 3 ) ) + Z( 2 ) + Z( 3 )
131             B = C*D( 2 )*D( 3 ) + Z( 2 )*D( 3 ) + Z( 3 )*D( 2 )
132          ELSE
133             TEMP = ( D( 1 )-D( 2 ) ) / TWO
134             C = RHO + Z( 3 ) / ( ( D( 3 )-D( 2 ) )-TEMP )
135             A = C*( D( 1 )+D( 2 ) ) + Z( 1 ) + Z( 2 )
136             B = C*D( 1 )*D( 2 ) + Z( 1 )*D( 2 ) + Z( 2 )*D( 1 )
137          END IF
138          TEMP = MAXABS( A ), ABS( B ), ABS( C ) )
139          A = A / TEMP
140          B = B / TEMP
141          C = C / TEMP
142          IF( C.EQ.ZERO ) THEN
143             TAU = B / A
144          ELSE IF( A.LE.ZERO ) THEN
145             TAU = ( A-SQRTABS( A*A-FOUR*B*C ) ) ) / ( TWO*C )
146          ELSE
147             TAU = TWO*/ ( A+SQRTABS( A*A-FOUR*B*C ) ) )
148          END IF
149          IF( TAU .LT. LBD .OR. TAU .GT. UBD )
150      $      TAU = ( LBD+UBD )/TWO
151          IF( D(1).EQ.TAU .OR. D(2).EQ.TAU .OR. D(3).EQ.TAU ) THEN
152             TAU = ZERO
153          ELSE
154             TEMP = FINIT + TAU*Z(1)/( D(1)*( D( 1 )-TAU ) ) +
155      $                     TAU*Z(2)/( D(2)*( D( 2 )-TAU ) ) +
156      $                     TAU*Z(3)/( D(3)*( D( 3 )-TAU ) )
157             IF( TEMP .LE. ZERO )THEN
158                LBD = TAU
159             ELSE
160                UBD = TAU
161             END IF
162             IFABS( FINIT ).LE.ABS( TEMP ) )
163      $         TAU = ZERO
164          END IF
165       END IF
166 *
167 *     get machine parameters for possible scaling to avoid overflow
168 *
169 *     modified by Sven: parameters SMALL1, SMINV1, SMALL2,
170 *     SMINV2, EPS are not SAVEd anymore between one call to the
171 *     others but recomputed at each call
172 *
173       EPS = DLAMCH( 'Epsilon' )
174       BASE = DLAMCH( 'Base' )
175       SMALL1 = BASE**INTLOG( DLAMCH( 'SafMin' ) ) / LOG( BASE ) /
176      $         THREE ) )
177       SMINV1 = ONE / SMALL1
178       SMALL2 = SMALL1*SMALL1
179       SMINV2 = SMINV1*SMINV1
180 *
181 *     Determine if scaling of inputs necessary to avoid overflow
182 *     when computing 1/TEMP**3
183 *
184       IF( ORGATI ) THEN
185          TEMP = MINABS( D( 2 )-TAU ), ABS( D( 3 )-TAU ) )
186       ELSE
187          TEMP = MINABS( D( 1 )-TAU ), ABS( D( 2 )-TAU ) )
188       END IF
189       SCALE = .FALSE.
190       IF( TEMP.LE.SMALL1 ) THEN
191          SCALE = .TRUE.
192          IF( TEMP.LE.SMALL2 ) THEN
193 *
194 *        Scale up by power of radix nearest 1/SAFMIN**(2/3)
195 *
196             SCLFAC = SMINV2
197             SCLINV = SMALL2
198          ELSE
199 *
200 *        Scale up by power of radix nearest 1/SAFMIN**(1/3)
201 *
202             SCLFAC = SMINV1
203             SCLINV = SMALL1
204          END IF
205 *
206 *        Scaling up safe because D, Z, TAU scaled elsewhere to be O(1)
207 *
208          DO 10 I = 13
209             DSCALE( I ) = D( I )*SCLFAC
210             ZSCALE( I ) = Z( I )*SCLFAC
211    10    CONTINUE
212          TAU = TAU*SCLFAC
213          LBD = LBD*SCLFAC
214          UBD = UBD*SCLFAC
215       ELSE
216 *
217 *        Copy D and Z to DSCALE and ZSCALE
218 *
219          DO 20 I = 13
220             DSCALE( I ) = D( I )
221             ZSCALE( I ) = Z( I )
222    20    CONTINUE
223       END IF
224 *
225       FC = ZERO
226       DF = ZERO
227       DDF = ZERO
228       DO 30 I = 13
229          TEMP = ONE / ( DSCALE( I )-TAU )
230          TEMP1 = ZSCALE( I )*TEMP
231          TEMP2 = TEMP1*TEMP
232          TEMP3 = TEMP2*TEMP
233          FC = FC + TEMP1 / DSCALE( I )
234          DF = DF + TEMP2
235          DDF = DDF + TEMP3
236    30 CONTINUE
237       F = FINIT + TAU*FC
238 *
239       IFABS( F ).LE.ZERO )
240      $   GO TO 60
241       IF( F .LE. ZERO )THEN
242          LBD = TAU
243       ELSE
244          UBD = TAU
245       END IF
246 *
247 *        Iteration begins -- Use Gragg-Thornton-Warner cubic convergent
248 *                            scheme
249 *
250 *     It is not hard to see that
251 *
252 *           1) Iterations will go up monotonically
253 *              if FINIT < 0;
254 *
255 *           2) Iterations will go down monotonically
256 *              if FINIT > 0.
257 *
258       ITER = NITER + 1
259 *
260       DO 50 NITER = ITER, MAXIT
261 *
262          IF( ORGATI ) THEN
263             TEMP1 = DSCALE( 2 ) - TAU
264             TEMP2 = DSCALE( 3 ) - TAU
265          ELSE
266             TEMP1 = DSCALE( 1 ) - TAU
267             TEMP2 = DSCALE( 2 ) - TAU
268          END IF
269          A = ( TEMP1+TEMP2 )*- TEMP1*TEMP2*DF
270          B = TEMP1*TEMP2*F
271          C = F - ( TEMP1+TEMP2 )*DF + TEMP1*TEMP2*DDF
272          TEMP = MAXABS( A ), ABS( B ), ABS( C ) )
273          A = A / TEMP
274          B = B / TEMP
275          C = C / TEMP
276          IF( C.EQ.ZERO ) THEN
277             ETA = B / A
278          ELSE IF( A.LE.ZERO ) THEN
279             ETA = ( A-SQRTABS( A*A-FOUR*B*C ) ) ) / ( TWO*C )
280          ELSE
281             ETA = TWO*/ ( A+SQRTABS( A*A-FOUR*B*C ) ) )
282          END IF
283          IF( F*ETA.GE.ZERO ) THEN
284             ETA = -/ DF
285          END IF
286 *
287          TAU = TAU + ETA
288          IF( TAU .LT. LBD .OR. TAU .GT. UBD )
289      $      TAU = ( LBD + UBD )/TWO 
290 *
291          FC = ZERO
292          ERRETM = ZERO
293          DF = ZERO
294          DDF = ZERO
295          DO 40 I = 13
296             TEMP = ONE / ( DSCALE( I )-TAU )
297             TEMP1 = ZSCALE( I )*TEMP
298             TEMP2 = TEMP1*TEMP
299             TEMP3 = TEMP2*TEMP
300             TEMP4 = TEMP1 / DSCALE( I )
301             FC = FC + TEMP4
302             ERRETM = ERRETM + ABS( TEMP4 )
303             DF = DF + TEMP2
304             DDF = DDF + TEMP3
305    40    CONTINUE
306          F = FINIT + TAU*FC
307          ERRETM = EIGHT*ABS( FINIT )+ABS( TAU )*ERRETM ) +
308      $            ABS( TAU )*DF
309          IFABS( F ).LE.EPS*ERRETM )
310      $      GO TO 60
311          IF( F .LE. ZERO )THEN
312             LBD = TAU
313          ELSE
314             UBD = TAU
315          END IF
316    50 CONTINUE
317       INFO = 1
318    60 CONTINUE
319 *
320 *     Undo scaling
321 *
322       IFSCALE )
323      $   TAU = TAU*SCLINV
324       RETURN
325 *
326 *     End of DLAED6
327 *
328       END