1 /* ../netlib/slarrf.f -- translated by f2c (version 20100827). You must link the resulting object file with libf2c: on Microsoft Windows system, link with libf2c.lib;
2 on Linux or Unix systems, link with .../path/to/libf2c.a -lm or, if you install libf2c.a in a standard place, with -lf2c -lm -- in that order, at the end of the command line, as in cc *.o -lf2c -lm Source for libf2c is in /netlib/f2c/libf2c.zip, e.g., http://www.netlib.org/f2c/libf2c.zip */
3 #include "FLA_f2c.h" /* Table of constant values */
4 static integer c__1 = 1;
5 /* > \brief \b SLARRF finds a new relatively robust representation such that at least one of the eigenvalues i s relatively isolated. */
6 /* =========== DOCUMENTATION =========== */
7 /* Online html documentation available at */
8 /* http://www.netlib.org/lapack/explore-html/ */
9 /* > \htmlonly */
10 /* > Download SLARRF + dependencies */
11 /* > <a href="http://www.netlib.org/cgi-bin/netlibfiles.tgz?format=tgz&filename=/lapack/lapack_routine/slarrf. f"> */
12 /* > [TGZ]</a> */
13 /* > <a href="http://www.netlib.org/cgi-bin/netlibfiles.zip?format=zip&filename=/lapack/lapack_routine/slarrf. f"> */
14 /* > [ZIP]</a> */
15 /* > <a href="http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/slarrf. f"> */
16 /* > [TXT]</a> */
17 /* > \endhtmlonly */
18 /* Definition: */
19 /* =========== */
20 /* SUBROUTINE SLARRF( N, D, L, LD, CLSTRT, CLEND, */
21 /* W, WGAP, WERR, */
22 /* SPDIAM, CLGAPL, CLGAPR, PIVMIN, SIGMA, */
23 /* DPLUS, LPLUS, WORK, INFO ) */
24 /* .. Scalar Arguments .. */
25 /* INTEGER CLSTRT, CLEND, INFO, N */
26 /* REAL CLGAPL, CLGAPR, PIVMIN, SIGMA, SPDIAM */
27 /* .. */
28 /* .. Array Arguments .. */
29 /* REAL D( * ), DPLUS( * ), L( * ), LD( * ), */
30 /* $ LPLUS( * ), W( * ), WGAP( * ), WERR( * ), WORK( * ) */
31 /* .. */
32 /* > \par Purpose: */
33 /* ============= */
34 /* > */
35 /* > \verbatim */
36 /* > */
37 /* > Given the initial representation L D L^T and its cluster of close */
38 /* > eigenvalues (in a relative measure), W( CLSTRT ), W( CLSTRT+1 ), ... */
39 /* > W( CLEND ), SLARRF finds a new relatively robust representation */
40 /* > L D L^T - SIGMA I = L(+) D(+) L(+)^T such that at least one of the */
41 /* > eigenvalues of L(+) D(+) L(+)^T is relatively isolated. */
42 /* > \endverbatim */
43 /* Arguments: */
44 /* ========== */
45 /* > \param[in] N */
46 /* > \verbatim */
47 /* > N is INTEGER */
48 /* > The order of the matrix (subblock, if the matrix splitted). */
49 /* > \endverbatim */
50 /* > */
51 /* > \param[in] D */
52 /* > \verbatim */
53 /* > D is REAL array, dimension (N) */
54 /* > The N diagonal elements of the diagonal matrix D. */
55 /* > \endverbatim */
56 /* > */
57 /* > \param[in] L */
58 /* > \verbatim */
59 /* > L is REAL array, dimension (N-1) */
60 /* > The (N-1) subdiagonal elements of the unit bidiagonal */
61 /* > matrix L. */
62 /* > \endverbatim */
63 /* > */
64 /* > \param[in] LD */
65 /* > \verbatim */
66 /* > LD is REAL array, dimension (N-1) */
67 /* > The (N-1) elements L(i)*D(i). */
68 /* > \endverbatim */
69 /* > */
70 /* > \param[in] CLSTRT */
71 /* > \verbatim */
72 /* > CLSTRT is INTEGER */
73 /* > The index of the first eigenvalue in the cluster. */
74 /* > \endverbatim */
75 /* > */
76 /* > \param[in] CLEND */
77 /* > \verbatim */
78 /* > CLEND is INTEGER */
79 /* > The index of the last eigenvalue in the cluster. */
80 /* > \endverbatim */
81 /* > */
82 /* > \param[in] W */
83 /* > \verbatim */
84 /* > W is REAL array, dimension */
85 /* > dimension is >= (CLEND-CLSTRT+1) */
86 /* > The eigenvalue APPROXIMATIONS of L D L^T in ascending order. */
87 /* > W( CLSTRT ) through W( CLEND ) form the cluster of relatively */
88 /* > close eigenalues. */
89 /* > \endverbatim */
90 /* > */
91 /* > \param[in,out] WGAP */
92 /* > \verbatim */
93 /* > WGAP is REAL array, dimension */
94 /* > dimension is >= (CLEND-CLSTRT+1) */
95 /* > The separation from the right neighbor eigenvalue in W. */
96 /* > \endverbatim */
97 /* > */
98 /* > \param[in] WERR */
99 /* > \verbatim */
100 /* > WERR is REAL array, dimension */
101 /* > dimension is >= (CLEND-CLSTRT+1) */
102 /* > WERR contain the semiwidth of the uncertainty */
103 /* > interval of the corresponding eigenvalue APPROXIMATION in W */
104 /* > \endverbatim */
105 /* > */
106 /* > \param[in] SPDIAM */
107 /* > \verbatim */
108 /* > SPDIAM is REAL */
109 /* > estimate of the spectral diameter obtained from the */
110 /* > Gerschgorin intervals */
111 /* > \endverbatim */
112 /* > */
113 /* > \param[in] CLGAPL */
114 /* > \verbatim */
115 /* > CLGAPL is REAL */
116 /* > \endverbatim */
117 /* > */
118 /* > \param[in] CLGAPR */
119 /* > \verbatim */
120 /* > CLGAPR is REAL */
121 /* > absolute gap on each end of the cluster. */
122 /* > Set by the calling routine to protect against shifts too close */
123 /* > to eigenvalues outside the cluster. */
124 /* > \endverbatim */
125 /* > */
126 /* > \param[in] PIVMIN */
127 /* > \verbatim */
128 /* > PIVMIN is REAL */
129 /* > The minimum pivot allowed in the Sturm sequence. */
130 /* > \endverbatim */
131 /* > */
132 /* > \param[out] SIGMA */
133 /* > \verbatim */
134 /* > SIGMA is REAL */
135 /* > The shift used to form L(+) D(+) L(+)^T. */
136 /* > \endverbatim */
137 /* > */
138 /* > \param[out] DPLUS */
139 /* > \verbatim */
140 /* > DPLUS is REAL array, dimension (N) */
141 /* > The N diagonal elements of the diagonal matrix D(+). */
142 /* > \endverbatim */
143 /* > */
144 /* > \param[out] LPLUS */
145 /* > \verbatim */
146 /* > LPLUS is REAL array, dimension (N-1) */
147 /* > The first (N-1) elements of LPLUS contain the subdiagonal */
148 /* > elements of the unit bidiagonal matrix L(+). */
149 /* > \endverbatim */
150 /* > */
151 /* > \param[out] WORK */
152 /* > \verbatim */
153 /* > WORK is REAL array, dimension (2*N) */
154 /* > Workspace. */
155 /* > \endverbatim */
156 /* > */
157 /* > \param[out] INFO */
158 /* > \verbatim */
159 /* > INFO is INTEGER */
160 /* > Signals processing OK (=0) or failure (=1) */
161 /* > \endverbatim */
162 /* Authors: */
163 /* ======== */
164 /* > \author Univ. of Tennessee */
165 /* > \author Univ. of California Berkeley */
166 /* > \author Univ. of Colorado Denver */
167 /* > \author NAG Ltd. */
168 /* > \date September 2012 */
169 /* > \ingroup auxOTHERauxiliary */
170 /* > \par Contributors: */
171 /* ================== */
172 /* > */
173 /* > Beresford Parlett, University of California, Berkeley, USA \n */
174 /* > Jim Demmel, University of California, Berkeley, USA \n */
175 /* > Inderjit Dhillon, University of Texas, Austin, USA \n */
176 /* > Osni Marques, LBNL/NERSC, USA \n */
177 /* > Christof Voemel, University of California, Berkeley, USA */
178 /* ===================================================================== */
179 /* Subroutine */
slarrf_(integer * n,real * d__,real * l,real * ld,integer * clstrt,integer * clend,real * w,real * wgap,real * werr,real * spdiam,real * clgapl,real * clgapr,real * pivmin,real * sigma,real * dplus,real * lplus,real * work,integer * info)180 int slarrf_(integer *n, real *d__, real *l, real *ld, integer *clstrt, integer *clend, real *w, real *wgap, real *werr, real *spdiam, real *clgapl, real *clgapr, real *pivmin, real *sigma, real *dplus, real *lplus, real *work, integer *info)
181 {
182 /* System generated locals */
183 integer i__1;
184 real r__1, r__2, r__3;
185 /* Builtin functions */
186 double sqrt(doublereal);
187 /* Local variables */
188 integer i__;
189 real s, bestshift, smlgrowth, eps, tmp, max1, max2, rrr1, rrr2, znm2, growthbound, fail, fact, oldp;
190 integer indx;
191 real prod;
192 integer ktry;
193 real fail2, avgap, ldmax, rdmax;
194 integer shift;
195 extern /* Subroutine */
196 int scopy_(integer *, real *, integer *, real *, integer *);
197 logical dorrr1;
198 real ldelta;
199 extern real slamch_(char *);
200 logical nofail;
201 real mingap, lsigma, rdelta;
202 logical forcer;
203 real rsigma, clwdth;
204 extern logical sisnan_(real *);
205 logical sawnan1, sawnan2, tryrrr1;
206 /* -- LAPACK auxiliary routine (version 3.4.2) -- */
207 /* -- LAPACK is a software package provided by Univ. of Tennessee, -- */
208 /* -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..-- */
209 /* September 2012 */
210 /* .. Scalar Arguments .. */
211 /* .. */
212 /* .. Array Arguments .. */
213 /* .. */
214 /* ===================================================================== */
215 /* .. Parameters .. */
216 /* .. */
217 /* .. Local Scalars .. */
218 /* .. */
219 /* .. External Functions .. */
220 /* .. */
221 /* .. External Subroutines .. */
222 /* .. */
223 /* .. Intrinsic Functions .. */
224 /* .. */
225 /* .. Executable Statements .. */
226 /* Parameter adjustments */
227 --work;
228 --lplus;
229 --dplus;
230 --werr;
231 --wgap;
232 --w;
233 --ld;
234 --l;
235 --d__;
236 /* Function Body */
237 *info = 0;
238 fact = 2.f;
239 eps = slamch_("Precision");
240 shift = 0;
241 forcer = FALSE_;
242 /* Note that we cannot guarantee that for any of the shifts tried, */
243 /* the factorization has a small or even moderate element growth. */
244 /* There could be Ritz values at both ends of the cluster and despite */
245 /* backing off, there are examples where all factorizations tried */
246 /* (in IEEE mode, allowing zero pivots & infinities) have INFINITE */
247 /* element growth. */
248 /* For this reason, we should use PIVMIN in this subroutine so that at */
249 /* least the L D L^T factorization exists. It can be checked afterwards */
250 /* whether the element growth caused bad residuals/orthogonality. */
251 /* Decide whether the code should accept the best among all */
252 /* representations despite large element growth or signal INFO=1 */
253 nofail = TRUE_;
254 /* Compute the average gap length of the cluster */
255 clwdth = (r__1 = w[*clend] - w[*clstrt], f2c_abs(r__1)) + werr[*clend] + werr[ *clstrt];
256 avgap = clwdth / (real) (*clend - *clstrt);
257 mingap = min(*clgapl,*clgapr);
258 /* Initial values for shifts to both ends of cluster */
259 /* Computing MIN */
260 r__1 = w[*clstrt];
261 r__2 = w[*clend]; // , expr subst
262 lsigma = min(r__1,r__2) - werr[*clstrt];
263 /* Computing MAX */
264 r__1 = w[*clstrt];
265 r__2 = w[*clend]; // , expr subst
266 rsigma = max(r__1,r__2) + werr[*clend];
267 /* Use a small fudge to make sure that we really shift to the outside */
268 lsigma -= f2c_abs(lsigma) * 2.f * eps;
269 rsigma += f2c_abs(rsigma) * 2.f * eps;
270 /* Compute upper bounds for how much to back off the initial shifts */
271 ldmax = mingap * .25f + *pivmin * 2.f;
272 rdmax = mingap * .25f + *pivmin * 2.f;
273 /* Computing MAX */
274 r__1 = avgap;
275 r__2 = wgap[*clstrt]; // , expr subst
276 ldelta = max(r__1,r__2) / fact;
277 /* Computing MAX */
278 r__1 = avgap;
279 r__2 = wgap[*clend - 1]; // , expr subst
280 rdelta = max(r__1,r__2) / fact;
281 /* Initialize the record of the best representation found */
282 s = slamch_("S");
283 smlgrowth = 1.f / s;
284 fail = (real) (*n - 1) * mingap / (*spdiam * eps);
285 fail2 = (real) (*n - 1) * mingap / (*spdiam * sqrt(eps));
286 bestshift = lsigma;
287 /* while (KTRY <= KTRYMAX) */
288 ktry = 0;
289 growthbound = *spdiam * 8.f;
290 L5:
291 sawnan1 = FALSE_;
292 sawnan2 = FALSE_;
293 /* Ensure that we do not back off too much of the initial shifts */
294 ldelta = min(ldmax,ldelta);
295 rdelta = min(rdmax,rdelta);
296 /* Compute the element growth when shifting to both ends of the cluster */
297 /* accept the shift if there is no element growth at one of the two ends */
298 /* Left end */
299 s = -lsigma;
300 dplus[1] = d__[1] + s;
301 if (f2c_abs(dplus[1]) < *pivmin)
302 {
303 dplus[1] = -(*pivmin);
304 /* Need to set SAWNAN1 because refined RRR test should not be used */
305 /* in this case */
306 sawnan1 = TRUE_;
307 }
308 max1 = f2c_abs(dplus[1]);
309 i__1 = *n - 1;
310 for (i__ = 1;
311 i__ <= i__1;
312 ++i__)
313 {
314 lplus[i__] = ld[i__] / dplus[i__];
315 s = s * lplus[i__] * l[i__] - lsigma;
316 dplus[i__ + 1] = d__[i__ + 1] + s;
317 if ((r__1 = dplus[i__ + 1], f2c_abs(r__1)) < *pivmin)
318 {
319 dplus[i__ + 1] = -(*pivmin);
320 /* Need to set SAWNAN1 because refined RRR test should not be used */
321 /* in this case */
322 sawnan1 = TRUE_;
323 }
324 /* Computing MAX */
325 r__2 = max1;
326 r__3 = (r__1 = dplus[i__ + 1], f2c_abs(r__1)); // , expr subst
327 max1 = max(r__2,r__3);
328 /* L6: */
329 }
330 sawnan1 = sawnan1 || sisnan_(&max1);
331 if (forcer || max1 <= growthbound && ! sawnan1)
332 {
333 *sigma = lsigma;
334 shift = 1;
335 goto L100;
336 }
337 /* Right end */
338 s = -rsigma;
339 work[1] = d__[1] + s;
340 if (f2c_abs(work[1]) < *pivmin)
341 {
342 work[1] = -(*pivmin);
343 /* Need to set SAWNAN2 because refined RRR test should not be used */
344 /* in this case */
345 sawnan2 = TRUE_;
346 }
347 max2 = f2c_abs(work[1]);
348 i__1 = *n - 1;
349 for (i__ = 1;
350 i__ <= i__1;
351 ++i__)
352 {
353 work[*n + i__] = ld[i__] / work[i__];
354 s = s * work[*n + i__] * l[i__] - rsigma;
355 work[i__ + 1] = d__[i__ + 1] + s;
356 if ((r__1 = work[i__ + 1], f2c_abs(r__1)) < *pivmin)
357 {
358 work[i__ + 1] = -(*pivmin);
359 /* Need to set SAWNAN2 because refined RRR test should not be used */
360 /* in this case */
361 sawnan2 = TRUE_;
362 }
363 /* Computing MAX */
364 r__2 = max2;
365 r__3 = (r__1 = work[i__ + 1], f2c_abs(r__1)); // , expr subst
366 max2 = max(r__2,r__3);
367 /* L7: */
368 }
369 sawnan2 = sawnan2 || sisnan_(&max2);
370 if (forcer || max2 <= growthbound && ! sawnan2)
371 {
372 *sigma = rsigma;
373 shift = 2;
374 goto L100;
375 }
376 /* If we are at this point, both shifts led to too much element growth */
377 /* Record the better of the two shifts (provided it didn't lead to NaN) */
378 if (sawnan1 && sawnan2)
379 {
380 /* both MAX1 and MAX2 are NaN */
381 goto L50;
382 }
383 else
384 {
385 if (! sawnan1)
386 {
387 indx = 1;
388 if (max1 <= smlgrowth)
389 {
390 smlgrowth = max1;
391 bestshift = lsigma;
392 }
393 }
394 if (! sawnan2)
395 {
396 if (sawnan1 || max2 <= max1)
397 {
398 indx = 2;
399 }
400 if (max2 <= smlgrowth)
401 {
402 smlgrowth = max2;
403 bestshift = rsigma;
404 }
405 }
406 }
407 /* If we are here, both the left and the right shift led to */
408 /* element growth. If the element growth is moderate, then */
409 /* we may still accept the representation, if it passes a */
410 /* refined test for RRR. This test supposes that no NaN occurred. */
411 /* Moreover, we use the refined RRR test only for isolated clusters. */
412 if (clwdth < mingap / 128.f && min(max1,max2) < fail2 && ! sawnan1 && ! sawnan2)
413 {
414 dorrr1 = TRUE_;
415 }
416 else
417 {
418 dorrr1 = FALSE_;
419 }
420 tryrrr1 = TRUE_;
421 if (tryrrr1 && dorrr1)
422 {
423 if (indx == 1)
424 {
425 tmp = (r__1 = dplus[*n], f2c_abs(r__1));
426 znm2 = 1.f;
427 prod = 1.f;
428 oldp = 1.f;
429 for (i__ = *n - 1;
430 i__ >= 1;
431 --i__)
432 {
433 if (prod <= eps)
434 {
435 prod = dplus[i__ + 1] * work[*n + i__ + 1] / (dplus[i__] * work[*n + i__]) * oldp;
436 }
437 else
438 {
439 prod *= (r__1 = work[*n + i__], f2c_abs(r__1));
440 }
441 oldp = prod;
442 /* Computing 2nd power */
443 r__1 = prod;
444 znm2 += r__1 * r__1;
445 /* Computing MAX */
446 r__2 = tmp;
447 r__3 = (r__1 = dplus[i__] * prod, f2c_abs(r__1)); // , expr subst
448 tmp = max(r__2,r__3);
449 /* L15: */
450 }
451 rrr1 = tmp / (*spdiam * sqrt(znm2));
452 if (rrr1 <= 8.f)
453 {
454 *sigma = lsigma;
455 shift = 1;
456 goto L100;
457 }
458 }
459 else if (indx == 2)
460 {
461 tmp = (r__1 = work[*n], f2c_abs(r__1));
462 znm2 = 1.f;
463 prod = 1.f;
464 oldp = 1.f;
465 for (i__ = *n - 1;
466 i__ >= 1;
467 --i__)
468 {
469 if (prod <= eps)
470 {
471 prod = work[i__ + 1] * lplus[i__ + 1] / (work[i__] * lplus[i__]) * oldp;
472 }
473 else
474 {
475 prod *= (r__1 = lplus[i__], f2c_abs(r__1));
476 }
477 oldp = prod;
478 /* Computing 2nd power */
479 r__1 = prod;
480 znm2 += r__1 * r__1;
481 /* Computing MAX */
482 r__2 = tmp;
483 r__3 = (r__1 = work[i__] * prod, f2c_abs(r__1)); // , expr subst
484 tmp = max(r__2,r__3);
485 /* L16: */
486 }
487 rrr2 = tmp / (*spdiam * sqrt(znm2));
488 if (rrr2 <= 8.f)
489 {
490 *sigma = rsigma;
491 shift = 2;
492 goto L100;
493 }
494 }
495 }
496 L50:
497 if (ktry < 1)
498 {
499 /* If we are here, both shifts failed also the RRR test. */
500 /* Back off to the outside */
501 /* Computing MAX */
502 r__1 = lsigma - ldelta;
503 r__2 = lsigma - ldmax; // , expr subst
504 lsigma = max(r__1,r__2);
505 /* Computing MIN */
506 r__1 = rsigma + rdelta;
507 r__2 = rsigma + rdmax; // , expr subst
508 rsigma = min(r__1,r__2);
509 ldelta *= 2.f;
510 rdelta *= 2.f;
511 ++ktry;
512 goto L5;
513 }
514 else
515 {
516 /* None of the representations investigated satisfied our */
517 /* criteria. Take the best one we found. */
518 if (smlgrowth < fail || nofail)
519 {
520 lsigma = bestshift;
521 rsigma = bestshift;
522 forcer = TRUE_;
523 goto L5;
524 }
525 else
526 {
527 *info = 1;
528 return 0;
529 }
530 }
531 L100:
532 if (shift == 1)
533 {
534 }
535 else if (shift == 2)
536 {
537 /* store new L and D back into DPLUS, LPLUS */
538 scopy_(n, &work[1], &c__1, &dplus[1], &c__1);
539 i__1 = *n - 1;
540 scopy_(&i__1, &work[*n + 1], &c__1, &lplus[1], &c__1);
541 }
542 return 0;
543 /* End of SLARRF */
544 }
545 /* slarrf_ */
546