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


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