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