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


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