3 /* Subroutine */ int dlar1v_(integer *n, integer *b1, integer *bn, doublereal
4 *lambda, doublereal *d__, doublereal *l, doublereal *ld, doublereal *
5 lld, doublereal *pivmin, doublereal *gaptol, doublereal *z__, logical
6 *wantnc, integer *negcnt, doublereal *ztz, doublereal *mingma,
7 integer *r__, integer *isuppz, doublereal *nrminv, doublereal *resid,
8 doublereal *rqcorr, doublereal *work)
10 /* System generated locals */
12 doublereal d__1, d__2, d__3;
14 /* Builtin functions */
15 double sqrt(doublereal);
22 integer neg1, neg2, indp, inds;
24 extern doublereal dlamch_(char *);
25 extern logical disnan_(doublereal *);
26 integer indlpl, indumn;
28 logical sawnan1, sawnan2;
31 /* -- LAPACK auxiliary routine (version 3.1) -- */
32 /* Univ. of Tennessee, Univ. of California Berkeley and NAG Ltd.. */
35 /* .. Scalar Arguments .. */
37 /* .. Array Arguments .. */
43 /* DLAR1V computes the (scaled) r-th column of the inverse of */
44 /* the sumbmatrix in rows B1 through BN of the tridiagonal matrix */
45 /* L D L^T - sigma I. When sigma is close to an eigenvalue, the */
46 /* computed vector is an accurate eigenvector. Usually, r corresponds */
47 /* to the index where the eigenvector is largest in magnitude. */
48 /* The following steps accomplish this computation : */
49 /* (a) Stationary qd transform, L D L^T - sigma I = L(+) D(+) L(+)^T, */
50 /* (b) Progressive qd transform, L D L^T - sigma I = U(-) D(-) U(-)^T, */
51 /* (c) Computation of the diagonal elements of the inverse of */
52 /* L D L^T - sigma I by combining the above transforms, and choosing */
53 /* r as the index where the diagonal of the inverse is (one of the) */
54 /* largest in magnitude. */
55 /* (d) Computation of the (scaled) r-th column of the inverse using the */
56 /* twisted factorization obtained by combining the top part of the */
57 /* the stationary and the bottom part of the progressive transform. */
62 /* N (input) INTEGER */
63 /* The order of the matrix L D L^T. */
65 /* B1 (input) INTEGER */
66 /* First index of the submatrix of L D L^T. */
68 /* BN (input) INTEGER */
69 /* Last index of the submatrix of L D L^T. */
71 /* LAMBDA (input) DOUBLE PRECISION */
72 /* The shift. In order to compute an accurate eigenvector, */
73 /* LAMBDA should be a good approximation to an eigenvalue */
76 /* L (input) DOUBLE PRECISION array, dimension (N-1) */
77 /* The (n-1) subdiagonal elements of the unit bidiagonal matrix */
78 /* L, in elements 1 to N-1. */
80 /* D (input) DOUBLE PRECISION array, dimension (N) */
81 /* The n diagonal elements of the diagonal matrix D. */
83 /* LD (input) DOUBLE PRECISION array, dimension (N-1) */
84 /* The n-1 elements L(i)*D(i). */
86 /* LLD (input) DOUBLE PRECISION array, dimension (N-1) */
87 /* The n-1 elements L(i)*L(i)*D(i). */
89 /* PIVMIN (input) DOUBLE PRECISION */
90 /* The minimum pivot in the Sturm sequence. */
92 /* GAPTOL (input) DOUBLE PRECISION */
93 /* Tolerance that indicates when eigenvector entries are negligible */
94 /* w.r.t. their contribution to the residual. */
96 /* Z (input/output) DOUBLE PRECISION array, dimension (N) */
97 /* On input, all entries of Z must be set to 0. */
98 /* On output, Z contains the (scaled) r-th column of the */
99 /* inverse. The scaling is such that Z(R) equals 1. */
101 /* WANTNC (input) LOGICAL */
102 /* Specifies whether NEGCNT has to be computed. */
104 /* NEGCNT (output) INTEGER */
105 /* If WANTNC is .TRUE. then NEGCNT = the number of pivots < pivmin */
106 /* in the matrix factorization L D L^T, and NEGCNT = -1 otherwise. */
108 /* ZTZ (output) DOUBLE PRECISION */
109 /* The square of the 2-norm of Z. */
111 /* MINGMA (output) DOUBLE PRECISION */
112 /* The reciprocal of the largest (in magnitude) diagonal */
113 /* element of the inverse of L D L^T - sigma I. */
115 /* R (input/output) INTEGER */
116 /* The twist index for the twisted factorization used to */
118 /* On input, 0 <= R <= N. If R is input as 0, R is set to */
119 /* the index where (L D L^T - sigma I)^{-1} is largest */
120 /* in magnitude. If 1 <= R <= N, R is unchanged. */
121 /* On output, R contains the twist index used to compute Z. */
122 /* Ideally, R designates the position of the maximum entry in the */
125 /* ISUPPZ (output) INTEGER array, dimension (2) */
126 /* The support of the vector in Z, i.e., the vector Z is */
127 /* nonzero only in elements ISUPPZ(1) through ISUPPZ( 2 ). */
129 /* NRMINV (output) DOUBLE PRECISION */
130 /* NRMINV = 1/SQRT( ZTZ ) */
132 /* RESID (output) DOUBLE PRECISION */
133 /* The residual of the FP vector. */
134 /* RESID = ABS( MINGMA )/SQRT( ZTZ ) */
136 /* RQCORR (output) DOUBLE PRECISION */
137 /* The Rayleigh Quotient correction to LAMBDA. */
138 /* RQCORR = MINGMA*TMP */
140 /* WORK (workspace) DOUBLE PRECISION array, dimension (4*N) */
142 /* Further Details */
143 /* =============== */
145 /* Based on contributions by */
146 /* Beresford Parlett, University of California, Berkeley, USA */
147 /* Jim Demmel, University of California, Berkeley, USA */
148 /* Inderjit Dhillon, University of Texas, Austin, USA */
149 /* Osni Marques, LBNL/NERSC, USA */
150 /* Christof Voemel, University of California, Berkeley, USA */
152 /* ===================================================================== */
154 /* .. Parameters .. */
156 /* .. Local Scalars .. */
158 /* .. External Functions .. */
160 /* .. Intrinsic Functions .. */
162 /* .. Executable Statements .. */
164 /* Parameter adjustments */
174 eps = dlamch_("Precision");
182 /* Storage for LPLUS */
184 /* Storage for UMINUS */
186 inds = (*n << 1) + 1;
191 work[inds + *b1 - 1] = lld[*b1 - 1];
194 /* Compute the stationary transform (using the differential form) */
195 /* until the index R2. */
199 s = work[inds + *b1 - 1] - *lambda;
201 for (i__ = *b1; i__ <= i__1; ++i__) {
202 dplus = d__[i__] + s;
203 work[indlpl + i__] = ld[i__] / dplus;
207 work[inds + i__] = s * work[indlpl + i__] * l[i__];
208 s = work[inds + i__] - *lambda;
211 sawnan1 = disnan_(&s);
216 for (i__ = r1; i__ <= i__1; ++i__) {
217 dplus = d__[i__] + s;
218 work[indlpl + i__] = ld[i__] / dplus;
219 work[inds + i__] = s * work[indlpl + i__] * l[i__];
220 s = work[inds + i__] - *lambda;
223 sawnan1 = disnan_(&s);
227 /* Runs a slower version of the above loop if a NaN is detected */
229 s = work[inds + *b1 - 1] - *lambda;
231 for (i__ = *b1; i__ <= i__1; ++i__) {
232 dplus = d__[i__] + s;
233 if (abs(dplus) < *pivmin) {
236 work[indlpl + i__] = ld[i__] / dplus;
240 work[inds + i__] = s * work[indlpl + i__] * l[i__];
241 if (work[indlpl + i__] == 0.) {
242 work[inds + i__] = lld[i__];
244 s = work[inds + i__] - *lambda;
248 for (i__ = r1; i__ <= i__1; ++i__) {
249 dplus = d__[i__] + s;
250 if (abs(dplus) < *pivmin) {
253 work[indlpl + i__] = ld[i__] / dplus;
254 work[inds + i__] = s * work[indlpl + i__] * l[i__];
255 if (work[indlpl + i__] == 0.) {
256 work[inds + i__] = lld[i__];
258 s = work[inds + i__] - *lambda;
263 /* Compute the progressive transform (using the differential form) */
264 /* until the index R1 */
268 work[indp + *bn - 1] = d__[*bn] - *lambda;
270 for (i__ = *bn - 1; i__ >= i__1; --i__) {
271 dminus = lld[i__] + work[indp + i__];
272 tmp = d__[i__] / dminus;
276 work[indumn + i__] = l[i__] * tmp;
277 work[indp + i__ - 1] = work[indp + i__] * tmp - *lambda;
280 tmp = work[indp + r1 - 1];
281 sawnan2 = disnan_(&tmp);
283 /* Runs a slower version of the above loop if a NaN is detected */
286 for (i__ = *bn - 1; i__ >= i__1; --i__) {
287 dminus = lld[i__] + work[indp + i__];
288 if (abs(dminus) < *pivmin) {
291 tmp = d__[i__] / dminus;
295 work[indumn + i__] = l[i__] * tmp;
296 work[indp + i__ - 1] = work[indp + i__] * tmp - *lambda;
298 work[indp + i__ - 1] = d__[i__] - *lambda;
304 /* Find the index (from R1 to R2) of the largest (in magnitude) */
305 /* diagonal element of the inverse */
307 *mingma = work[inds + r1 - 1] + work[indp + r1 - 1];
312 *negcnt = neg1 + neg2;
316 if (abs(*mingma) == 0.) {
317 *mingma = eps * work[inds + r1 - 1];
321 for (i__ = r1; i__ <= i__1; ++i__) {
322 tmp = work[inds + i__] + work[indp + i__];
324 tmp = eps * work[inds + i__];
326 if (abs(tmp) <= abs(*mingma)) {
333 /* Compute the FP vector: solve N^T v = e_r */
340 /* Compute the FP vector upwards from R */
342 if (! sawnan1 && ! sawnan2) {
344 for (i__ = *r__ - 1; i__ >= i__1; --i__) {
345 z__[i__] = -(work[indlpl + i__] * z__[i__ + 1]);
346 if (((d__1 = z__[i__], abs(d__1)) + (d__2 = z__[i__ + 1], abs(
347 d__2))) * (d__3 = ld[i__], abs(d__3)) < *gaptol) {
352 *ztz += z__[i__] * z__[i__];
358 /* Run slower loop if NaN occurred. */
360 for (i__ = *r__ - 1; i__ >= i__1; --i__) {
361 if (z__[i__ + 1] == 0.) {
362 z__[i__] = -(ld[i__ + 1] / ld[i__]) * z__[i__ + 2];
364 z__[i__] = -(work[indlpl + i__] * z__[i__ + 1]);
366 if (((d__1 = z__[i__], abs(d__1)) + (d__2 = z__[i__ + 1], abs(
367 d__2))) * (d__3 = ld[i__], abs(d__3)) < *gaptol) {
372 *ztz += z__[i__] * z__[i__];
378 /* Compute the FP vector downwards from R in blocks of size BLKSIZ */
379 if (! sawnan1 && ! sawnan2) {
381 for (i__ = *r__; i__ <= i__1; ++i__) {
382 z__[i__ + 1] = -(work[indumn + i__] * z__[i__]);
383 if (((d__1 = z__[i__], abs(d__1)) + (d__2 = z__[i__ + 1], abs(
384 d__2))) * (d__3 = ld[i__], abs(d__3)) < *gaptol) {
389 *ztz += z__[i__ + 1] * z__[i__ + 1];
395 /* Run slower loop if NaN occurred. */
397 for (i__ = *r__; i__ <= i__1; ++i__) {
398 if (z__[i__] == 0.) {
399 z__[i__ + 1] = -(ld[i__ - 1] / ld[i__]) * z__[i__ - 1];
401 z__[i__ + 1] = -(work[indumn + i__] * z__[i__]);
403 if (((d__1 = z__[i__], abs(d__1)) + (d__2 = z__[i__ + 1], abs(
404 d__2))) * (d__3 = ld[i__], abs(d__3)) < *gaptol) {
409 *ztz += z__[i__ + 1] * z__[i__ + 1];
416 /* Compute quantities for convergence test */
420 *resid = abs(*mingma) * *nrminv;
421 *rqcorr = *mingma * tmp;