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


swiftnav
Author(s):
autogenerated on Sat Jun 8 2019 18:56:11