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