3 /* Subroutine */ int slaed6_(integer *kniter, logical *orgati, real *rho,
4 real *d__, real *z__, real *finit, real *tau, integer *info)
6 /* System generated locals */
8 real r__1, r__2, r__3, r__4;
10 /* Builtin functions */
11 double sqrt(doublereal), log(doublereal), pow_ri(real *, integer *);
16 real fc, df, ddf, lbd, eta, ubd, eps, base;
18 real temp, temp1, temp2, temp3, temp4;
21 real small1, small2, sminv1, sminv2, dscale[3], sclfac;
22 extern doublereal slamch_(char *);
23 real zscale[3], erretm, sclinv;
26 /* -- LAPACK routine (version 3.1.1) -- */
27 /* Univ. of Tennessee, Univ. of California Berkeley and NAG Ltd.. */
30 /* .. Scalar Arguments .. */
32 /* .. Array Arguments .. */
38 /* SLAED6 computes the positive or negative root (closest to the origin) */
41 /* f(x) = rho + --------- + ---------- + --------- */
42 /* d(1)-x d(2)-x d(3)-x */
44 /* It is assumed that */
46 /* if ORGATI = .true. the root is between d(2) and d(3); */
47 /* otherwise it is between d(1) and d(2) */
49 /* This routine will be called by SLAED4 when necessary. In most cases, */
50 /* the root sought is the smallest in magnitude, though it might not be */
51 /* in some extremely rare situations. */
56 /* KNITER (input) INTEGER */
57 /* Refer to SLAED4 for its significance. */
59 /* ORGATI (input) LOGICAL */
60 /* If ORGATI is true, the needed root is between d(2) and */
61 /* d(3); otherwise it is between d(1) and d(2). See */
62 /* SLAED4 for further details. */
64 /* RHO (input) REAL */
65 /* Refer to the equation f(x) above. */
67 /* D (input) REAL array, dimension (3) */
68 /* D satisfies d(1) < d(2) < d(3). */
70 /* Z (input) REAL array, dimension (3) */
71 /* Each of the elements in z must be positive. */
73 /* FINIT (input) REAL */
74 /* The value of f at 0. It is more accurate than the one */
75 /* evaluated inside this routine (if someone wants to do */
78 /* TAU (output) REAL */
79 /* The root of the equation f(x). */
81 /* INFO (output) INTEGER */
82 /* = 0: successful exit */
83 /* > 0: if INFO = 1, failure to converge */
88 /* 30/06/99: Based on contributions by */
89 /* Ren-Cang Li, Computer Science Division, University of California */
90 /* at Berkeley, USA */
92 /* 10/02/03: This version has a few statements commented out for thread safety */
93 /* (machine parameters are computed on each entry). SJH. */
95 /* 05/10/06: Modified from a new version of Ren-Cang Li, use */
96 /* Gragg-Thornton-Warner cubic convergent scheme for better stability. */
98 /* ===================================================================== */
100 /* .. Parameters .. */
102 /* .. External Functions .. */
104 /* .. Local Arrays .. */
106 /* .. Local Scalars .. */
108 /* .. Intrinsic Functions .. */
110 /* .. Executable Statements .. */
112 /* Parameter adjustments */
136 temp = (d__[3] - d__[2]) / 2.f;
137 c__ = *rho + z__[1] / (d__[1] - d__[2] - temp);
138 a = c__ * (d__[2] + d__[3]) + z__[2] + z__[3];
139 b = c__ * d__[2] * d__[3] + z__[2] * d__[3] + z__[3] * d__[2];
141 temp = (d__[1] - d__[2]) / 2.f;
142 c__ = *rho + z__[3] / (d__[3] - d__[2] - temp);
143 a = c__ * (d__[1] + d__[2]) + z__[1] + z__[2];
144 b = c__ * d__[1] * d__[2] + z__[1] * d__[2] + z__[2] * d__[1];
147 r__1 = dabs(a), r__2 = dabs(b), r__1 = max(r__1,r__2), r__2 = dabs(
149 temp = dmax(r__1,r__2);
155 } else if (a <= 0.f) {
156 *tau = (a - sqrt((r__1 = a * a - b * 4.f * c__, dabs(r__1)))) / (
159 *tau = b * 2.f / (a + sqrt((r__1 = a * a - b * 4.f * c__, dabs(
162 if (*tau < lbd || *tau > ubd) {
163 *tau = (lbd + ubd) / 2.f;
165 if (d__[1] == *tau || d__[2] == *tau || d__[3] == *tau) {
168 temp = *finit + *tau * z__[1] / (d__[1] * (d__[1] - *tau)) + *tau
169 * z__[2] / (d__[2] * (d__[2] - *tau)) + *tau * z__[3] / (
170 d__[3] * (d__[3] - *tau));
176 if (dabs(*finit) <= dabs(temp)) {
182 /* get machine parameters for possible scaling to avoid overflow */
184 /* modified by Sven: parameters SMALL1, SMINV1, SMALL2, */
185 /* SMINV2, EPS are not SAVEd anymore between one call to the */
186 /* others but recomputed at each call */
188 eps = slamch_("Epsilon");
189 base = slamch_("Base");
190 i__1 = (integer) (log(slamch_("SafMin")) / log(base) / 3.f);
191 small1 = pow_ri(&base, &i__1);
192 sminv1 = 1.f / small1;
193 small2 = small1 * small1;
194 sminv2 = sminv1 * sminv1;
196 /* Determine if scaling of inputs necessary to avoid overflow */
197 /* when computing 1/TEMP**3 */
201 r__3 = (r__1 = d__[2] - *tau, dabs(r__1)), r__4 = (r__2 = d__[3] - *
203 temp = dmin(r__3,r__4);
206 r__3 = (r__1 = d__[1] - *tau, dabs(r__1)), r__4 = (r__2 = d__[2] - *
208 temp = dmin(r__3,r__4);
211 if (temp <= small1) {
213 if (temp <= small2) {
215 /* Scale up by power of radix nearest 1/SAFMIN**(2/3) */
221 /* Scale up by power of radix nearest 1/SAFMIN**(1/3) */
227 /* Scaling up safe because D, Z, TAU scaled elsewhere to be O(1) */
229 for (i__ = 1; i__ <= 3; ++i__) {
230 dscale[i__ - 1] = d__[i__] * sclfac;
231 zscale[i__ - 1] = z__[i__] * sclfac;
239 /* Copy D and Z to DSCALE and ZSCALE */
241 for (i__ = 1; i__ <= 3; ++i__) {
242 dscale[i__ - 1] = d__[i__];
243 zscale[i__ - 1] = z__[i__];
251 for (i__ = 1; i__ <= 3; ++i__) {
252 temp = 1.f / (dscale[i__ - 1] - *tau);
253 temp1 = zscale[i__ - 1] * temp;
254 temp2 = temp1 * temp;
255 temp3 = temp2 * temp;
256 fc += temp1 / dscale[i__ - 1];
261 f = *finit + *tau * fc;
263 if (dabs(f) <= 0.f) {
272 /* Iteration begins -- Use Gragg-Thornton-Warner cubic convergent */
275 /* It is not hard to see that */
277 /* 1) Iterations will go up monotonically */
280 /* 2) Iterations will go down monotonically */
285 for (niter = iter; niter <= 40; ++niter) {
288 temp1 = dscale[1] - *tau;
289 temp2 = dscale[2] - *tau;
291 temp1 = dscale[0] - *tau;
292 temp2 = dscale[1] - *tau;
294 a = (temp1 + temp2) * f - temp1 * temp2 * df;
295 b = temp1 * temp2 * f;
296 c__ = f - (temp1 + temp2) * df + temp1 * temp2 * ddf;
298 r__1 = dabs(a), r__2 = dabs(b), r__1 = max(r__1,r__2), r__2 = dabs(
300 temp = dmax(r__1,r__2);
306 } else if (a <= 0.f) {
307 eta = (a - sqrt((r__1 = a * a - b * 4.f * c__, dabs(r__1)))) / (
310 eta = b * 2.f / (a + sqrt((r__1 = a * a - b * 4.f * c__, dabs(
313 if (f * eta >= 0.f) {
318 if (*tau < lbd || *tau > ubd) {
319 *tau = (lbd + ubd) / 2.f;
326 for (i__ = 1; i__ <= 3; ++i__) {
327 temp = 1.f / (dscale[i__ - 1] - *tau);
328 temp1 = zscale[i__ - 1] * temp;
329 temp2 = temp1 * temp;
330 temp3 = temp2 * temp;
331 temp4 = temp1 / dscale[i__ - 1];
333 erretm += dabs(temp4);
338 f = *finit + *tau * fc;
339 erretm = (dabs(*finit) + dabs(*tau) * erretm) * 8.f + dabs(*tau) * df;
340 if (dabs(f) <= eps * erretm) {