dlaed6.c
Go to the documentation of this file.
00001 /* dlaed6.f -- translated by f2c (version 20061008).
00002    You must link the resulting object file with libf2c:
00003         on Microsoft Windows system, link with libf2c.lib;
00004         on Linux or Unix systems, link with .../path/to/libf2c.a -lm
00005         or, if you install libf2c.a in a standard place, with -lf2c -lm
00006         -- in that order, at the end of the command line, as in
00007                 cc *.o -lf2c -lm
00008         Source for libf2c is in /netlib/f2c/libf2c.zip, e.g.,
00009 
00010                 http://www.netlib.org/f2c/libf2c.zip
00011 */
00012 
00013 #include "f2c.h"
00014 #include "blaswrap.h"
00015 
00016 /* Subroutine */ int dlaed6_(integer *kniter, logical *orgati, doublereal *
00017         rho, doublereal *d__, doublereal *z__, doublereal *finit, doublereal *
00018         tau, integer *info)
00019 {
00020     /* System generated locals */
00021     integer i__1;
00022     doublereal d__1, d__2, d__3, d__4;
00023 
00024     /* Builtin functions */
00025     double sqrt(doublereal), log(doublereal), pow_di(doublereal *, integer *);
00026 
00027     /* Local variables */
00028     doublereal a, b, c__, f;
00029     integer i__;
00030     doublereal fc, df, ddf, lbd, eta, ubd, eps, base;
00031     integer iter;
00032     doublereal temp, temp1, temp2, temp3, temp4;
00033     logical scale;
00034     integer niter;
00035     doublereal small1, small2, sminv1, sminv2;
00036     extern doublereal dlamch_(char *);
00037     doublereal dscale[3], sclfac, zscale[3], erretm, sclinv;
00038 
00039 
00040 /*  -- LAPACK routine (version 3.2) -- */
00041 /*     Univ. of Tennessee, Univ. of California Berkeley and NAG Ltd.. */
00042 /*     February 2007 */
00043 
00044 /*     .. Scalar Arguments .. */
00045 /*     .. */
00046 /*     .. Array Arguments .. */
00047 /*     .. */
00048 
00049 /*  Purpose */
00050 /*  ======= */
00051 
00052 /*  DLAED6 computes the positive or negative root (closest to the origin) */
00053 /*  of */
00054 /*                   z(1)        z(2)        z(3) */
00055 /*  f(x) =   rho + --------- + ---------- + --------- */
00056 /*                  d(1)-x      d(2)-x      d(3)-x */
00057 
00058 /*  It is assumed that */
00059 
00060 /*        if ORGATI = .true. the root is between d(2) and d(3); */
00061 /*        otherwise it is between d(1) and d(2) */
00062 
00063 /*  This routine will be called by DLAED4 when necessary. In most cases, */
00064 /*  the root sought is the smallest in magnitude, though it might not be */
00065 /*  in some extremely rare situations. */
00066 
00067 /*  Arguments */
00068 /*  ========= */
00069 
00070 /*  KNITER       (input) INTEGER */
00071 /*               Refer to DLAED4 for its significance. */
00072 
00073 /*  ORGATI       (input) LOGICAL */
00074 /*               If ORGATI is true, the needed root is between d(2) and */
00075 /*               d(3); otherwise it is between d(1) and d(2).  See */
00076 /*               DLAED4 for further details. */
00077 
00078 /*  RHO          (input) DOUBLE PRECISION */
00079 /*               Refer to the equation f(x) above. */
00080 
00081 /*  D            (input) DOUBLE PRECISION array, dimension (3) */
00082 /*               D satisfies d(1) < d(2) < d(3). */
00083 
00084 /*  Z            (input) DOUBLE PRECISION array, dimension (3) */
00085 /*               Each of the elements in z must be positive. */
00086 
00087 /*  FINIT        (input) DOUBLE PRECISION */
00088 /*               The value of f at 0. It is more accurate than the one */
00089 /*               evaluated inside this routine (if someone wants to do */
00090 /*               so). */
00091 
00092 /*  TAU          (output) DOUBLE PRECISION */
00093 /*               The root of the equation f(x). */
00094 
00095 /*  INFO         (output) INTEGER */
00096 /*               = 0: successful exit */
00097 /*               > 0: if INFO = 1, failure to converge */
00098 
00099 /*  Further Details */
00100 /*  =============== */
00101 
00102 /*  30/06/99: Based on contributions by */
00103 /*     Ren-Cang Li, Computer Science Division, University of California */
00104 /*     at Berkeley, USA */
00105 
00106 /*  10/02/03: This version has a few statements commented out for thread */
00107 /*  safety (machine parameters are computed on each entry). SJH. */
00108 
00109 /*  05/10/06: Modified from a new version of Ren-Cang Li, use */
00110 /*     Gragg-Thornton-Warner cubic convergent scheme for better stability. */
00111 
00112 /*  ===================================================================== */
00113 
00114 /*     .. Parameters .. */
00115 /*     .. */
00116 /*     .. External Functions .. */
00117 /*     .. */
00118 /*     .. Local Arrays .. */
00119 /*     .. */
00120 /*     .. Local Scalars .. */
00121 /*     .. */
00122 /*     .. Intrinsic Functions .. */
00123 /*     .. */
00124 /*     .. Executable Statements .. */
00125 
00126     /* Parameter adjustments */
00127     --z__;
00128     --d__;
00129 
00130     /* Function Body */
00131     *info = 0;
00132 
00133     if (*orgati) {
00134         lbd = d__[2];
00135         ubd = d__[3];
00136     } else {
00137         lbd = d__[1];
00138         ubd = d__[2];
00139     }
00140     if (*finit < 0.) {
00141         lbd = 0.;
00142     } else {
00143         ubd = 0.;
00144     }
00145 
00146     niter = 1;
00147     *tau = 0.;
00148     if (*kniter == 2) {
00149         if (*orgati) {
00150             temp = (d__[3] - d__[2]) / 2.;
00151             c__ = *rho + z__[1] / (d__[1] - d__[2] - temp);
00152             a = c__ * (d__[2] + d__[3]) + z__[2] + z__[3];
00153             b = c__ * d__[2] * d__[3] + z__[2] * d__[3] + z__[3] * d__[2];
00154         } else {
00155             temp = (d__[1] - d__[2]) / 2.;
00156             c__ = *rho + z__[3] / (d__[3] - d__[2] - temp);
00157             a = c__ * (d__[1] + d__[2]) + z__[1] + z__[2];
00158             b = c__ * d__[1] * d__[2] + z__[1] * d__[2] + z__[2] * d__[1];
00159         }
00160 /* Computing MAX */
00161         d__1 = abs(a), d__2 = abs(b), d__1 = max(d__1,d__2), d__2 = abs(c__);
00162         temp = max(d__1,d__2);
00163         a /= temp;
00164         b /= temp;
00165         c__ /= temp;
00166         if (c__ == 0.) {
00167             *tau = b / a;
00168         } else if (a <= 0.) {
00169             *tau = (a - sqrt((d__1 = a * a - b * 4. * c__, abs(d__1)))) / (
00170                     c__ * 2.);
00171         } else {
00172             *tau = b * 2. / (a + sqrt((d__1 = a * a - b * 4. * c__, abs(d__1))
00173                     ));
00174         }
00175         if (*tau < lbd || *tau > ubd) {
00176             *tau = (lbd + ubd) / 2.;
00177         }
00178         if (d__[1] == *tau || d__[2] == *tau || d__[3] == *tau) {
00179             *tau = 0.;
00180         } else {
00181             temp = *finit + *tau * z__[1] / (d__[1] * (d__[1] - *tau)) + *tau 
00182                     * z__[2] / (d__[2] * (d__[2] - *tau)) + *tau * z__[3] / (
00183                     d__[3] * (d__[3] - *tau));
00184             if (temp <= 0.) {
00185                 lbd = *tau;
00186             } else {
00187                 ubd = *tau;
00188             }
00189             if (abs(*finit) <= abs(temp)) {
00190                 *tau = 0.;
00191             }
00192         }
00193     }
00194 
00195 /*     get machine parameters for possible scaling to avoid overflow */
00196 
00197 /*     modified by Sven: parameters SMALL1, SMINV1, SMALL2, */
00198 /*     SMINV2, EPS are not SAVEd anymore between one call to the */
00199 /*     others but recomputed at each call */
00200 
00201     eps = dlamch_("Epsilon");
00202     base = dlamch_("Base");
00203     i__1 = (integer) (log(dlamch_("SafMin")) / log(base) / 3.);
00204     small1 = pow_di(&base, &i__1);
00205     sminv1 = 1. / small1;
00206     small2 = small1 * small1;
00207     sminv2 = sminv1 * sminv1;
00208 
00209 /*     Determine if scaling of inputs necessary to avoid overflow */
00210 /*     when computing 1/TEMP**3 */
00211 
00212     if (*orgati) {
00213 /* Computing MIN */
00214         d__3 = (d__1 = d__[2] - *tau, abs(d__1)), d__4 = (d__2 = d__[3] - *
00215                 tau, abs(d__2));
00216         temp = min(d__3,d__4);
00217     } else {
00218 /* Computing MIN */
00219         d__3 = (d__1 = d__[1] - *tau, abs(d__1)), d__4 = (d__2 = d__[2] - *
00220                 tau, abs(d__2));
00221         temp = min(d__3,d__4);
00222     }
00223     scale = FALSE_;
00224     if (temp <= small1) {
00225         scale = TRUE_;
00226         if (temp <= small2) {
00227 
00228 /*        Scale up by power of radix nearest 1/SAFMIN**(2/3) */
00229 
00230             sclfac = sminv2;
00231             sclinv = small2;
00232         } else {
00233 
00234 /*        Scale up by power of radix nearest 1/SAFMIN**(1/3) */
00235 
00236             sclfac = sminv1;
00237             sclinv = small1;
00238         }
00239 
00240 /*        Scaling up safe because D, Z, TAU scaled elsewhere to be O(1) */
00241 
00242         for (i__ = 1; i__ <= 3; ++i__) {
00243             dscale[i__ - 1] = d__[i__] * sclfac;
00244             zscale[i__ - 1] = z__[i__] * sclfac;
00245 /* L10: */
00246         }
00247         *tau *= sclfac;
00248         lbd *= sclfac;
00249         ubd *= sclfac;
00250     } else {
00251 
00252 /*        Copy D and Z to DSCALE and ZSCALE */
00253 
00254         for (i__ = 1; i__ <= 3; ++i__) {
00255             dscale[i__ - 1] = d__[i__];
00256             zscale[i__ - 1] = z__[i__];
00257 /* L20: */
00258         }
00259     }
00260 
00261     fc = 0.;
00262     df = 0.;
00263     ddf = 0.;
00264     for (i__ = 1; i__ <= 3; ++i__) {
00265         temp = 1. / (dscale[i__ - 1] - *tau);
00266         temp1 = zscale[i__ - 1] * temp;
00267         temp2 = temp1 * temp;
00268         temp3 = temp2 * temp;
00269         fc += temp1 / dscale[i__ - 1];
00270         df += temp2;
00271         ddf += temp3;
00272 /* L30: */
00273     }
00274     f = *finit + *tau * fc;
00275 
00276     if (abs(f) <= 0.) {
00277         goto L60;
00278     }
00279     if (f <= 0.) {
00280         lbd = *tau;
00281     } else {
00282         ubd = *tau;
00283     }
00284 
00285 /*        Iteration begins -- Use Gragg-Thornton-Warner cubic convergent */
00286 /*                            scheme */
00287 
00288 /*     It is not hard to see that */
00289 
00290 /*           1) Iterations will go up monotonically */
00291 /*              if FINIT < 0; */
00292 
00293 /*           2) Iterations will go down monotonically */
00294 /*              if FINIT > 0. */
00295 
00296     iter = niter + 1;
00297 
00298     for (niter = iter; niter <= 40; ++niter) {
00299 
00300         if (*orgati) {
00301             temp1 = dscale[1] - *tau;
00302             temp2 = dscale[2] - *tau;
00303         } else {
00304             temp1 = dscale[0] - *tau;
00305             temp2 = dscale[1] - *tau;
00306         }
00307         a = (temp1 + temp2) * f - temp1 * temp2 * df;
00308         b = temp1 * temp2 * f;
00309         c__ = f - (temp1 + temp2) * df + temp1 * temp2 * ddf;
00310 /* Computing MAX */
00311         d__1 = abs(a), d__2 = abs(b), d__1 = max(d__1,d__2), d__2 = abs(c__);
00312         temp = max(d__1,d__2);
00313         a /= temp;
00314         b /= temp;
00315         c__ /= temp;
00316         if (c__ == 0.) {
00317             eta = b / a;
00318         } else if (a <= 0.) {
00319             eta = (a - sqrt((d__1 = a * a - b * 4. * c__, abs(d__1)))) / (c__ 
00320                     * 2.);
00321         } else {
00322             eta = b * 2. / (a + sqrt((d__1 = a * a - b * 4. * c__, abs(d__1)))
00323                     );
00324         }
00325         if (f * eta >= 0.) {
00326             eta = -f / df;
00327         }
00328 
00329         *tau += eta;
00330         if (*tau < lbd || *tau > ubd) {
00331             *tau = (lbd + ubd) / 2.;
00332         }
00333 
00334         fc = 0.;
00335         erretm = 0.;
00336         df = 0.;
00337         ddf = 0.;
00338         for (i__ = 1; i__ <= 3; ++i__) {
00339             temp = 1. / (dscale[i__ - 1] - *tau);
00340             temp1 = zscale[i__ - 1] * temp;
00341             temp2 = temp1 * temp;
00342             temp3 = temp2 * temp;
00343             temp4 = temp1 / dscale[i__ - 1];
00344             fc += temp4;
00345             erretm += abs(temp4);
00346             df += temp2;
00347             ddf += temp3;
00348 /* L40: */
00349         }
00350         f = *finit + *tau * fc;
00351         erretm = (abs(*finit) + abs(*tau) * erretm) * 8. + abs(*tau) * df;
00352         if (abs(f) <= eps * erretm) {
00353             goto L60;
00354         }
00355         if (f <= 0.) {
00356             lbd = *tau;
00357         } else {
00358             ubd = *tau;
00359         }
00360 /* L50: */
00361     }
00362     *info = 1;
00363 L60:
00364 
00365 /*     Undo scaling */
00366 
00367     if (scale) {
00368         *tau *= sclinv;
00369     }
00370     return 0;
00371 
00372 /*     End of DLAED6 */
00373 
00374 } /* dlaed6_ */


swiftnav
Author(s):
autogenerated on Sat Jun 8 2019 18:55:46