Update to 2.0.0 tree from current Fremantle build
[opencv] / 3rdparty / lapack / slarrb.c
1 #include "clapack.h"
2
3 /* Subroutine */ int slarrb_(integer *n, real *d__, real *lld, integer *
4         ifirst, integer *ilast, real *rtol1, real *rtol2, integer *offset, 
5         real *w, real *wgap, real *werr, real *work, integer *iwork, real *
6         pivmin, real *spdiam, integer *twist, integer *info)
7 {
8     /* System generated locals */
9     integer i__1;
10     real r__1, r__2;
11
12     /* Builtin functions */
13     double log(doublereal);
14
15     /* Local variables */
16     integer i__, k, r__, i1, ii, ip;
17     real gap, mid, tmp, back, lgap, rgap, left;
18     integer iter, nint, prev, next;
19     real cvrgd, right, width;
20     extern integer slaneg_(integer *, real *, real *, real *, real *, integer 
21             *);
22     integer negcnt;
23     real mnwdth;
24     integer olnint, maxitr;
25
26
27 /*  -- LAPACK auxiliary routine (version 3.1) -- */
28 /*     Univ. of Tennessee, Univ. of California Berkeley and NAG Ltd.. */
29 /*     November 2006 */
30
31 /*     .. Scalar Arguments .. */
32 /*     .. */
33 /*     .. Array Arguments .. */
34 /*     .. */
35
36 /*  Purpose */
37 /*  ======= */
38
39 /*  Given the relatively robust representation(RRR) L D L^T, SLARRB */
40 /*  does "limited" bisection to refine the eigenvalues of L D L^T, */
41 /*  W( IFIRST-OFFSET ) through W( ILAST-OFFSET ), to more accuracy. Initial */
42 /*  guesses for these eigenvalues are input in W, the corresponding estimate */
43 /*  of the error in these guesses and their gaps are input in WERR */
44 /*  and WGAP, respectively. During bisection, intervals */
45 /*  [left, right] are maintained by storing their mid-points and */
46 /*  semi-widths in the arrays W and WERR respectively. */
47
48 /*  Arguments */
49 /*  ========= */
50
51 /*  N       (input) INTEGER */
52 /*          The order of the matrix. */
53
54 /*  D       (input) REAL             array, dimension (N) */
55 /*          The N diagonal elements of the diagonal matrix D. */
56
57 /*  LLD     (input) REAL             array, dimension (N-1) */
58 /*          The (N-1) elements L(i)*L(i)*D(i). */
59
60 /*  IFIRST  (input) INTEGER */
61 /*          The index of the first eigenvalue to be computed. */
62
63 /*  ILAST   (input) INTEGER */
64 /*          The index of the last eigenvalue to be computed. */
65
66 /*  RTOL1   (input) REAL */
67 /*  RTOL2   (input) REAL */
68 /*          Tolerance for the convergence of the bisection intervals. */
69 /*          An interval [LEFT,RIGHT] has converged if */
70 /*          RIGHT-LEFT.LT.MAX( RTOL1*GAP, RTOL2*MAX(|LEFT|,|RIGHT|) ) */
71 /*          where GAP is the (estimated) distance to the nearest */
72 /*          eigenvalue. */
73
74 /*  OFFSET  (input) INTEGER */
75 /*          Offset for the arrays W, WGAP and WERR, i.e., the IFIRST-OFFSET */
76 /*          through ILAST-OFFSET elements of these arrays are to be used. */
77
78 /*  W       (input/output) REAL             array, dimension (N) */
79 /*          On input, W( IFIRST-OFFSET ) through W( ILAST-OFFSET ) are */
80 /*          estimates of the eigenvalues of L D L^T indexed IFIRST throug */
81 /*          ILAST. */
82 /*          On output, these estimates are refined. */
83
84 /*  WGAP    (input/output) REAL             array, dimension (N-1) */
85 /*          On input, the (estimated) gaps between consecutive */
86 /*          eigenvalues of L D L^T, i.e., WGAP(I-OFFSET) is the gap between */
87 /*          eigenvalues I and I+1. Note that if IFIRST.EQ.ILAST */
88 /*          then WGAP(IFIRST-OFFSET) must be set to ZERO. */
89 /*          On output, these gaps are refined. */
90
91 /*  WERR    (input/output) REAL             array, dimension (N) */
92 /*          On input, WERR( IFIRST-OFFSET ) through WERR( ILAST-OFFSET ) are */
93 /*          the errors in the estimates of the corresponding elements in W. */
94 /*          On output, these errors are refined. */
95
96 /*  WORK    (workspace) REAL             array, dimension (2*N) */
97 /*          Workspace. */
98
99 /*  IWORK   (workspace) INTEGER array, dimension (2*N) */
100 /*          Workspace. */
101
102 /*  PIVMIN  (input) DOUBLE PRECISION */
103 /*          The minimum pivot in the Sturm sequence. */
104
105 /*  SPDIAM  (input) DOUBLE PRECISION */
106 /*          The spectral diameter of the matrix. */
107
108 /*  TWIST   (input) INTEGER */
109 /*          The twist index for the twisted factorization that is used */
110 /*          for the negcount. */
111 /*          TWIST = N: Compute negcount from L D L^T - LAMBDA I = L+ D+ L+^T */
112 /*          TWIST = 1: Compute negcount from L D L^T - LAMBDA I = U- D- U-^T */
113 /*          TWIST = R: Compute negcount from L D L^T - LAMBDA I = N(r) D(r) N(r) */
114
115 /*  INFO    (output) INTEGER */
116 /*          Error flag. */
117
118 /*  Further Details */
119 /*  =============== */
120
121 /*  Based on contributions by */
122 /*     Beresford Parlett, University of California, Berkeley, USA */
123 /*     Jim Demmel, University of California, Berkeley, USA */
124 /*     Inderjit Dhillon, University of Texas, Austin, USA */
125 /*     Osni Marques, LBNL/NERSC, USA */
126 /*     Christof Voemel, University of California, Berkeley, USA */
127
128 /*  ===================================================================== */
129
130 /*     .. Parameters .. */
131 /*     .. */
132 /*     .. Local Scalars .. */
133 /*     .. */
134 /*     .. External Functions .. */
135
136 /*     .. */
137 /*     .. Intrinsic Functions .. */
138 /*     .. */
139 /*     .. Executable Statements .. */
140
141     /* Parameter adjustments */
142     --iwork;
143     --work;
144     --werr;
145     --wgap;
146     --w;
147     --lld;
148     --d__;
149
150     /* Function Body */
151     *info = 0;
152
153     maxitr = (integer) ((log(*spdiam + *pivmin) - log(*pivmin)) / log(2.f)) + 
154             2;
155     mnwdth = *pivmin * 2.f;
156
157     r__ = *twist;
158     if (r__ < 1 || r__ > *n) {
159         r__ = *n;
160     }
161
162 /*     Initialize unconverged intervals in [ WORK(2*I-1), WORK(2*I) ]. */
163 /*     The Sturm Count, Count( WORK(2*I-1) ) is arranged to be I-1, while */
164 /*     Count( WORK(2*I) ) is stored in IWORK( 2*I ). The integer IWORK( 2*I-1 ) */
165 /*     for an unconverged interval is set to the index of the next unconverged */
166 /*     interval, and is -1 or 0 for a converged interval. Thus a linked */
167 /*     list of unconverged intervals is set up. */
168
169     i1 = *ifirst;
170 /*     The number of unconverged intervals */
171     nint = 0;
172 /*     The last unconverged interval found */
173     prev = 0;
174     rgap = wgap[i1 - *offset];
175     i__1 = *ilast;
176     for (i__ = i1; i__ <= i__1; ++i__) {
177         k = i__ << 1;
178         ii = i__ - *offset;
179         left = w[ii] - werr[ii];
180         right = w[ii] + werr[ii];
181         lgap = rgap;
182         rgap = wgap[ii];
183         gap = dmin(lgap,rgap);
184 /*        Make sure that [LEFT,RIGHT] contains the desired eigenvalue */
185 /*        Compute negcount from dstqds facto L+D+L+^T = L D L^T - LEFT */
186
187 /*        Do while( NEGCNT(LEFT).GT.I-1 ) */
188
189         back = werr[ii];
190 L20:
191         negcnt = slaneg_(n, &d__[1], &lld[1], &left, pivmin, &r__);
192         if (negcnt > i__ - 1) {
193             left -= back;
194             back *= 2.f;
195             goto L20;
196         }
197
198 /*        Do while( NEGCNT(RIGHT).LT.I ) */
199 /*        Compute negcount from dstqds facto L+D+L+^T = L D L^T - RIGHT */
200
201         back = werr[ii];
202 L50:
203         negcnt = slaneg_(n, &d__[1], &lld[1], &right, pivmin, &r__);
204         if (negcnt < i__) {
205             right += back;
206             back *= 2.f;
207             goto L50;
208         }
209         width = (r__1 = left - right, dabs(r__1)) * .5f;
210 /* Computing MAX */
211         r__1 = dabs(left), r__2 = dabs(right);
212         tmp = dmax(r__1,r__2);
213 /* Computing MAX */
214         r__1 = *rtol1 * gap, r__2 = *rtol2 * tmp;
215         cvrgd = dmax(r__1,r__2);
216         if (width <= cvrgd || width <= mnwdth) {
217 /*           This interval has already converged and does not need refinement. */
218 /*           (Note that the gaps might change through refining the */
219 /*            eigenvalues, however, they can only get bigger.) */
220 /*           Remove it from the list. */
221             iwork[k - 1] = -1;
222 /*           Make sure that I1 always points to the first unconverged interval */
223             if (i__ == i1 && i__ < *ilast) {
224                 i1 = i__ + 1;
225             }
226             if (prev >= i1 && i__ <= *ilast) {
227                 iwork[(prev << 1) - 1] = i__ + 1;
228             }
229         } else {
230 /*           unconverged interval found */
231             prev = i__;
232             ++nint;
233             iwork[k - 1] = i__ + 1;
234             iwork[k] = negcnt;
235         }
236         work[k - 1] = left;
237         work[k] = right;
238 /* L75: */
239     }
240
241 /*     Do while( NINT.GT.0 ), i.e. there are still unconverged intervals */
242 /*     and while (ITER.LT.MAXITR) */
243
244     iter = 0;
245 L80:
246     prev = i1 - 1;
247     i__ = i1;
248     olnint = nint;
249     i__1 = olnint;
250     for (ip = 1; ip <= i__1; ++ip) {
251         k = i__ << 1;
252         ii = i__ - *offset;
253         rgap = wgap[ii];
254         lgap = rgap;
255         if (ii > 1) {
256             lgap = wgap[ii - 1];
257         }
258         gap = dmin(lgap,rgap);
259         next = iwork[k - 1];
260         left = work[k - 1];
261         right = work[k];
262         mid = (left + right) * .5f;
263 /*        semiwidth of interval */
264         width = right - mid;
265 /* Computing MAX */
266         r__1 = dabs(left), r__2 = dabs(right);
267         tmp = dmax(r__1,r__2);
268 /* Computing MAX */
269         r__1 = *rtol1 * gap, r__2 = *rtol2 * tmp;
270         cvrgd = dmax(r__1,r__2);
271         if (width <= cvrgd || width <= mnwdth || iter == maxitr) {
272 /*           reduce number of unconverged intervals */
273             --nint;
274 /*           Mark interval as converged. */
275             iwork[k - 1] = 0;
276             if (i1 == i__) {
277                 i1 = next;
278             } else {
279 /*              Prev holds the last unconverged interval previously examined */
280                 if (prev >= i1) {
281                     iwork[(prev << 1) - 1] = next;
282                 }
283             }
284             i__ = next;
285             goto L100;
286         }
287         prev = i__;
288
289 /*        Perform one bisection step */
290
291         negcnt = slaneg_(n, &d__[1], &lld[1], &mid, pivmin, &r__);
292         if (negcnt <= i__ - 1) {
293             work[k - 1] = mid;
294         } else {
295             work[k] = mid;
296         }
297         i__ = next;
298 L100:
299         ;
300     }
301     ++iter;
302 /*     do another loop if there are still unconverged intervals */
303 /*     However, in the last iteration, all intervals are accepted */
304 /*     since this is the best we can do. */
305     if (nint > 0 && iter <= maxitr) {
306         goto L80;
307     }
308
309
310 /*     At this point, all the intervals have converged */
311     i__1 = *ilast;
312     for (i__ = *ifirst; i__ <= i__1; ++i__) {
313         k = i__ << 1;
314         ii = i__ - *offset;
315 /*        All intervals marked by '0' have been refined. */
316         if (iwork[k - 1] == 0) {
317             w[ii] = (work[k - 1] + work[k]) * .5f;
318             werr[ii] = work[k] - w[ii];
319         }
320 /* L110: */
321     }
322
323     i__1 = *ilast;
324     for (i__ = *ifirst + 1; i__ <= i__1; ++i__) {
325         k = i__ << 1;
326         ii = i__ - *offset;
327 /* Computing MAX */
328         r__1 = 0.f, r__2 = w[ii] - werr[ii] - w[ii - 1] - werr[ii - 1];
329         wgap[ii - 1] = dmax(r__1,r__2);
330 /* L111: */
331     }
332     return 0;
333
334 /*     End of SLARRB */
335
336 } /* slarrb_ */