dlarrf.c
Go to the documentation of this file.
00001 /* dlarrf.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 /* Table of constant values */
00017 
00018 static integer c__1 = 1;
00019 
00020 /* Subroutine */ int dlarrf_(integer *n, doublereal *d__, doublereal *l, 
00021         doublereal *ld, integer *clstrt, integer *clend, doublereal *w, 
00022         doublereal *wgap, doublereal *werr, doublereal *spdiam, doublereal *
00023         clgapl, doublereal *clgapr, doublereal *pivmin, doublereal *sigma, 
00024         doublereal *dplus, doublereal *lplus, doublereal *work, integer *info)
00025 {
00026     /* System generated locals */
00027     integer i__1;
00028     doublereal d__1, d__2, d__3;
00029 
00030     /* Builtin functions */
00031     double sqrt(doublereal);
00032 
00033     /* Local variables */
00034     integer i__;
00035     doublereal s, bestshift, smlgrowth, eps, tmp, max1, max2, rrr1, rrr2, 
00036             znm2, growthbound, fail, fact, oldp;
00037     integer indx;
00038     doublereal prod;
00039     integer ktry;
00040     doublereal fail2, avgap, ldmax, rdmax;
00041     integer shift;
00042     extern /* Subroutine */ int dcopy_(integer *, doublereal *, integer *, 
00043             doublereal *, integer *);
00044     logical dorrr1;
00045     extern doublereal dlamch_(char *);
00046     doublereal ldelta;
00047     logical nofail;
00048     doublereal mingap, lsigma, rdelta;
00049     extern logical disnan_(doublereal *);
00050     logical forcer;
00051     doublereal rsigma, clwdth;
00052     logical sawnan1, sawnan2, tryrrr1;
00053 
00054 
00055 /*  -- LAPACK auxiliary routine (version 3.2) -- */
00056 /*     Univ. of Tennessee, Univ. of California Berkeley and NAG Ltd.. */
00057 /*     November 2006 */
00058 /* * */
00059 /*     .. Scalar Arguments .. */
00060 /*     .. */
00061 /*     .. Array Arguments .. */
00062 /*     .. */
00063 
00064 /*  Purpose */
00065 /*  ======= */
00066 
00067 /*  Given the initial representation L D L^T and its cluster of close */
00068 /*  eigenvalues (in a relative measure), W( CLSTRT ), W( CLSTRT+1 ), ... */
00069 /*  W( CLEND ), DLARRF finds a new relatively robust representation */
00070 /*  L D L^T - SIGMA I = L(+) D(+) L(+)^T such that at least one of the */
00071 /*  eigenvalues of L(+) D(+) L(+)^T is relatively isolated. */
00072 
00073 /*  Arguments */
00074 /*  ========= */
00075 
00076 /*  N       (input) INTEGER */
00077 /*          The order of the matrix (subblock, if the matrix splitted). */
00078 
00079 /*  D       (input) DOUBLE PRECISION array, dimension (N) */
00080 /*          The N diagonal elements of the diagonal matrix D. */
00081 
00082 /*  L       (input) DOUBLE PRECISION array, dimension (N-1) */
00083 /*          The (N-1) subdiagonal elements of the unit bidiagonal */
00084 /*          matrix L. */
00085 
00086 /*  LD      (input) DOUBLE PRECISION array, dimension (N-1) */
00087 /*          The (N-1) elements L(i)*D(i). */
00088 
00089 /*  CLSTRT  (input) INTEGER */
00090 /*          The index of the first eigenvalue in the cluster. */
00091 
00092 /*  CLEND   (input) INTEGER */
00093 /*          The index of the last eigenvalue in the cluster. */
00094 
00095 /*  W       (input) DOUBLE PRECISION array, dimension >=  (CLEND-CLSTRT+1) */
00096 /*          The eigenvalue APPROXIMATIONS of L D L^T in ascending order. */
00097 /*          W( CLSTRT ) through W( CLEND ) form the cluster of relatively */
00098 /*          close eigenalues. */
00099 
00100 /*  WGAP    (input/output) DOUBLE PRECISION array, dimension >=  (CLEND-CLSTRT+1) */
00101 /*          The separation from the right neighbor eigenvalue in W. */
00102 
00103 /*  WERR    (input) DOUBLE PRECISION array, dimension >=  (CLEND-CLSTRT+1) */
00104 /*          WERR contain the semiwidth of the uncertainty */
00105 /*          interval of the corresponding eigenvalue APPROXIMATION in W */
00106 
00107 /*  SPDIAM (input) estimate of the spectral diameter obtained from the */
00108 /*          Gerschgorin intervals */
00109 
00110 /*  CLGAPL, CLGAPR (input) absolute gap on each end of the cluster. */
00111 /*          Set by the calling routine to protect against shifts too close */
00112 /*          to eigenvalues outside the cluster. */
00113 
00114 /*  PIVMIN  (input) DOUBLE PRECISION */
00115 /*          The minimum pivot allowed in the Sturm sequence. */
00116 
00117 /*  SIGMA   (output) DOUBLE PRECISION */
00118 /*          The shift used to form L(+) D(+) L(+)^T. */
00119 
00120 /*  DPLUS   (output) DOUBLE PRECISION array, dimension (N) */
00121 /*          The N diagonal elements of the diagonal matrix D(+). */
00122 
00123 /*  LPLUS   (output) DOUBLE PRECISION array, dimension (N-1) */
00124 /*          The first (N-1) elements of LPLUS contain the subdiagonal */
00125 /*          elements of the unit bidiagonal matrix L(+). */
00126 
00127 /*  WORK    (workspace) DOUBLE PRECISION array, dimension (2*N) */
00128 /*          Workspace. */
00129 
00130 /*  Further Details */
00131 /*  =============== */
00132 
00133 /*  Based on contributions by */
00134 /*     Beresford Parlett, University of California, Berkeley, USA */
00135 /*     Jim Demmel, University of California, Berkeley, USA */
00136 /*     Inderjit Dhillon, University of Texas, Austin, USA */
00137 /*     Osni Marques, LBNL/NERSC, USA */
00138 /*     Christof Voemel, University of California, Berkeley, USA */
00139 
00140 /*  ===================================================================== */
00141 
00142 /*     .. Parameters .. */
00143 /*     .. */
00144 /*     .. Local Scalars .. */
00145 /*     .. */
00146 /*     .. External Functions .. */
00147 /*     .. */
00148 /*     .. External Subroutines .. */
00149 /*     .. */
00150 /*     .. Intrinsic Functions .. */
00151 /*     .. */
00152 /*     .. Executable Statements .. */
00153 
00154     /* Parameter adjustments */
00155     --work;
00156     --lplus;
00157     --dplus;
00158     --werr;
00159     --wgap;
00160     --w;
00161     --ld;
00162     --l;
00163     --d__;
00164 
00165     /* Function Body */
00166     *info = 0;
00167     fact = 2.;
00168     eps = dlamch_("Precision");
00169     shift = 0;
00170     forcer = FALSE_;
00171 /*     Note that we cannot guarantee that for any of the shifts tried, */
00172 /*     the factorization has a small or even moderate element growth. */
00173 /*     There could be Ritz values at both ends of the cluster and despite */
00174 /*     backing off, there are examples where all factorizations tried */
00175 /*     (in IEEE mode, allowing zero pivots & infinities) have INFINITE */
00176 /*     element growth. */
00177 /*     For this reason, we should use PIVMIN in this subroutine so that at */
00178 /*     least the L D L^T factorization exists. It can be checked afterwards */
00179 /*     whether the element growth caused bad residuals/orthogonality. */
00180 /*     Decide whether the code should accept the best among all */
00181 /*     representations despite large element growth or signal INFO=1 */
00182     nofail = TRUE_;
00183 
00184 /*     Compute the average gap length of the cluster */
00185     clwdth = (d__1 = w[*clend] - w[*clstrt], abs(d__1)) + werr[*clend] + werr[
00186             *clstrt];
00187     avgap = clwdth / (doublereal) (*clend - *clstrt);
00188     mingap = min(*clgapl,*clgapr);
00189 /*     Initial values for shifts to both ends of cluster */
00190 /* Computing MIN */
00191     d__1 = w[*clstrt], d__2 = w[*clend];
00192     lsigma = min(d__1,d__2) - werr[*clstrt];
00193 /* Computing MAX */
00194     d__1 = w[*clstrt], d__2 = w[*clend];
00195     rsigma = max(d__1,d__2) + werr[*clend];
00196 /*     Use a small fudge to make sure that we really shift to the outside */
00197     lsigma -= abs(lsigma) * 4. * eps;
00198     rsigma += abs(rsigma) * 4. * eps;
00199 /*     Compute upper bounds for how much to back off the initial shifts */
00200     ldmax = mingap * .25 + *pivmin * 2.;
00201     rdmax = mingap * .25 + *pivmin * 2.;
00202 /* Computing MAX */
00203     d__1 = avgap, d__2 = wgap[*clstrt];
00204     ldelta = max(d__1,d__2) / fact;
00205 /* Computing MAX */
00206     d__1 = avgap, d__2 = wgap[*clend - 1];
00207     rdelta = max(d__1,d__2) / fact;
00208 
00209 /*     Initialize the record of the best representation found */
00210 
00211     s = dlamch_("S");
00212     smlgrowth = 1. / s;
00213     fail = (doublereal) (*n - 1) * mingap / (*spdiam * eps);
00214     fail2 = (doublereal) (*n - 1) * mingap / (*spdiam * sqrt(eps));
00215     bestshift = lsigma;
00216 
00217 /*     while (KTRY <= KTRYMAX) */
00218     ktry = 0;
00219     growthbound = *spdiam * 8.;
00220 L5:
00221     sawnan1 = FALSE_;
00222     sawnan2 = FALSE_;
00223 /*     Ensure that we do not back off too much of the initial shifts */
00224     ldelta = min(ldmax,ldelta);
00225     rdelta = min(rdmax,rdelta);
00226 /*     Compute the element growth when shifting to both ends of the cluster */
00227 /*     accept the shift if there is no element growth at one of the two ends */
00228 /*     Left end */
00229     s = -lsigma;
00230     dplus[1] = d__[1] + s;
00231     if (abs(dplus[1]) < *pivmin) {
00232         dplus[1] = -(*pivmin);
00233 /*        Need to set SAWNAN1 because refined RRR test should not be used */
00234 /*        in this case */
00235         sawnan1 = TRUE_;
00236     }
00237     max1 = abs(dplus[1]);
00238     i__1 = *n - 1;
00239     for (i__ = 1; i__ <= i__1; ++i__) {
00240         lplus[i__] = ld[i__] / dplus[i__];
00241         s = s * lplus[i__] * l[i__] - lsigma;
00242         dplus[i__ + 1] = d__[i__ + 1] + s;
00243         if ((d__1 = dplus[i__ + 1], abs(d__1)) < *pivmin) {
00244             dplus[i__ + 1] = -(*pivmin);
00245 /*           Need to set SAWNAN1 because refined RRR test should not be used */
00246 /*           in this case */
00247             sawnan1 = TRUE_;
00248         }
00249 /* Computing MAX */
00250         d__2 = max1, d__3 = (d__1 = dplus[i__ + 1], abs(d__1));
00251         max1 = max(d__2,d__3);
00252 /* L6: */
00253     }
00254     sawnan1 = sawnan1 || disnan_(&max1);
00255     if (forcer || max1 <= growthbound && ! sawnan1) {
00256         *sigma = lsigma;
00257         shift = 1;
00258         goto L100;
00259     }
00260 /*     Right end */
00261     s = -rsigma;
00262     work[1] = d__[1] + s;
00263     if (abs(work[1]) < *pivmin) {
00264         work[1] = -(*pivmin);
00265 /*        Need to set SAWNAN2 because refined RRR test should not be used */
00266 /*        in this case */
00267         sawnan2 = TRUE_;
00268     }
00269     max2 = abs(work[1]);
00270     i__1 = *n - 1;
00271     for (i__ = 1; i__ <= i__1; ++i__) {
00272         work[*n + i__] = ld[i__] / work[i__];
00273         s = s * work[*n + i__] * l[i__] - rsigma;
00274         work[i__ + 1] = d__[i__ + 1] + s;
00275         if ((d__1 = work[i__ + 1], abs(d__1)) < *pivmin) {
00276             work[i__ + 1] = -(*pivmin);
00277 /*           Need to set SAWNAN2 because refined RRR test should not be used */
00278 /*           in this case */
00279             sawnan2 = TRUE_;
00280         }
00281 /* Computing MAX */
00282         d__2 = max2, d__3 = (d__1 = work[i__ + 1], abs(d__1));
00283         max2 = max(d__2,d__3);
00284 /* L7: */
00285     }
00286     sawnan2 = sawnan2 || disnan_(&max2);
00287     if (forcer || max2 <= growthbound && ! sawnan2) {
00288         *sigma = rsigma;
00289         shift = 2;
00290         goto L100;
00291     }
00292 /*     If we are at this point, both shifts led to too much element growth */
00293 /*     Record the better of the two shifts (provided it didn't lead to NaN) */
00294     if (sawnan1 && sawnan2) {
00295 /*        both MAX1 and MAX2 are NaN */
00296         goto L50;
00297     } else {
00298         if (! sawnan1) {
00299             indx = 1;
00300             if (max1 <= smlgrowth) {
00301                 smlgrowth = max1;
00302                 bestshift = lsigma;
00303             }
00304         }
00305         if (! sawnan2) {
00306             if (sawnan1 || max2 <= max1) {
00307                 indx = 2;
00308             }
00309             if (max2 <= smlgrowth) {
00310                 smlgrowth = max2;
00311                 bestshift = rsigma;
00312             }
00313         }
00314     }
00315 /*     If we are here, both the left and the right shift led to */
00316 /*     element growth. If the element growth is moderate, then */
00317 /*     we may still accept the representation, if it passes a */
00318 /*     refined test for RRR. This test supposes that no NaN occurred. */
00319 /*     Moreover, we use the refined RRR test only for isolated clusters. */
00320     if (clwdth < mingap / 128. && min(max1,max2) < fail2 && ! sawnan1 && ! 
00321             sawnan2) {
00322         dorrr1 = TRUE_;
00323     } else {
00324         dorrr1 = FALSE_;
00325     }
00326     tryrrr1 = TRUE_;
00327     if (tryrrr1 && dorrr1) {
00328         if (indx == 1) {
00329             tmp = (d__1 = dplus[*n], abs(d__1));
00330             znm2 = 1.;
00331             prod = 1.;
00332             oldp = 1.;
00333             for (i__ = *n - 1; i__ >= 1; --i__) {
00334                 if (prod <= eps) {
00335                     prod = dplus[i__ + 1] * work[*n + i__ + 1] / (dplus[i__] *
00336                              work[*n + i__]) * oldp;
00337                 } else {
00338                     prod *= (d__1 = work[*n + i__], abs(d__1));
00339                 }
00340                 oldp = prod;
00341 /* Computing 2nd power */
00342                 d__1 = prod;
00343                 znm2 += d__1 * d__1;
00344 /* Computing MAX */
00345                 d__2 = tmp, d__3 = (d__1 = dplus[i__] * prod, abs(d__1));
00346                 tmp = max(d__2,d__3);
00347 /* L15: */
00348             }
00349             rrr1 = tmp / (*spdiam * sqrt(znm2));
00350             if (rrr1 <= 8.) {
00351                 *sigma = lsigma;
00352                 shift = 1;
00353                 goto L100;
00354             }
00355         } else if (indx == 2) {
00356             tmp = (d__1 = work[*n], abs(d__1));
00357             znm2 = 1.;
00358             prod = 1.;
00359             oldp = 1.;
00360             for (i__ = *n - 1; i__ >= 1; --i__) {
00361                 if (prod <= eps) {
00362                     prod = work[i__ + 1] * lplus[i__ + 1] / (work[i__] * 
00363                             lplus[i__]) * oldp;
00364                 } else {
00365                     prod *= (d__1 = lplus[i__], abs(d__1));
00366                 }
00367                 oldp = prod;
00368 /* Computing 2nd power */
00369                 d__1 = prod;
00370                 znm2 += d__1 * d__1;
00371 /* Computing MAX */
00372                 d__2 = tmp, d__3 = (d__1 = work[i__] * prod, abs(d__1));
00373                 tmp = max(d__2,d__3);
00374 /* L16: */
00375             }
00376             rrr2 = tmp / (*spdiam * sqrt(znm2));
00377             if (rrr2 <= 8.) {
00378                 *sigma = rsigma;
00379                 shift = 2;
00380                 goto L100;
00381             }
00382         }
00383     }
00384 L50:
00385     if (ktry < 1) {
00386 /*        If we are here, both shifts failed also the RRR test. */
00387 /*        Back off to the outside */
00388 /* Computing MAX */
00389         d__1 = lsigma - ldelta, d__2 = lsigma - ldmax;
00390         lsigma = max(d__1,d__2);
00391 /* Computing MIN */
00392         d__1 = rsigma + rdelta, d__2 = rsigma + rdmax;
00393         rsigma = min(d__1,d__2);
00394         ldelta *= 2.;
00395         rdelta *= 2.;
00396         ++ktry;
00397         goto L5;
00398     } else {
00399 /*        None of the representations investigated satisfied our */
00400 /*        criteria. Take the best one we found. */
00401         if (smlgrowth < fail || nofail) {
00402             lsigma = bestshift;
00403             rsigma = bestshift;
00404             forcer = TRUE_;
00405             goto L5;
00406         } else {
00407             *info = 1;
00408             return 0;
00409         }
00410     }
00411 L100:
00412     if (shift == 1) {
00413     } else if (shift == 2) {
00414 /*        store new L and D back into DPLUS, LPLUS */
00415         dcopy_(n, &work[1], &c__1, &dplus[1], &c__1);
00416         i__1 = *n - 1;
00417         dcopy_(&i__1, &work[*n + 1], &c__1, &lplus[1], &c__1);
00418     }
00419     return 0;
00420 
00421 /*     End of DLARRF */
00422 
00423 } /* dlarrf_ */


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