dlar1v.c
Go to the documentation of this file.
00001 /* dlar1v.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 dlar1v_(integer *n, integer *b1, integer *bn, doublereal 
00017         *lambda, doublereal *d__, doublereal *l, doublereal *ld, doublereal *
00018         lld, doublereal *pivmin, doublereal *gaptol, doublereal *z__, logical 
00019         *wantnc, integer *negcnt, doublereal *ztz, doublereal *mingma, 
00020         integer *r__, integer *isuppz, doublereal *nrminv, doublereal *resid, 
00021         doublereal *rqcorr, doublereal *work)
00022 {
00023     /* System generated locals */
00024     integer i__1;
00025     doublereal d__1, d__2, d__3;
00026 
00027     /* Builtin functions */
00028     double sqrt(doublereal);
00029 
00030     /* Local variables */
00031     integer i__;
00032     doublereal s;
00033     integer r1, r2;
00034     doublereal eps, tmp;
00035     integer neg1, neg2, indp, inds;
00036     doublereal dplus;
00037     extern doublereal dlamch_(char *);
00038     extern logical disnan_(doublereal *);
00039     integer indlpl, indumn;
00040     doublereal dminus;
00041     logical sawnan1, sawnan2;
00042 
00043 
00044 /*  -- LAPACK auxiliary routine (version 3.2) -- */
00045 /*     Univ. of Tennessee, Univ. of California Berkeley and NAG Ltd.. */
00046 /*     November 2006 */
00047 
00048 /*     .. Scalar Arguments .. */
00049 /*     .. */
00050 /*     .. Array Arguments .. */
00051 /*     .. */
00052 
00053 /*  Purpose */
00054 /*  ======= */
00055 
00056 /*  DLAR1V computes the (scaled) r-th column of the inverse of */
00057 /*  the sumbmatrix in rows B1 through BN of the tridiagonal matrix */
00058 /*  L D L^T - sigma I. When sigma is close to an eigenvalue, the */
00059 /*  computed vector is an accurate eigenvector. Usually, r corresponds */
00060 /*  to the index where the eigenvector is largest in magnitude. */
00061 /*  The following steps accomplish this computation : */
00062 /*  (a) Stationary qd transform,  L D L^T - sigma I = L(+) D(+) L(+)^T, */
00063 /*  (b) Progressive qd transform, L D L^T - sigma I = U(-) D(-) U(-)^T, */
00064 /*  (c) Computation of the diagonal elements of the inverse of */
00065 /*      L D L^T - sigma I by combining the above transforms, and choosing */
00066 /*      r as the index where the diagonal of the inverse is (one of the) */
00067 /*      largest in magnitude. */
00068 /*  (d) Computation of the (scaled) r-th column of the inverse using the */
00069 /*      twisted factorization obtained by combining the top part of the */
00070 /*      the stationary and the bottom part of the progressive transform. */
00071 
00072 /*  Arguments */
00073 /*  ========= */
00074 
00075 /*  N        (input) INTEGER */
00076 /*           The order of the matrix L D L^T. */
00077 
00078 /*  B1       (input) INTEGER */
00079 /*           First index of the submatrix of L D L^T. */
00080 
00081 /*  BN       (input) INTEGER */
00082 /*           Last index of the submatrix of L D L^T. */
00083 
00084 /*  LAMBDA    (input) DOUBLE PRECISION */
00085 /*           The shift. In order to compute an accurate eigenvector, */
00086 /*           LAMBDA should be a good approximation to an eigenvalue */
00087 /*           of L D L^T. */
00088 
00089 /*  L        (input) DOUBLE PRECISION array, dimension (N-1) */
00090 /*           The (n-1) subdiagonal elements of the unit bidiagonal matrix */
00091 /*           L, in elements 1 to N-1. */
00092 
00093 /*  D        (input) DOUBLE PRECISION array, dimension (N) */
00094 /*           The n diagonal elements of the diagonal matrix D. */
00095 
00096 /*  LD       (input) DOUBLE PRECISION array, dimension (N-1) */
00097 /*           The n-1 elements L(i)*D(i). */
00098 
00099 /*  LLD      (input) DOUBLE PRECISION array, dimension (N-1) */
00100 /*           The n-1 elements L(i)*L(i)*D(i). */
00101 
00102 /*  PIVMIN   (input) DOUBLE PRECISION */
00103 /*           The minimum pivot in the Sturm sequence. */
00104 
00105 /*  GAPTOL   (input) DOUBLE PRECISION */
00106 /*           Tolerance that indicates when eigenvector entries are negligible */
00107 /*           w.r.t. their contribution to the residual. */
00108 
00109 /*  Z        (input/output) DOUBLE PRECISION array, dimension (N) */
00110 /*           On input, all entries of Z must be set to 0. */
00111 /*           On output, Z contains the (scaled) r-th column of the */
00112 /*           inverse. The scaling is such that Z(R) equals 1. */
00113 
00114 /*  WANTNC   (input) LOGICAL */
00115 /*           Specifies whether NEGCNT has to be computed. */
00116 
00117 /*  NEGCNT   (output) INTEGER */
00118 /*           If WANTNC is .TRUE. then NEGCNT = the number of pivots < pivmin */
00119 /*           in the  matrix factorization L D L^T, and NEGCNT = -1 otherwise. */
00120 
00121 /*  ZTZ      (output) DOUBLE PRECISION */
00122 /*           The square of the 2-norm of Z. */
00123 
00124 /*  MINGMA   (output) DOUBLE PRECISION */
00125 /*           The reciprocal of the largest (in magnitude) diagonal */
00126 /*           element of the inverse of L D L^T - sigma I. */
00127 
00128 /*  R        (input/output) INTEGER */
00129 /*           The twist index for the twisted factorization used to */
00130 /*           compute Z. */
00131 /*           On input, 0 <= R <= N. If R is input as 0, R is set to */
00132 /*           the index where (L D L^T - sigma I)^{-1} is largest */
00133 /*           in magnitude. If 1 <= R <= N, R is unchanged. */
00134 /*           On output, R contains the twist index used to compute Z. */
00135 /*           Ideally, R designates the position of the maximum entry in the */
00136 /*           eigenvector. */
00137 
00138 /*  ISUPPZ   (output) INTEGER array, dimension (2) */
00139 /*           The support of the vector in Z, i.e., the vector Z is */
00140 /*           nonzero only in elements ISUPPZ(1) through ISUPPZ( 2 ). */
00141 
00142 /*  NRMINV   (output) DOUBLE PRECISION */
00143 /*           NRMINV = 1/SQRT( ZTZ ) */
00144 
00145 /*  RESID    (output) DOUBLE PRECISION */
00146 /*           The residual of the FP vector. */
00147 /*           RESID = ABS( MINGMA )/SQRT( ZTZ ) */
00148 
00149 /*  RQCORR   (output) DOUBLE PRECISION */
00150 /*           The Rayleigh Quotient correction to LAMBDA. */
00151 /*           RQCORR = MINGMA*TMP */
00152 
00153 /*  WORK     (workspace) DOUBLE PRECISION array, dimension (4*N) */
00154 
00155 /*  Further Details */
00156 /*  =============== */
00157 
00158 /*  Based on contributions by */
00159 /*     Beresford Parlett, University of California, Berkeley, USA */
00160 /*     Jim Demmel, University of California, Berkeley, USA */
00161 /*     Inderjit Dhillon, University of Texas, Austin, USA */
00162 /*     Osni Marques, LBNL/NERSC, USA */
00163 /*     Christof Voemel, University of California, Berkeley, USA */
00164 
00165 /*  ===================================================================== */
00166 
00167 /*     .. Parameters .. */
00168 /*     .. */
00169 /*     .. Local Scalars .. */
00170 /*     .. */
00171 /*     .. External Functions .. */
00172 /*     .. */
00173 /*     .. Intrinsic Functions .. */
00174 /*     .. */
00175 /*     .. Executable Statements .. */
00176 
00177     /* Parameter adjustments */
00178     --work;
00179     --isuppz;
00180     --z__;
00181     --lld;
00182     --ld;
00183     --l;
00184     --d__;
00185 
00186     /* Function Body */
00187     eps = dlamch_("Precision");
00188     if (*r__ == 0) {
00189         r1 = *b1;
00190         r2 = *bn;
00191     } else {
00192         r1 = *r__;
00193         r2 = *r__;
00194     }
00195 /*     Storage for LPLUS */
00196     indlpl = 0;
00197 /*     Storage for UMINUS */
00198     indumn = *n;
00199     inds = (*n << 1) + 1;
00200     indp = *n * 3 + 1;
00201     if (*b1 == 1) {
00202         work[inds] = 0.;
00203     } else {
00204         work[inds + *b1 - 1] = lld[*b1 - 1];
00205     }
00206 
00207 /*     Compute the stationary transform (using the differential form) */
00208 /*     until the index R2. */
00209 
00210     sawnan1 = FALSE_;
00211     neg1 = 0;
00212     s = work[inds + *b1 - 1] - *lambda;
00213     i__1 = r1 - 1;
00214     for (i__ = *b1; i__ <= i__1; ++i__) {
00215         dplus = d__[i__] + s;
00216         work[indlpl + i__] = ld[i__] / dplus;
00217         if (dplus < 0.) {
00218             ++neg1;
00219         }
00220         work[inds + i__] = s * work[indlpl + i__] * l[i__];
00221         s = work[inds + i__] - *lambda;
00222 /* L50: */
00223     }
00224     sawnan1 = disnan_(&s);
00225     if (sawnan1) {
00226         goto L60;
00227     }
00228     i__1 = r2 - 1;
00229     for (i__ = r1; i__ <= i__1; ++i__) {
00230         dplus = d__[i__] + s;
00231         work[indlpl + i__] = ld[i__] / dplus;
00232         work[inds + i__] = s * work[indlpl + i__] * l[i__];
00233         s = work[inds + i__] - *lambda;
00234 /* L51: */
00235     }
00236     sawnan1 = disnan_(&s);
00237 
00238 L60:
00239     if (sawnan1) {
00240 /*        Runs a slower version of the above loop if a NaN is detected */
00241         neg1 = 0;
00242         s = work[inds + *b1 - 1] - *lambda;
00243         i__1 = r1 - 1;
00244         for (i__ = *b1; i__ <= i__1; ++i__) {
00245             dplus = d__[i__] + s;
00246             if (abs(dplus) < *pivmin) {
00247                 dplus = -(*pivmin);
00248             }
00249             work[indlpl + i__] = ld[i__] / dplus;
00250             if (dplus < 0.) {
00251                 ++neg1;
00252             }
00253             work[inds + i__] = s * work[indlpl + i__] * l[i__];
00254             if (work[indlpl + i__] == 0.) {
00255                 work[inds + i__] = lld[i__];
00256             }
00257             s = work[inds + i__] - *lambda;
00258 /* L70: */
00259         }
00260         i__1 = r2 - 1;
00261         for (i__ = r1; i__ <= i__1; ++i__) {
00262             dplus = d__[i__] + s;
00263             if (abs(dplus) < *pivmin) {
00264                 dplus = -(*pivmin);
00265             }
00266             work[indlpl + i__] = ld[i__] / dplus;
00267             work[inds + i__] = s * work[indlpl + i__] * l[i__];
00268             if (work[indlpl + i__] == 0.) {
00269                 work[inds + i__] = lld[i__];
00270             }
00271             s = work[inds + i__] - *lambda;
00272 /* L71: */
00273         }
00274     }
00275 
00276 /*     Compute the progressive transform (using the differential form) */
00277 /*     until the index R1 */
00278 
00279     sawnan2 = FALSE_;
00280     neg2 = 0;
00281     work[indp + *bn - 1] = d__[*bn] - *lambda;
00282     i__1 = r1;
00283     for (i__ = *bn - 1; i__ >= i__1; --i__) {
00284         dminus = lld[i__] + work[indp + i__];
00285         tmp = d__[i__] / dminus;
00286         if (dminus < 0.) {
00287             ++neg2;
00288         }
00289         work[indumn + i__] = l[i__] * tmp;
00290         work[indp + i__ - 1] = work[indp + i__] * tmp - *lambda;
00291 /* L80: */
00292     }
00293     tmp = work[indp + r1 - 1];
00294     sawnan2 = disnan_(&tmp);
00295     if (sawnan2) {
00296 /*        Runs a slower version of the above loop if a NaN is detected */
00297         neg2 = 0;
00298         i__1 = r1;
00299         for (i__ = *bn - 1; i__ >= i__1; --i__) {
00300             dminus = lld[i__] + work[indp + i__];
00301             if (abs(dminus) < *pivmin) {
00302                 dminus = -(*pivmin);
00303             }
00304             tmp = d__[i__] / dminus;
00305             if (dminus < 0.) {
00306                 ++neg2;
00307             }
00308             work[indumn + i__] = l[i__] * tmp;
00309             work[indp + i__ - 1] = work[indp + i__] * tmp - *lambda;
00310             if (tmp == 0.) {
00311                 work[indp + i__ - 1] = d__[i__] - *lambda;
00312             }
00313 /* L100: */
00314         }
00315     }
00316 
00317 /*     Find the index (from R1 to R2) of the largest (in magnitude) */
00318 /*     diagonal element of the inverse */
00319 
00320     *mingma = work[inds + r1 - 1] + work[indp + r1 - 1];
00321     if (*mingma < 0.) {
00322         ++neg1;
00323     }
00324     if (*wantnc) {
00325         *negcnt = neg1 + neg2;
00326     } else {
00327         *negcnt = -1;
00328     }
00329     if (abs(*mingma) == 0.) {
00330         *mingma = eps * work[inds + r1 - 1];
00331     }
00332     *r__ = r1;
00333     i__1 = r2 - 1;
00334     for (i__ = r1; i__ <= i__1; ++i__) {
00335         tmp = work[inds + i__] + work[indp + i__];
00336         if (tmp == 0.) {
00337             tmp = eps * work[inds + i__];
00338         }
00339         if (abs(tmp) <= abs(*mingma)) {
00340             *mingma = tmp;
00341             *r__ = i__ + 1;
00342         }
00343 /* L110: */
00344     }
00345 
00346 /*     Compute the FP vector: solve N^T v = e_r */
00347 
00348     isuppz[1] = *b1;
00349     isuppz[2] = *bn;
00350     z__[*r__] = 1.;
00351     *ztz = 1.;
00352 
00353 /*     Compute the FP vector upwards from R */
00354 
00355     if (! sawnan1 && ! sawnan2) {
00356         i__1 = *b1;
00357         for (i__ = *r__ - 1; i__ >= i__1; --i__) {
00358             z__[i__] = -(work[indlpl + i__] * z__[i__ + 1]);
00359             if (((d__1 = z__[i__], abs(d__1)) + (d__2 = z__[i__ + 1], abs(
00360                     d__2))) * (d__3 = ld[i__], abs(d__3)) < *gaptol) {
00361                 z__[i__] = 0.;
00362                 isuppz[1] = i__ + 1;
00363                 goto L220;
00364             }
00365             *ztz += z__[i__] * z__[i__];
00366 /* L210: */
00367         }
00368 L220:
00369         ;
00370     } else {
00371 /*        Run slower loop if NaN occurred. */
00372         i__1 = *b1;
00373         for (i__ = *r__ - 1; i__ >= i__1; --i__) {
00374             if (z__[i__ + 1] == 0.) {
00375                 z__[i__] = -(ld[i__ + 1] / ld[i__]) * z__[i__ + 2];
00376             } else {
00377                 z__[i__] = -(work[indlpl + i__] * z__[i__ + 1]);
00378             }
00379             if (((d__1 = z__[i__], abs(d__1)) + (d__2 = z__[i__ + 1], abs(
00380                     d__2))) * (d__3 = ld[i__], abs(d__3)) < *gaptol) {
00381                 z__[i__] = 0.;
00382                 isuppz[1] = i__ + 1;
00383                 goto L240;
00384             }
00385             *ztz += z__[i__] * z__[i__];
00386 /* L230: */
00387         }
00388 L240:
00389         ;
00390     }
00391 /*     Compute the FP vector downwards from R in blocks of size BLKSIZ */
00392     if (! sawnan1 && ! sawnan2) {
00393         i__1 = *bn - 1;
00394         for (i__ = *r__; i__ <= i__1; ++i__) {
00395             z__[i__ + 1] = -(work[indumn + i__] * z__[i__]);
00396             if (((d__1 = z__[i__], abs(d__1)) + (d__2 = z__[i__ + 1], abs(
00397                     d__2))) * (d__3 = ld[i__], abs(d__3)) < *gaptol) {
00398                 z__[i__ + 1] = 0.;
00399                 isuppz[2] = i__;
00400                 goto L260;
00401             }
00402             *ztz += z__[i__ + 1] * z__[i__ + 1];
00403 /* L250: */
00404         }
00405 L260:
00406         ;
00407     } else {
00408 /*        Run slower loop if NaN occurred. */
00409         i__1 = *bn - 1;
00410         for (i__ = *r__; i__ <= i__1; ++i__) {
00411             if (z__[i__] == 0.) {
00412                 z__[i__ + 1] = -(ld[i__ - 1] / ld[i__]) * z__[i__ - 1];
00413             } else {
00414                 z__[i__ + 1] = -(work[indumn + i__] * z__[i__]);
00415             }
00416             if (((d__1 = z__[i__], abs(d__1)) + (d__2 = z__[i__ + 1], abs(
00417                     d__2))) * (d__3 = ld[i__], abs(d__3)) < *gaptol) {
00418                 z__[i__ + 1] = 0.;
00419                 isuppz[2] = i__;
00420                 goto L280;
00421             }
00422             *ztz += z__[i__ + 1] * z__[i__ + 1];
00423 /* L270: */
00424         }
00425 L280:
00426         ;
00427     }
00428 
00429 /*     Compute quantities for convergence test */
00430 
00431     tmp = 1. / *ztz;
00432     *nrminv = sqrt(tmp);
00433     *resid = abs(*mingma) * *nrminv;
00434     *rqcorr = *mingma * tmp;
00435 
00436 
00437     return 0;
00438 
00439 /*     End of DLAR1V */
00440 
00441 } /* dlar1v_ */


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