clar1v.c
Go to the documentation of this file.
00001 /* clar1v.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 clar1v_(integer *n, integer *b1, integer *bn, real *
00017         lambda, real *d__, real *l, real *ld, real *lld, real *pivmin, real *
00018         gaptol, complex *z__, logical *wantnc, integer *negcnt, real *ztz, 
00019         real *mingma, integer *r__, integer *isuppz, real *nrminv, real *
00020         resid, real *rqcorr, real *work)
00021 {
00022     /* System generated locals */
00023     integer i__1, i__2, i__3, i__4;
00024     real r__1;
00025     complex q__1, q__2;
00026 
00027     /* Builtin functions */
00028     double c_abs(complex *), sqrt(doublereal);
00029 
00030     /* Local variables */
00031     integer i__;
00032     real s;
00033     integer r1, r2;
00034     real eps, tmp;
00035     integer neg1, neg2, indp, inds;
00036     real dplus;
00037     extern doublereal slamch_(char *);
00038     integer indlpl, indumn;
00039     extern logical sisnan_(real *);
00040     real 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 /*  CLAR1V 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) REAL */
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) REAL             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) REAL             array, dimension (N) */
00094 /*           The n diagonal elements of the diagonal matrix D. */
00095 
00096 /*  LD       (input) REAL             array, dimension (N-1) */
00097 /*           The n-1 elements L(i)*D(i). */
00098 
00099 /*  LLD      (input) REAL             array, dimension (N-1) */
00100 /*           The n-1 elements L(i)*L(i)*D(i). */
00101 
00102 /*  PIVMIN   (input) REAL */
00103 /*           The minimum pivot in the Sturm sequence. */
00104 
00105 /*  GAPTOL   (input) REAL */
00106 /*           Tolerance that indicates when eigenvector entries are negligible */
00107 /*           w.r.t. their contribution to the residual. */
00108 
00109 /*  Z        (input/output) COMPLEX          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) REAL */
00122 /*           The square of the 2-norm of Z. */
00123 
00124 /*  MINGMA   (output) REAL */
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) REAL */
00143 /*           NRMINV = 1/SQRT( ZTZ ) */
00144 
00145 /*  RESID    (output) REAL */
00146 /*           The residual of the FP vector. */
00147 /*           RESID = ABS( MINGMA )/SQRT( ZTZ ) */
00148 
00149 /*  RQCORR   (output) REAL */
00150 /*           The Rayleigh Quotient correction to LAMBDA. */
00151 /*           RQCORR = MINGMA*TMP */
00152 
00153 /*  WORK     (workspace) REAL             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 = slamch_("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.f;
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.f) {
00218             ++neg1;
00219         }
00220         work[inds + i__] = s * work[indlpl + i__] * l[i__];
00221         s = work[inds + i__] - *lambda;
00222 /* L50: */
00223     }
00224     sawnan1 = sisnan_(&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 = sisnan_(&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 (dabs(dplus) < *pivmin) {
00247                 dplus = -(*pivmin);
00248             }
00249             work[indlpl + i__] = ld[i__] / dplus;
00250             if (dplus < 0.f) {
00251                 ++neg1;
00252             }
00253             work[inds + i__] = s * work[indlpl + i__] * l[i__];
00254             if (work[indlpl + i__] == 0.f) {
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 (dabs(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.f) {
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.f) {
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 = sisnan_(&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 (dabs(dminus) < *pivmin) {
00302                 dminus = -(*pivmin);
00303             }
00304             tmp = d__[i__] / dminus;
00305             if (dminus < 0.f) {
00306                 ++neg2;
00307             }
00308             work[indumn + i__] = l[i__] * tmp;
00309             work[indp + i__ - 1] = work[indp + i__] * tmp - *lambda;
00310             if (tmp == 0.f) {
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.f) {
00322         ++neg1;
00323     }
00324     if (*wantnc) {
00325         *negcnt = neg1 + neg2;
00326     } else {
00327         *negcnt = -1;
00328     }
00329     if (dabs(*mingma) == 0.f) {
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.f) {
00337             tmp = eps * work[inds + i__];
00338         }
00339         if (dabs(tmp) <= dabs(*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     i__1 = *r__;
00351     z__[i__1].r = 1.f, z__[i__1].i = 0.f;
00352     *ztz = 1.f;
00353 
00354 /*     Compute the FP vector upwards from R */
00355 
00356     if (! sawnan1 && ! sawnan2) {
00357         i__1 = *b1;
00358         for (i__ = *r__ - 1; i__ >= i__1; --i__) {
00359             i__2 = i__;
00360             i__3 = indlpl + i__;
00361             i__4 = i__ + 1;
00362             q__2.r = work[i__3] * z__[i__4].r, q__2.i = work[i__3] * z__[i__4]
00363                     .i;
00364             q__1.r = -q__2.r, q__1.i = -q__2.i;
00365             z__[i__2].r = q__1.r, z__[i__2].i = q__1.i;
00366             if ((c_abs(&z__[i__]) + c_abs(&z__[i__ + 1])) * (r__1 = ld[i__], 
00367                     dabs(r__1)) < *gaptol) {
00368                 i__2 = i__;
00369                 z__[i__2].r = 0.f, z__[i__2].i = 0.f;
00370                 isuppz[1] = i__ + 1;
00371                 goto L220;
00372             }
00373             i__2 = i__;
00374             i__3 = i__;
00375             q__1.r = z__[i__2].r * z__[i__3].r - z__[i__2].i * z__[i__3].i, 
00376                     q__1.i = z__[i__2].r * z__[i__3].i + z__[i__2].i * z__[
00377                     i__3].r;
00378             *ztz += q__1.r;
00379 /* L210: */
00380         }
00381 L220:
00382         ;
00383     } else {
00384 /*        Run slower loop if NaN occurred. */
00385         i__1 = *b1;
00386         for (i__ = *r__ - 1; i__ >= i__1; --i__) {
00387             i__2 = i__ + 1;
00388             if (z__[i__2].r == 0.f && z__[i__2].i == 0.f) {
00389                 i__2 = i__;
00390                 r__1 = -(ld[i__ + 1] / ld[i__]);
00391                 i__3 = i__ + 2;
00392                 q__1.r = r__1 * z__[i__3].r, q__1.i = r__1 * z__[i__3].i;
00393                 z__[i__2].r = q__1.r, z__[i__2].i = q__1.i;
00394             } else {
00395                 i__2 = i__;
00396                 i__3 = indlpl + i__;
00397                 i__4 = i__ + 1;
00398                 q__2.r = work[i__3] * z__[i__4].r, q__2.i = work[i__3] * z__[
00399                         i__4].i;
00400                 q__1.r = -q__2.r, q__1.i = -q__2.i;
00401                 z__[i__2].r = q__1.r, z__[i__2].i = q__1.i;
00402             }
00403             if ((c_abs(&z__[i__]) + c_abs(&z__[i__ + 1])) * (r__1 = ld[i__], 
00404                     dabs(r__1)) < *gaptol) {
00405                 i__2 = i__;
00406                 z__[i__2].r = 0.f, z__[i__2].i = 0.f;
00407                 isuppz[1] = i__ + 1;
00408                 goto L240;
00409             }
00410             i__2 = i__;
00411             i__3 = i__;
00412             q__1.r = z__[i__2].r * z__[i__3].r - z__[i__2].i * z__[i__3].i, 
00413                     q__1.i = z__[i__2].r * z__[i__3].i + z__[i__2].i * z__[
00414                     i__3].r;
00415             *ztz += q__1.r;
00416 /* L230: */
00417         }
00418 L240:
00419         ;
00420     }
00421 /*     Compute the FP vector downwards from R in blocks of size BLKSIZ */
00422     if (! sawnan1 && ! sawnan2) {
00423         i__1 = *bn - 1;
00424         for (i__ = *r__; i__ <= i__1; ++i__) {
00425             i__2 = i__ + 1;
00426             i__3 = indumn + i__;
00427             i__4 = i__;
00428             q__2.r = work[i__3] * z__[i__4].r, q__2.i = work[i__3] * z__[i__4]
00429                     .i;
00430             q__1.r = -q__2.r, q__1.i = -q__2.i;
00431             z__[i__2].r = q__1.r, z__[i__2].i = q__1.i;
00432             if ((c_abs(&z__[i__]) + c_abs(&z__[i__ + 1])) * (r__1 = ld[i__], 
00433                     dabs(r__1)) < *gaptol) {
00434                 i__2 = i__ + 1;
00435                 z__[i__2].r = 0.f, z__[i__2].i = 0.f;
00436                 isuppz[2] = i__;
00437                 goto L260;
00438             }
00439             i__2 = i__ + 1;
00440             i__3 = i__ + 1;
00441             q__1.r = z__[i__2].r * z__[i__3].r - z__[i__2].i * z__[i__3].i, 
00442                     q__1.i = z__[i__2].r * z__[i__3].i + z__[i__2].i * z__[
00443                     i__3].r;
00444             *ztz += q__1.r;
00445 /* L250: */
00446         }
00447 L260:
00448         ;
00449     } else {
00450 /*        Run slower loop if NaN occurred. */
00451         i__1 = *bn - 1;
00452         for (i__ = *r__; i__ <= i__1; ++i__) {
00453             i__2 = i__;
00454             if (z__[i__2].r == 0.f && z__[i__2].i == 0.f) {
00455                 i__2 = i__ + 1;
00456                 r__1 = -(ld[i__ - 1] / ld[i__]);
00457                 i__3 = i__ - 1;
00458                 q__1.r = r__1 * z__[i__3].r, q__1.i = r__1 * z__[i__3].i;
00459                 z__[i__2].r = q__1.r, z__[i__2].i = q__1.i;
00460             } else {
00461                 i__2 = i__ + 1;
00462                 i__3 = indumn + i__;
00463                 i__4 = i__;
00464                 q__2.r = work[i__3] * z__[i__4].r, q__2.i = work[i__3] * z__[
00465                         i__4].i;
00466                 q__1.r = -q__2.r, q__1.i = -q__2.i;
00467                 z__[i__2].r = q__1.r, z__[i__2].i = q__1.i;
00468             }
00469             if ((c_abs(&z__[i__]) + c_abs(&z__[i__ + 1])) * (r__1 = ld[i__], 
00470                     dabs(r__1)) < *gaptol) {
00471                 i__2 = i__ + 1;
00472                 z__[i__2].r = 0.f, z__[i__2].i = 0.f;
00473                 isuppz[2] = i__;
00474                 goto L280;
00475             }
00476             i__2 = i__ + 1;
00477             i__3 = i__ + 1;
00478             q__1.r = z__[i__2].r * z__[i__3].r - z__[i__2].i * z__[i__3].i, 
00479                     q__1.i = z__[i__2].r * z__[i__3].i + z__[i__2].i * z__[
00480                     i__3].r;
00481             *ztz += q__1.r;
00482 /* L270: */
00483         }
00484 L280:
00485         ;
00486     }
00487 
00488 /*     Compute quantities for convergence test */
00489 
00490     tmp = 1.f / *ztz;
00491     *nrminv = sqrt(tmp);
00492     *resid = dabs(*mingma) * *nrminv;
00493     *rqcorr = *mingma * tmp;
00494 
00495 
00496     return 0;
00497 
00498 /*     End of CLAR1V */
00499 
00500 } /* clar1v_ */


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