Update to 2.0.0 tree from current Fremantle build
[opencv] / 3rdparty / lapack / sstebz.c
1 #include "clapack.h"
2
3 /* Table of constant values */
4
5 static integer c__1 = 1;
6 static integer c_n1 = -1;
7 static integer c__3 = 3;
8 static integer c__2 = 2;
9 static integer c__0 = 0;
10
11 /* Subroutine */ int sstebz_(char *range, char *order, integer *n, real *vl, 
12         real *vu, integer *il, integer *iu, real *abstol, real *d__, real *e, 
13         integer *m, integer *nsplit, real *w, integer *iblock, integer *
14         isplit, real *work, integer *iwork, integer *info)
15 {
16     /* System generated locals */
17     integer i__1, i__2, i__3;
18     real r__1, r__2, r__3, r__4, r__5;
19
20     /* Builtin functions */
21     double sqrt(doublereal), log(doublereal);
22
23     /* Local variables */
24     integer j, ib, jb, ie, je, nb;
25     real gl;
26     integer im, in;
27     real gu;
28     integer iw;
29     real wl, wu;
30     integer nwl;
31     real ulp, wlu, wul;
32     integer nwu;
33     real tmp1, tmp2;
34     integer iend, ioff, iout, itmp1, jdisc;
35     extern logical lsame_(char *, char *);
36     integer iinfo;
37     real atoli;
38     integer iwoff;
39     real bnorm;
40     integer itmax;
41     real wkill, rtoli, tnorm;
42     integer ibegin, irange, idiscl;
43     extern doublereal slamch_(char *);
44     real safemn;
45     integer idumma[1];
46     extern /* Subroutine */ int xerbla_(char *, integer *);
47     extern integer ilaenv_(integer *, char *, char *, integer *, integer *, 
48             integer *, integer *);
49     integer idiscu;
50     extern /* Subroutine */ int slaebz_(integer *, integer *, integer *, 
51             integer *, integer *, integer *, real *, real *, real *, real *, 
52             real *, real *, integer *, real *, real *, integer *, integer *, 
53             real *, integer *, integer *);
54     integer iorder;
55     logical ncnvrg;
56     real pivmin;
57     logical toofew;
58
59
60 /*  -- LAPACK routine (version 3.1) -- */
61 /*     Univ. of Tennessee, Univ. of California Berkeley and NAG Ltd.. */
62 /*     November 2006 */
63 /*     8-18-00:  Increase FUDGE factor for T3E (eca) */
64
65 /*     .. Scalar Arguments .. */
66 /*     .. */
67 /*     .. Array Arguments .. */
68 /*     .. */
69
70 /*  Purpose */
71 /*  ======= */
72
73 /*  SSTEBZ computes the eigenvalues of a symmetric tridiagonal */
74 /*  matrix T.  The user may ask for all eigenvalues, all eigenvalues */
75 /*  in the half-open interval (VL, VU], or the IL-th through IU-th */
76 /*  eigenvalues. */
77
78 /*  To avoid overflow, the matrix must be scaled so that its */
79 /*  largest element is no greater than overflow**(1/2) * */
80 /*  underflow**(1/4) in absolute value, and for greatest */
81 /*  accuracy, it should not be much smaller than that. */
82
83 /*  See W. Kahan "Accurate Eigenvalues of a Symmetric Tridiagonal */
84 /*  Matrix", Report CS41, Computer Science Dept., Stanford */
85 /*  University, July 21, 1966. */
86
87 /*  Arguments */
88 /*  ========= */
89
90 /*  RANGE   (input) CHARACTER*1 */
91 /*          = 'A': ("All")   all eigenvalues will be found. */
92 /*          = 'V': ("Value") all eigenvalues in the half-open interval */
93 /*                           (VL, VU] will be found. */
94 /*          = 'I': ("Index") the IL-th through IU-th eigenvalues (of the */
95 /*                           entire matrix) will be found. */
96
97 /*  ORDER   (input) CHARACTER*1 */
98 /*          = 'B': ("By Block") the eigenvalues will be grouped by */
99 /*                              split-off block (see IBLOCK, ISPLIT) and */
100 /*                              ordered from smallest to largest within */
101 /*                              the block. */
102 /*          = 'E': ("Entire matrix") */
103 /*                              the eigenvalues for the entire matrix */
104 /*                              will be ordered from smallest to */
105 /*                              largest. */
106
107 /*  N       (input) INTEGER */
108 /*          The order of the tridiagonal matrix T.  N >= 0. */
109
110 /*  VL      (input) REAL */
111 /*  VU      (input) REAL */
112 /*          If RANGE='V', the lower and upper bounds of the interval to */
113 /*          be searched for eigenvalues.  Eigenvalues less than or equal */
114 /*          to VL, or greater than VU, will not be returned.  VL < VU. */
115 /*          Not referenced if RANGE = 'A' or 'I'. */
116
117 /*  IL      (input) INTEGER */
118 /*  IU      (input) INTEGER */
119 /*          If RANGE='I', the indices (in ascending order) of the */
120 /*          smallest and largest eigenvalues to be returned. */
121 /*          1 <= IL <= IU <= N, if N > 0; IL = 1 and IU = 0 if N = 0. */
122 /*          Not referenced if RANGE = 'A' or 'V'. */
123
124 /*  ABSTOL  (input) REAL */
125 /*          The absolute tolerance for the eigenvalues.  An eigenvalue */
126 /*          (or cluster) is considered to be located if it has been */
127 /*          determined to lie in an interval whose width is ABSTOL or */
128 /*          less.  If ABSTOL is less than or equal to zero, then ULP*|T| */
129 /*          will be used, where |T| means the 1-norm of T. */
130
131 /*          Eigenvalues will be computed most accurately when ABSTOL is */
132 /*          set to twice the underflow threshold 2*SLAMCH('S'), not zero. */
133
134 /*  D       (input) REAL array, dimension (N) */
135 /*          The n diagonal elements of the tridiagonal matrix T. */
136
137 /*  E       (input) REAL array, dimension (N-1) */
138 /*          The (n-1) off-diagonal elements of the tridiagonal matrix T. */
139
140 /*  M       (output) INTEGER */
141 /*          The actual number of eigenvalues found. 0 <= M <= N. */
142 /*          (See also the description of INFO=2,3.) */
143
144 /*  NSPLIT  (output) INTEGER */
145 /*          The number of diagonal blocks in the matrix T. */
146 /*          1 <= NSPLIT <= N. */
147
148 /*  W       (output) REAL array, dimension (N) */
149 /*          On exit, the first M elements of W will contain the */
150 /*          eigenvalues.  (SSTEBZ may use the remaining N-M elements as */
151 /*          workspace.) */
152
153 /*  IBLOCK  (output) INTEGER array, dimension (N) */
154 /*          At each row/column j where E(j) is zero or small, the */
155 /*          matrix T is considered to split into a block diagonal */
156 /*          matrix.  On exit, if INFO = 0, IBLOCK(i) specifies to which */
157 /*          block (from 1 to the number of blocks) the eigenvalue W(i) */
158 /*          belongs.  (SSTEBZ may use the remaining N-M elements as */
159 /*          workspace.) */
160
161 /*  ISPLIT  (output) INTEGER array, dimension (N) */
162 /*          The splitting points, at which T breaks up into submatrices. */
163 /*          The first submatrix consists of rows/columns 1 to ISPLIT(1), */
164 /*          the second of rows/columns ISPLIT(1)+1 through ISPLIT(2), */
165 /*          etc., and the NSPLIT-th consists of rows/columns */
166 /*          ISPLIT(NSPLIT-1)+1 through ISPLIT(NSPLIT)=N. */
167 /*          (Only the first NSPLIT elements will actually be used, but */
168 /*          since the user cannot know a priori what value NSPLIT will */
169 /*          have, N words must be reserved for ISPLIT.) */
170
171 /*  WORK    (workspace) REAL array, dimension (4*N) */
172
173 /*  IWORK   (workspace) INTEGER array, dimension (3*N) */
174
175 /*  INFO    (output) INTEGER */
176 /*          = 0:  successful exit */
177 /*          < 0:  if INFO = -i, the i-th argument had an illegal value */
178 /*          > 0:  some or all of the eigenvalues failed to converge or */
179 /*                were not computed: */
180 /*                =1 or 3: Bisection failed to converge for some */
181 /*                        eigenvalues; these eigenvalues are flagged by a */
182 /*                        negative block number.  The effect is that the */
183 /*                        eigenvalues may not be as accurate as the */
184 /*                        absolute and relative tolerances.  This is */
185 /*                        generally caused by unexpectedly inaccurate */
186 /*                        arithmetic. */
187 /*                =2 or 3: RANGE='I' only: Not all of the eigenvalues */
188 /*                        IL:IU were found. */
189 /*                        Effect: M < IU+1-IL */
190 /*                        Cause:  non-monotonic arithmetic, causing the */
191 /*                                Sturm sequence to be non-monotonic. */
192 /*                        Cure:   recalculate, using RANGE='A', and pick */
193 /*                                out eigenvalues IL:IU.  In some cases, */
194 /*                                increasing the PARAMETER "FUDGE" may */
195 /*                                make things work. */
196 /*                = 4:    RANGE='I', and the Gershgorin interval */
197 /*                        initially used was too small.  No eigenvalues */
198 /*                        were computed. */
199 /*                        Probable cause: your machine has sloppy */
200 /*                                        floating-point arithmetic. */
201 /*                        Cure: Increase the PARAMETER "FUDGE", */
202 /*                              recompile, and try again. */
203
204 /*  Internal Parameters */
205 /*  =================== */
206
207 /*  RELFAC  REAL, default = 2.0e0 */
208 /*          The relative tolerance.  An interval (a,b] lies within */
209 /*          "relative tolerance" if  b-a < RELFAC*ulp*max(|a|,|b|), */
210 /*          where "ulp" is the machine precision (distance from 1 to */
211 /*          the next larger floating point number.) */
212
213 /*  FUDGE   REAL, default = 2 */
214 /*          A "fudge factor" to widen the Gershgorin intervals.  Ideally, */
215 /*          a value of 1 should work, but on machines with sloppy */
216 /*          arithmetic, this needs to be larger.  The default for */
217 /*          publicly released versions should be large enough to handle */
218 /*          the worst machine around.  Note that this has no effect */
219 /*          on accuracy of the solution. */
220
221 /*  ===================================================================== */
222
223 /*     .. Parameters .. */
224 /*     .. */
225 /*     .. Local Scalars .. */
226 /*     .. */
227 /*     .. Local Arrays .. */
228 /*     .. */
229 /*     .. External Functions .. */
230 /*     .. */
231 /*     .. External Subroutines .. */
232 /*     .. */
233 /*     .. Intrinsic Functions .. */
234 /*     .. */
235 /*     .. Executable Statements .. */
236
237     /* Parameter adjustments */
238     --iwork;
239     --work;
240     --isplit;
241     --iblock;
242     --w;
243     --e;
244     --d__;
245
246     /* Function Body */
247     *info = 0;
248
249 /*     Decode RANGE */
250
251     if (lsame_(range, "A")) {
252         irange = 1;
253     } else if (lsame_(range, "V")) {
254         irange = 2;
255     } else if (lsame_(range, "I")) {
256         irange = 3;
257     } else {
258         irange = 0;
259     }
260
261 /*     Decode ORDER */
262
263     if (lsame_(order, "B")) {
264         iorder = 2;
265     } else if (lsame_(order, "E")) {
266         iorder = 1;
267     } else {
268         iorder = 0;
269     }
270
271 /*     Check for Errors */
272
273     if (irange <= 0) {
274         *info = -1;
275     } else if (iorder <= 0) {
276         *info = -2;
277     } else if (*n < 0) {
278         *info = -3;
279     } else if (irange == 2) {
280         if (*vl >= *vu) {
281             *info = -5;
282         }
283     } else if (irange == 3 && (*il < 1 || *il > max(1,*n))) {
284         *info = -6;
285     } else if (irange == 3 && (*iu < min(*n,*il) || *iu > *n)) {
286         *info = -7;
287     }
288
289     if (*info != 0) {
290         i__1 = -(*info);
291         xerbla_("SSTEBZ", &i__1);
292         return 0;
293     }
294
295 /*     Initialize error flags */
296
297     *info = 0;
298     ncnvrg = FALSE_;
299     toofew = FALSE_;
300
301 /*     Quick return if possible */
302
303     *m = 0;
304     if (*n == 0) {
305         return 0;
306     }
307
308 /*     Simplifications: */
309
310     if (irange == 3 && *il == 1 && *iu == *n) {
311         irange = 1;
312     }
313
314 /*     Get machine constants */
315 /*     NB is the minimum vector length for vector bisection, or 0 */
316 /*     if only scalar is to be done. */
317
318     safemn = slamch_("S");
319     ulp = slamch_("P");
320     rtoli = ulp * 2.f;
321     nb = ilaenv_(&c__1, "SSTEBZ", " ", n, &c_n1, &c_n1, &c_n1);
322     if (nb <= 1) {
323         nb = 0;
324     }
325
326 /*     Special Case when N=1 */
327
328     if (*n == 1) {
329         *nsplit = 1;
330         isplit[1] = 1;
331         if (irange == 2 && (*vl >= d__[1] || *vu < d__[1])) {
332             *m = 0;
333         } else {
334             w[1] = d__[1];
335             iblock[1] = 1;
336             *m = 1;
337         }
338         return 0;
339     }
340
341 /*     Compute Splitting Points */
342
343     *nsplit = 1;
344     work[*n] = 0.f;
345     pivmin = 1.f;
346
347 /* DIR$ NOVECTOR */
348     i__1 = *n;
349     for (j = 2; j <= i__1; ++j) {
350 /* Computing 2nd power */
351         r__1 = e[j - 1];
352         tmp1 = r__1 * r__1;
353 /* Computing 2nd power */
354         r__2 = ulp;
355         if ((r__1 = d__[j] * d__[j - 1], dabs(r__1)) * (r__2 * r__2) + safemn 
356                 > tmp1) {
357             isplit[*nsplit] = j - 1;
358             ++(*nsplit);
359             work[j - 1] = 0.f;
360         } else {
361             work[j - 1] = tmp1;
362             pivmin = dmax(pivmin,tmp1);
363         }
364 /* L10: */
365     }
366     isplit[*nsplit] = *n;
367     pivmin *= safemn;
368
369 /*     Compute Interval and ATOLI */
370
371     if (irange == 3) {
372
373 /*        RANGE='I': Compute the interval containing eigenvalues */
374 /*                   IL through IU. */
375
376 /*        Compute Gershgorin interval for entire (split) matrix */
377 /*        and use it as the initial interval */
378
379         gu = d__[1];
380         gl = d__[1];
381         tmp1 = 0.f;
382
383         i__1 = *n - 1;
384         for (j = 1; j <= i__1; ++j) {
385             tmp2 = sqrt(work[j]);
386 /* Computing MAX */
387             r__1 = gu, r__2 = d__[j] + tmp1 + tmp2;
388             gu = dmax(r__1,r__2);
389 /* Computing MIN */
390             r__1 = gl, r__2 = d__[j] - tmp1 - tmp2;
391             gl = dmin(r__1,r__2);
392             tmp1 = tmp2;
393 /* L20: */
394         }
395
396 /* Computing MAX */
397         r__1 = gu, r__2 = d__[*n] + tmp1;
398         gu = dmax(r__1,r__2);
399 /* Computing MIN */
400         r__1 = gl, r__2 = d__[*n] - tmp1;
401         gl = dmin(r__1,r__2);
402 /* Computing MAX */
403         r__1 = dabs(gl), r__2 = dabs(gu);
404         tnorm = dmax(r__1,r__2);
405         gl = gl - tnorm * 2.1f * ulp * *n - pivmin * 4.2000000000000002f;
406         gu = gu + tnorm * 2.1f * ulp * *n + pivmin * 2.1f;
407
408 /*        Compute Iteration parameters */
409
410         itmax = (integer) ((log(tnorm + pivmin) - log(pivmin)) / log(2.f)) + 
411                 2;
412         if (*abstol <= 0.f) {
413             atoli = ulp * tnorm;
414         } else {
415             atoli = *abstol;
416         }
417
418         work[*n + 1] = gl;
419         work[*n + 2] = gl;
420         work[*n + 3] = gu;
421         work[*n + 4] = gu;
422         work[*n + 5] = gl;
423         work[*n + 6] = gu;
424         iwork[1] = -1;
425         iwork[2] = -1;
426         iwork[3] = *n + 1;
427         iwork[4] = *n + 1;
428         iwork[5] = *il - 1;
429         iwork[6] = *iu;
430
431         slaebz_(&c__3, &itmax, n, &c__2, &c__2, &nb, &atoli, &rtoli, &pivmin, 
432                 &d__[1], &e[1], &work[1], &iwork[5], &work[*n + 1], &work[*n 
433                 + 5], &iout, &iwork[1], &w[1], &iblock[1], &iinfo);
434
435         if (iwork[6] == *iu) {
436             wl = work[*n + 1];
437             wlu = work[*n + 3];
438             nwl = iwork[1];
439             wu = work[*n + 4];
440             wul = work[*n + 2];
441             nwu = iwork[4];
442         } else {
443             wl = work[*n + 2];
444             wlu = work[*n + 4];
445             nwl = iwork[2];
446             wu = work[*n + 3];
447             wul = work[*n + 1];
448             nwu = iwork[3];
449         }
450
451         if (nwl < 0 || nwl >= *n || nwu < 1 || nwu > *n) {
452             *info = 4;
453             return 0;
454         }
455     } else {
456
457 /*        RANGE='A' or 'V' -- Set ATOLI */
458
459 /* Computing MAX */
460         r__3 = dabs(d__[1]) + dabs(e[1]), r__4 = (r__1 = d__[*n], dabs(r__1)) 
461                 + (r__2 = e[*n - 1], dabs(r__2));
462         tnorm = dmax(r__3,r__4);
463
464         i__1 = *n - 1;
465         for (j = 2; j <= i__1; ++j) {
466 /* Computing MAX */
467             r__4 = tnorm, r__5 = (r__1 = d__[j], dabs(r__1)) + (r__2 = e[j - 
468                     1], dabs(r__2)) + (r__3 = e[j], dabs(r__3));
469             tnorm = dmax(r__4,r__5);
470 /* L30: */
471         }
472
473         if (*abstol <= 0.f) {
474             atoli = ulp * tnorm;
475         } else {
476             atoli = *abstol;
477         }
478
479         if (irange == 2) {
480             wl = *vl;
481             wu = *vu;
482         } else {
483             wl = 0.f;
484             wu = 0.f;
485         }
486     }
487
488 /*     Find Eigenvalues -- Loop Over Blocks and recompute NWL and NWU. */
489 /*     NWL accumulates the number of eigenvalues .le. WL, */
490 /*     NWU accumulates the number of eigenvalues .le. WU */
491
492     *m = 0;
493     iend = 0;
494     *info = 0;
495     nwl = 0;
496     nwu = 0;
497
498     i__1 = *nsplit;
499     for (jb = 1; jb <= i__1; ++jb) {
500         ioff = iend;
501         ibegin = ioff + 1;
502         iend = isplit[jb];
503         in = iend - ioff;
504
505         if (in == 1) {
506
507 /*           Special Case -- IN=1 */
508
509             if (irange == 1 || wl >= d__[ibegin] - pivmin) {
510                 ++nwl;
511             }
512             if (irange == 1 || wu >= d__[ibegin] - pivmin) {
513                 ++nwu;
514             }
515             if (irange == 1 || wl < d__[ibegin] - pivmin && wu >= d__[ibegin] 
516                     - pivmin) {
517                 ++(*m);
518                 w[*m] = d__[ibegin];
519                 iblock[*m] = jb;
520             }
521         } else {
522
523 /*           General Case -- IN > 1 */
524
525 /*           Compute Gershgorin Interval */
526 /*           and use it as the initial interval */
527
528             gu = d__[ibegin];
529             gl = d__[ibegin];
530             tmp1 = 0.f;
531
532             i__2 = iend - 1;
533             for (j = ibegin; j <= i__2; ++j) {
534                 tmp2 = (r__1 = e[j], dabs(r__1));
535 /* Computing MAX */
536                 r__1 = gu, r__2 = d__[j] + tmp1 + tmp2;
537                 gu = dmax(r__1,r__2);
538 /* Computing MIN */
539                 r__1 = gl, r__2 = d__[j] - tmp1 - tmp2;
540                 gl = dmin(r__1,r__2);
541                 tmp1 = tmp2;
542 /* L40: */
543             }
544
545 /* Computing MAX */
546             r__1 = gu, r__2 = d__[iend] + tmp1;
547             gu = dmax(r__1,r__2);
548 /* Computing MIN */
549             r__1 = gl, r__2 = d__[iend] - tmp1;
550             gl = dmin(r__1,r__2);
551 /* Computing MAX */
552             r__1 = dabs(gl), r__2 = dabs(gu);
553             bnorm = dmax(r__1,r__2);
554             gl = gl - bnorm * 2.1f * ulp * in - pivmin * 2.1f;
555             gu = gu + bnorm * 2.1f * ulp * in + pivmin * 2.1f;
556
557 /*           Compute ATOLI for the current submatrix */
558
559             if (*abstol <= 0.f) {
560 /* Computing MAX */
561                 r__1 = dabs(gl), r__2 = dabs(gu);
562                 atoli = ulp * dmax(r__1,r__2);
563             } else {
564                 atoli = *abstol;
565             }
566
567             if (irange > 1) {
568                 if (gu < wl) {
569                     nwl += in;
570                     nwu += in;
571                     goto L70;
572                 }
573                 gl = dmax(gl,wl);
574                 gu = dmin(gu,wu);
575                 if (gl >= gu) {
576                     goto L70;
577                 }
578             }
579
580 /*           Set Up Initial Interval */
581
582             work[*n + 1] = gl;
583             work[*n + in + 1] = gu;
584             slaebz_(&c__1, &c__0, &in, &in, &c__1, &nb, &atoli, &rtoli, &
585                     pivmin, &d__[ibegin], &e[ibegin], &work[ibegin], idumma, &
586                     work[*n + 1], &work[*n + (in << 1) + 1], &im, &iwork[1], &
587                     w[*m + 1], &iblock[*m + 1], &iinfo);
588
589             nwl += iwork[1];
590             nwu += iwork[in + 1];
591             iwoff = *m - iwork[1];
592
593 /*           Compute Eigenvalues */
594
595             itmax = (integer) ((log(gu - gl + pivmin) - log(pivmin)) / log(
596                     2.f)) + 2;
597             slaebz_(&c__2, &itmax, &in, &in, &c__1, &nb, &atoli, &rtoli, &
598                     pivmin, &d__[ibegin], &e[ibegin], &work[ibegin], idumma, &
599                     work[*n + 1], &work[*n + (in << 1) + 1], &iout, &iwork[1], 
600                      &w[*m + 1], &iblock[*m + 1], &iinfo);
601
602 /*           Copy Eigenvalues Into W and IBLOCK */
603 /*           Use -JB for block number for unconverged eigenvalues. */
604
605             i__2 = iout;
606             for (j = 1; j <= i__2; ++j) {
607                 tmp1 = (work[j + *n] + work[j + in + *n]) * .5f;
608
609 /*              Flag non-convergence. */
610
611                 if (j > iout - iinfo) {
612                     ncnvrg = TRUE_;
613                     ib = -jb;
614                 } else {
615                     ib = jb;
616                 }
617                 i__3 = iwork[j + in] + iwoff;
618                 for (je = iwork[j] + 1 + iwoff; je <= i__3; ++je) {
619                     w[je] = tmp1;
620                     iblock[je] = ib;
621 /* L50: */
622                 }
623 /* L60: */
624             }
625
626             *m += im;
627         }
628 L70:
629         ;
630     }
631
632 /*     If RANGE='I', then (WL,WU) contains eigenvalues NWL+1,...,NWU */
633 /*     If NWL+1 < IL or NWU > IU, discard extra eigenvalues. */
634
635     if (irange == 3) {
636         im = 0;
637         idiscl = *il - 1 - nwl;
638         idiscu = nwu - *iu;
639
640         if (idiscl > 0 || idiscu > 0) {
641             i__1 = *m;
642             for (je = 1; je <= i__1; ++je) {
643                 if (w[je] <= wlu && idiscl > 0) {
644                     --idiscl;
645                 } else if (w[je] >= wul && idiscu > 0) {
646                     --idiscu;
647                 } else {
648                     ++im;
649                     w[im] = w[je];
650                     iblock[im] = iblock[je];
651                 }
652 /* L80: */
653             }
654             *m = im;
655         }
656         if (idiscl > 0 || idiscu > 0) {
657
658 /*           Code to deal with effects of bad arithmetic: */
659 /*           Some low eigenvalues to be discarded are not in (WL,WLU], */
660 /*           or high eigenvalues to be discarded are not in (WUL,WU] */
661 /*           so just kill off the smallest IDISCL/largest IDISCU */
662 /*           eigenvalues, by simply finding the smallest/largest */
663 /*           eigenvalue(s). */
664
665 /*           (If N(w) is monotone non-decreasing, this should never */
666 /*               happen.) */
667
668             if (idiscl > 0) {
669                 wkill = wu;
670                 i__1 = idiscl;
671                 for (jdisc = 1; jdisc <= i__1; ++jdisc) {
672                     iw = 0;
673                     i__2 = *m;
674                     for (je = 1; je <= i__2; ++je) {
675                         if (iblock[je] != 0 && (w[je] < wkill || iw == 0)) {
676                             iw = je;
677                             wkill = w[je];
678                         }
679 /* L90: */
680                     }
681                     iblock[iw] = 0;
682 /* L100: */
683                 }
684             }
685             if (idiscu > 0) {
686
687                 wkill = wl;
688                 i__1 = idiscu;
689                 for (jdisc = 1; jdisc <= i__1; ++jdisc) {
690                     iw = 0;
691                     i__2 = *m;
692                     for (je = 1; je <= i__2; ++je) {
693                         if (iblock[je] != 0 && (w[je] > wkill || iw == 0)) {
694                             iw = je;
695                             wkill = w[je];
696                         }
697 /* L110: */
698                     }
699                     iblock[iw] = 0;
700 /* L120: */
701                 }
702             }
703             im = 0;
704             i__1 = *m;
705             for (je = 1; je <= i__1; ++je) {
706                 if (iblock[je] != 0) {
707                     ++im;
708                     w[im] = w[je];
709                     iblock[im] = iblock[je];
710                 }
711 /* L130: */
712             }
713             *m = im;
714         }
715         if (idiscl < 0 || idiscu < 0) {
716             toofew = TRUE_;
717         }
718     }
719
720 /*     If ORDER='B', do nothing -- the eigenvalues are already sorted */
721 /*        by block. */
722 /*     If ORDER='E', sort the eigenvalues from smallest to largest */
723
724     if (iorder == 1 && *nsplit > 1) {
725         i__1 = *m - 1;
726         for (je = 1; je <= i__1; ++je) {
727             ie = 0;
728             tmp1 = w[je];
729             i__2 = *m;
730             for (j = je + 1; j <= i__2; ++j) {
731                 if (w[j] < tmp1) {
732                     ie = j;
733                     tmp1 = w[j];
734                 }
735 /* L140: */
736             }
737
738             if (ie != 0) {
739                 itmp1 = iblock[ie];
740                 w[ie] = w[je];
741                 iblock[ie] = iblock[je];
742                 w[je] = tmp1;
743                 iblock[je] = itmp1;
744             }
745 /* L150: */
746         }
747     }
748
749     *info = 0;
750     if (ncnvrg) {
751         ++(*info);
752     }
753     if (toofew) {
754         *info += 2;
755     }
756     return 0;
757
758 /*     End of SSTEBZ */
759
760 } /* sstebz_ */