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