Annotation of rpl/lapack/lapack/dstebz.f, revision 1.17
1.9 bertrand 1: *> \brief \b DSTEBZ
2: *
3: * =========== DOCUMENTATION ===========
4: *
1.16 bertrand 5: * Online html documentation available at
6: * http://www.netlib.org/lapack/explore-html/
1.9 bertrand 7: *
8: *> \htmlonly
1.16 bertrand 9: *> Download DSTEBZ + dependencies
10: *> <a href="http://www.netlib.org/cgi-bin/netlibfiles.tgz?format=tgz&filename=/lapack/lapack_routine/dstebz.f">
11: *> [TGZ]</a>
12: *> <a href="http://www.netlib.org/cgi-bin/netlibfiles.zip?format=zip&filename=/lapack/lapack_routine/dstebz.f">
13: *> [ZIP]</a>
14: *> <a href="http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/dstebz.f">
1.9 bertrand 15: *> [TXT]</a>
1.16 bertrand 16: *> \endhtmlonly
1.9 bertrand 17: *
18: * Definition:
19: * ===========
20: *
21: * SUBROUTINE DSTEBZ( RANGE, ORDER, N, VL, VU, IL, IU, ABSTOL, D, E,
22: * M, NSPLIT, W, IBLOCK, ISPLIT, WORK, IWORK,
23: * INFO )
1.16 bertrand 24: *
1.9 bertrand 25: * .. Scalar Arguments ..
26: * CHARACTER ORDER, RANGE
27: * INTEGER IL, INFO, IU, M, N, NSPLIT
28: * DOUBLE PRECISION ABSTOL, VL, VU
29: * ..
30: * .. Array Arguments ..
31: * INTEGER IBLOCK( * ), ISPLIT( * ), IWORK( * )
32: * DOUBLE PRECISION D( * ), E( * ), W( * ), WORK( * )
33: * ..
1.16 bertrand 34: *
1.9 bertrand 35: *
36: *> \par Purpose:
37: * =============
38: *>
39: *> \verbatim
40: *>
41: *> DSTEBZ computes the eigenvalues of a symmetric tridiagonal
42: *> matrix T. The user may ask for all eigenvalues, all eigenvalues
43: *> in the half-open interval (VL, VU], or the IL-th through IU-th
44: *> eigenvalues.
45: *>
46: *> To avoid overflow, the matrix must be scaled so that its
47: *> largest element is no greater than overflow**(1/2) * underflow**(1/4) in absolute value, and for greatest
48: *> accuracy, it should not be much smaller than that.
49: *>
50: *> See W. Kahan "Accurate Eigenvalues of a Symmetric Tridiagonal
51: *> Matrix", Report CS41, Computer Science Dept., Stanford
52: *> University, July 21, 1966.
53: *> \endverbatim
54: *
55: * Arguments:
56: * ==========
57: *
58: *> \param[in] RANGE
59: *> \verbatim
60: *> RANGE is CHARACTER*1
61: *> = 'A': ("All") all eigenvalues will be found.
62: *> = 'V': ("Value") all eigenvalues in the half-open interval
63: *> (VL, VU] will be found.
64: *> = 'I': ("Index") the IL-th through IU-th eigenvalues (of the
65: *> entire matrix) will be found.
66: *> \endverbatim
67: *>
68: *> \param[in] ORDER
69: *> \verbatim
70: *> ORDER is CHARACTER*1
71: *> = 'B': ("By Block") the eigenvalues will be grouped by
72: *> split-off block (see IBLOCK, ISPLIT) and
73: *> ordered from smallest to largest within
74: *> the block.
75: *> = 'E': ("Entire matrix")
76: *> the eigenvalues for the entire matrix
77: *> will be ordered from smallest to
78: *> largest.
79: *> \endverbatim
80: *>
81: *> \param[in] N
82: *> \verbatim
83: *> N is INTEGER
84: *> The order of the tridiagonal matrix T. N >= 0.
85: *> \endverbatim
86: *>
87: *> \param[in] VL
88: *> \verbatim
89: *> VL is DOUBLE PRECISION
1.14 bertrand 90: *>
91: *> If RANGE='V', the lower bound of the interval to
92: *> be searched for eigenvalues. Eigenvalues less than or equal
93: *> to VL, or greater than VU, will not be returned. VL < VU.
94: *> Not referenced if RANGE = 'A' or 'I'.
1.9 bertrand 95: *> \endverbatim
96: *>
97: *> \param[in] VU
98: *> \verbatim
99: *> VU is DOUBLE PRECISION
100: *>
1.14 bertrand 101: *> If RANGE='V', the upper bound of the interval to
1.9 bertrand 102: *> be searched for eigenvalues. Eigenvalues less than or equal
103: *> to VL, or greater than VU, will not be returned. VL < VU.
104: *> Not referenced if RANGE = 'A' or 'I'.
105: *> \endverbatim
106: *>
107: *> \param[in] IL
108: *> \verbatim
109: *> IL is INTEGER
1.14 bertrand 110: *>
111: *> If RANGE='I', the index of the
112: *> smallest eigenvalue to be returned.
113: *> 1 <= IL <= IU <= N, if N > 0; IL = 1 and IU = 0 if N = 0.
114: *> Not referenced if RANGE = 'A' or 'V'.
1.9 bertrand 115: *> \endverbatim
116: *>
117: *> \param[in] IU
118: *> \verbatim
119: *> IU is INTEGER
120: *>
1.14 bertrand 121: *> If RANGE='I', the index of the
122: *> largest eigenvalue to be returned.
1.9 bertrand 123: *> 1 <= IL <= IU <= N, if N > 0; IL = 1 and IU = 0 if N = 0.
124: *> Not referenced if RANGE = 'A' or 'V'.
125: *> \endverbatim
126: *>
127: *> \param[in] ABSTOL
128: *> \verbatim
129: *> ABSTOL is DOUBLE PRECISION
130: *> The absolute tolerance for the eigenvalues. An eigenvalue
131: *> (or cluster) is considered to be located if it has been
132: *> determined to lie in an interval whose width is ABSTOL or
133: *> less. If ABSTOL is less than or equal to zero, then ULP*|T|
134: *> will be used, where |T| means the 1-norm of T.
135: *>
136: *> Eigenvalues will be computed most accurately when ABSTOL is
137: *> set to twice the underflow threshold 2*DLAMCH('S'), not zero.
138: *> \endverbatim
139: *>
140: *> \param[in] D
141: *> \verbatim
142: *> D is DOUBLE PRECISION array, dimension (N)
143: *> The n diagonal elements of the tridiagonal matrix T.
144: *> \endverbatim
145: *>
146: *> \param[in] E
147: *> \verbatim
148: *> E is DOUBLE PRECISION array, dimension (N-1)
149: *> The (n-1) off-diagonal elements of the tridiagonal matrix T.
150: *> \endverbatim
151: *>
152: *> \param[out] M
153: *> \verbatim
154: *> M is INTEGER
155: *> The actual number of eigenvalues found. 0 <= M <= N.
156: *> (See also the description of INFO=2,3.)
157: *> \endverbatim
158: *>
159: *> \param[out] NSPLIT
160: *> \verbatim
161: *> NSPLIT is INTEGER
162: *> The number of diagonal blocks in the matrix T.
163: *> 1 <= NSPLIT <= N.
164: *> \endverbatim
165: *>
166: *> \param[out] W
167: *> \verbatim
168: *> W is DOUBLE PRECISION array, dimension (N)
169: *> On exit, the first M elements of W will contain the
170: *> eigenvalues. (DSTEBZ may use the remaining N-M elements as
171: *> workspace.)
172: *> \endverbatim
173: *>
174: *> \param[out] IBLOCK
175: *> \verbatim
176: *> IBLOCK is INTEGER array, dimension (N)
177: *> At each row/column j where E(j) is zero or small, the
178: *> matrix T is considered to split into a block diagonal
179: *> matrix. On exit, if INFO = 0, IBLOCK(i) specifies to which
180: *> block (from 1 to the number of blocks) the eigenvalue W(i)
181: *> belongs. (DSTEBZ may use the remaining N-M elements as
182: *> workspace.)
183: *> \endverbatim
184: *>
185: *> \param[out] ISPLIT
186: *> \verbatim
187: *> ISPLIT is INTEGER array, dimension (N)
188: *> The splitting points, at which T breaks up into submatrices.
189: *> The first submatrix consists of rows/columns 1 to ISPLIT(1),
190: *> the second of rows/columns ISPLIT(1)+1 through ISPLIT(2),
191: *> etc., and the NSPLIT-th consists of rows/columns
192: *> ISPLIT(NSPLIT-1)+1 through ISPLIT(NSPLIT)=N.
193: *> (Only the first NSPLIT elements will actually be used, but
194: *> since the user cannot know a priori what value NSPLIT will
195: *> have, N words must be reserved for ISPLIT.)
196: *> \endverbatim
197: *>
198: *> \param[out] WORK
199: *> \verbatim
200: *> WORK is DOUBLE PRECISION array, dimension (4*N)
201: *> \endverbatim
202: *>
203: *> \param[out] IWORK
204: *> \verbatim
205: *> IWORK is INTEGER array, dimension (3*N)
206: *> \endverbatim
207: *>
208: *> \param[out] INFO
209: *> \verbatim
210: *> INFO is INTEGER
211: *> = 0: successful exit
212: *> < 0: if INFO = -i, the i-th argument had an illegal value
213: *> > 0: some or all of the eigenvalues failed to converge or
214: *> were not computed:
215: *> =1 or 3: Bisection failed to converge for some
216: *> eigenvalues; these eigenvalues are flagged by a
217: *> negative block number. The effect is that the
218: *> eigenvalues may not be as accurate as the
219: *> absolute and relative tolerances. This is
220: *> generally caused by unexpectedly inaccurate
221: *> arithmetic.
222: *> =2 or 3: RANGE='I' only: Not all of the eigenvalues
223: *> IL:IU were found.
224: *> Effect: M < IU+1-IL
225: *> Cause: non-monotonic arithmetic, causing the
226: *> Sturm sequence to be non-monotonic.
227: *> Cure: recalculate, using RANGE='A', and pick
228: *> out eigenvalues IL:IU. In some cases,
229: *> increasing the PARAMETER "FUDGE" may
230: *> make things work.
231: *> = 4: RANGE='I', and the Gershgorin interval
232: *> initially used was too small. No eigenvalues
233: *> were computed.
234: *> Probable cause: your machine has sloppy
235: *> floating-point arithmetic.
236: *> Cure: Increase the PARAMETER "FUDGE",
237: *> recompile, and try again.
238: *> \endverbatim
239: *
240: *> \par Internal Parameters:
241: * =========================
242: *>
243: *> \verbatim
244: *> RELFAC DOUBLE PRECISION, default = 2.0e0
245: *> The relative tolerance. An interval (a,b] lies within
246: *> "relative tolerance" if b-a < RELFAC*ulp*max(|a|,|b|),
247: *> where "ulp" is the machine precision (distance from 1 to
248: *> the next larger floating point number.)
249: *>
250: *> FUDGE DOUBLE PRECISION, default = 2
251: *> A "fudge factor" to widen the Gershgorin intervals. Ideally,
252: *> a value of 1 should work, but on machines with sloppy
253: *> arithmetic, this needs to be larger. The default for
254: *> publicly released versions should be large enough to handle
255: *> the worst machine around. Note that this has no effect
256: *> on accuracy of the solution.
257: *> \endverbatim
258: *
259: * Authors:
260: * ========
261: *
1.16 bertrand 262: *> \author Univ. of Tennessee
263: *> \author Univ. of California Berkeley
264: *> \author Univ. of Colorado Denver
265: *> \author NAG Ltd.
1.9 bertrand 266: *
1.14 bertrand 267: *> \date June 2016
1.9 bertrand 268: *
269: *> \ingroup auxOTHERcomputational
270: *
271: * =====================================================================
1.1 bertrand 272: SUBROUTINE DSTEBZ( RANGE, ORDER, N, VL, VU, IL, IU, ABSTOL, D, E,
273: $ M, NSPLIT, W, IBLOCK, ISPLIT, WORK, IWORK,
274: $ INFO )
275: *
1.16 bertrand 276: * -- LAPACK computational routine (version 3.7.0) --
1.1 bertrand 277: * -- LAPACK is a software package provided by Univ. of Tennessee, --
278: * -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..--
1.14 bertrand 279: * June 2016
1.1 bertrand 280: *
281: * .. Scalar Arguments ..
282: CHARACTER ORDER, RANGE
283: INTEGER IL, INFO, IU, M, N, NSPLIT
284: DOUBLE PRECISION ABSTOL, VL, VU
285: * ..
286: * .. Array Arguments ..
287: INTEGER IBLOCK( * ), ISPLIT( * ), IWORK( * )
288: DOUBLE PRECISION D( * ), E( * ), W( * ), WORK( * )
289: * ..
290: *
291: * =====================================================================
292: *
293: * .. Parameters ..
294: DOUBLE PRECISION ZERO, ONE, TWO, HALF
295: PARAMETER ( ZERO = 0.0D0, ONE = 1.0D0, TWO = 2.0D0,
296: $ HALF = 1.0D0 / TWO )
297: DOUBLE PRECISION FUDGE, RELFAC
298: PARAMETER ( FUDGE = 2.1D0, RELFAC = 2.0D0 )
299: * ..
300: * .. Local Scalars ..
301: LOGICAL NCNVRG, TOOFEW
302: INTEGER IB, IBEGIN, IDISCL, IDISCU, IE, IEND, IINFO,
303: $ IM, IN, IOFF, IORDER, IOUT, IRANGE, ITMAX,
304: $ ITMP1, IW, IWOFF, J, JB, JDISC, JE, NB, NWL,
305: $ NWU
306: DOUBLE PRECISION ATOLI, BNORM, GL, GU, PIVMIN, RTOLI, SAFEMN,
307: $ TMP1, TMP2, TNORM, ULP, WKILL, WL, WLU, WU, WUL
308: * ..
309: * .. Local Arrays ..
310: INTEGER IDUMMA( 1 )
311: * ..
312: * .. External Functions ..
313: LOGICAL LSAME
314: INTEGER ILAENV
315: DOUBLE PRECISION DLAMCH
316: EXTERNAL LSAME, ILAENV, DLAMCH
317: * ..
318: * .. External Subroutines ..
319: EXTERNAL DLAEBZ, XERBLA
320: * ..
321: * .. Intrinsic Functions ..
322: INTRINSIC ABS, INT, LOG, MAX, MIN, SQRT
323: * ..
324: * .. Executable Statements ..
325: *
326: INFO = 0
327: *
328: * Decode RANGE
329: *
330: IF( LSAME( RANGE, 'A' ) ) THEN
331: IRANGE = 1
332: ELSE IF( LSAME( RANGE, 'V' ) ) THEN
333: IRANGE = 2
334: ELSE IF( LSAME( RANGE, 'I' ) ) THEN
335: IRANGE = 3
336: ELSE
337: IRANGE = 0
338: END IF
339: *
340: * Decode ORDER
341: *
342: IF( LSAME( ORDER, 'B' ) ) THEN
343: IORDER = 2
344: ELSE IF( LSAME( ORDER, 'E' ) ) THEN
345: IORDER = 1
346: ELSE
347: IORDER = 0
348: END IF
349: *
350: * Check for Errors
351: *
352: IF( IRANGE.LE.0 ) THEN
353: INFO = -1
354: ELSE IF( IORDER.LE.0 ) THEN
355: INFO = -2
356: ELSE IF( N.LT.0 ) THEN
357: INFO = -3
358: ELSE IF( IRANGE.EQ.2 ) THEN
359: IF( VL.GE.VU )
360: $ INFO = -5
361: ELSE IF( IRANGE.EQ.3 .AND. ( IL.LT.1 .OR. IL.GT.MAX( 1, N ) ) )
362: $ THEN
363: INFO = -6
364: ELSE IF( IRANGE.EQ.3 .AND. ( IU.LT.MIN( N, IL ) .OR. IU.GT.N ) )
365: $ THEN
366: INFO = -7
367: END IF
368: *
369: IF( INFO.NE.0 ) THEN
370: CALL XERBLA( 'DSTEBZ', -INFO )
371: RETURN
372: END IF
373: *
374: * Initialize error flags
375: *
376: INFO = 0
377: NCNVRG = .FALSE.
378: TOOFEW = .FALSE.
379: *
380: * Quick return if possible
381: *
382: M = 0
383: IF( N.EQ.0 )
384: $ RETURN
385: *
386: * Simplifications:
387: *
388: IF( IRANGE.EQ.3 .AND. IL.EQ.1 .AND. IU.EQ.N )
389: $ IRANGE = 1
390: *
391: * Get machine constants
392: * NB is the minimum vector length for vector bisection, or 0
393: * if only scalar is to be done.
394: *
395: SAFEMN = DLAMCH( 'S' )
396: ULP = DLAMCH( 'P' )
397: RTOLI = ULP*RELFAC
398: NB = ILAENV( 1, 'DSTEBZ', ' ', N, -1, -1, -1 )
399: IF( NB.LE.1 )
400: $ NB = 0
401: *
402: * Special Case when N=1
403: *
404: IF( N.EQ.1 ) THEN
405: NSPLIT = 1
406: ISPLIT( 1 ) = 1
407: IF( IRANGE.EQ.2 .AND. ( VL.GE.D( 1 ) .OR. VU.LT.D( 1 ) ) ) THEN
408: M = 0
409: ELSE
410: W( 1 ) = D( 1 )
411: IBLOCK( 1 ) = 1
412: M = 1
413: END IF
414: RETURN
415: END IF
416: *
417: * Compute Splitting Points
418: *
419: NSPLIT = 1
420: WORK( N ) = ZERO
421: PIVMIN = ONE
422: *
423: DO 10 J = 2, N
424: TMP1 = E( J-1 )**2
425: IF( ABS( D( J )*D( J-1 ) )*ULP**2+SAFEMN.GT.TMP1 ) THEN
426: ISPLIT( NSPLIT ) = J - 1
427: NSPLIT = NSPLIT + 1
428: WORK( J-1 ) = ZERO
429: ELSE
430: WORK( J-1 ) = TMP1
431: PIVMIN = MAX( PIVMIN, TMP1 )
432: END IF
433: 10 CONTINUE
434: ISPLIT( NSPLIT ) = N
435: PIVMIN = PIVMIN*SAFEMN
436: *
437: * Compute Interval and ATOLI
438: *
439: IF( IRANGE.EQ.3 ) THEN
440: *
441: * RANGE='I': Compute the interval containing eigenvalues
442: * IL through IU.
443: *
444: * Compute Gershgorin interval for entire (split) matrix
445: * and use it as the initial interval
446: *
447: GU = D( 1 )
448: GL = D( 1 )
449: TMP1 = ZERO
450: *
451: DO 20 J = 1, N - 1
452: TMP2 = SQRT( WORK( J ) )
453: GU = MAX( GU, D( J )+TMP1+TMP2 )
454: GL = MIN( GL, D( J )-TMP1-TMP2 )
455: TMP1 = TMP2
456: 20 CONTINUE
457: *
458: GU = MAX( GU, D( N )+TMP1 )
459: GL = MIN( GL, D( N )-TMP1 )
460: TNORM = MAX( ABS( GL ), ABS( GU ) )
461: GL = GL - FUDGE*TNORM*ULP*N - FUDGE*TWO*PIVMIN
462: GU = GU + FUDGE*TNORM*ULP*N + FUDGE*PIVMIN
463: *
464: * Compute Iteration parameters
465: *
466: ITMAX = INT( ( LOG( TNORM+PIVMIN )-LOG( PIVMIN ) ) /
467: $ LOG( TWO ) ) + 2
468: IF( ABSTOL.LE.ZERO ) THEN
469: ATOLI = ULP*TNORM
470: ELSE
471: ATOLI = ABSTOL
472: END IF
473: *
474: WORK( N+1 ) = GL
475: WORK( N+2 ) = GL
476: WORK( N+3 ) = GU
477: WORK( N+4 ) = GU
478: WORK( N+5 ) = GL
479: WORK( N+6 ) = GU
480: IWORK( 1 ) = -1
481: IWORK( 2 ) = -1
482: IWORK( 3 ) = N + 1
483: IWORK( 4 ) = N + 1
484: IWORK( 5 ) = IL - 1
485: IWORK( 6 ) = IU
486: *
487: CALL DLAEBZ( 3, ITMAX, N, 2, 2, NB, ATOLI, RTOLI, PIVMIN, D, E,
488: $ WORK, IWORK( 5 ), WORK( N+1 ), WORK( N+5 ), IOUT,
489: $ IWORK, W, IBLOCK, IINFO )
490: *
491: IF( IWORK( 6 ).EQ.IU ) THEN
492: WL = WORK( N+1 )
493: WLU = WORK( N+3 )
494: NWL = IWORK( 1 )
495: WU = WORK( N+4 )
496: WUL = WORK( N+2 )
497: NWU = IWORK( 4 )
498: ELSE
499: WL = WORK( N+2 )
500: WLU = WORK( N+4 )
501: NWL = IWORK( 2 )
502: WU = WORK( N+3 )
503: WUL = WORK( N+1 )
504: NWU = IWORK( 3 )
505: END IF
506: *
507: IF( NWL.LT.0 .OR. NWL.GE.N .OR. NWU.LT.1 .OR. NWU.GT.N ) THEN
508: INFO = 4
509: RETURN
510: END IF
511: ELSE
512: *
513: * RANGE='A' or 'V' -- Set ATOLI
514: *
515: TNORM = MAX( ABS( D( 1 ) )+ABS( E( 1 ) ),
516: $ ABS( D( N ) )+ABS( E( N-1 ) ) )
517: *
518: DO 30 J = 2, N - 1
519: TNORM = MAX( TNORM, ABS( D( J ) )+ABS( E( J-1 ) )+
520: $ ABS( E( J ) ) )
521: 30 CONTINUE
522: *
523: IF( ABSTOL.LE.ZERO ) THEN
524: ATOLI = ULP*TNORM
525: ELSE
526: ATOLI = ABSTOL
527: END IF
528: *
529: IF( IRANGE.EQ.2 ) THEN
530: WL = VL
531: WU = VU
532: ELSE
533: WL = ZERO
534: WU = ZERO
535: END IF
536: END IF
537: *
538: * Find Eigenvalues -- Loop Over Blocks and recompute NWL and NWU.
539: * NWL accumulates the number of eigenvalues .le. WL,
540: * NWU accumulates the number of eigenvalues .le. WU
541: *
542: M = 0
543: IEND = 0
544: INFO = 0
545: NWL = 0
546: NWU = 0
547: *
548: DO 70 JB = 1, NSPLIT
549: IOFF = IEND
550: IBEGIN = IOFF + 1
551: IEND = ISPLIT( JB )
552: IN = IEND - IOFF
553: *
554: IF( IN.EQ.1 ) THEN
555: *
556: * Special Case -- IN=1
557: *
558: IF( IRANGE.EQ.1 .OR. WL.GE.D( IBEGIN )-PIVMIN )
559: $ NWL = NWL + 1
560: IF( IRANGE.EQ.1 .OR. WU.GE.D( IBEGIN )-PIVMIN )
561: $ NWU = NWU + 1
562: IF( IRANGE.EQ.1 .OR. ( WL.LT.D( IBEGIN )-PIVMIN .AND. WU.GE.
563: $ D( IBEGIN )-PIVMIN ) ) THEN
564: M = M + 1
565: W( M ) = D( IBEGIN )
566: IBLOCK( M ) = JB
567: END IF
568: ELSE
569: *
570: * General Case -- IN > 1
571: *
572: * Compute Gershgorin Interval
573: * and use it as the initial interval
574: *
575: GU = D( IBEGIN )
576: GL = D( IBEGIN )
577: TMP1 = ZERO
578: *
579: DO 40 J = IBEGIN, IEND - 1
580: TMP2 = ABS( E( J ) )
581: GU = MAX( GU, D( J )+TMP1+TMP2 )
582: GL = MIN( GL, D( J )-TMP1-TMP2 )
583: TMP1 = TMP2
584: 40 CONTINUE
585: *
586: GU = MAX( GU, D( IEND )+TMP1 )
587: GL = MIN( GL, D( IEND )-TMP1 )
588: BNORM = MAX( ABS( GL ), ABS( GU ) )
589: GL = GL - FUDGE*BNORM*ULP*IN - FUDGE*PIVMIN
590: GU = GU + FUDGE*BNORM*ULP*IN + FUDGE*PIVMIN
591: *
592: * Compute ATOLI for the current submatrix
593: *
594: IF( ABSTOL.LE.ZERO ) THEN
595: ATOLI = ULP*MAX( ABS( GL ), ABS( GU ) )
596: ELSE
597: ATOLI = ABSTOL
598: END IF
599: *
600: IF( IRANGE.GT.1 ) THEN
601: IF( GU.LT.WL ) THEN
602: NWL = NWL + IN
603: NWU = NWU + IN
604: GO TO 70
605: END IF
606: GL = MAX( GL, WL )
607: GU = MIN( GU, WU )
608: IF( GL.GE.GU )
609: $ GO TO 70
610: END IF
611: *
612: * Set Up Initial Interval
613: *
614: WORK( N+1 ) = GL
615: WORK( N+IN+1 ) = GU
616: CALL DLAEBZ( 1, 0, IN, IN, 1, NB, ATOLI, RTOLI, PIVMIN,
617: $ D( IBEGIN ), E( IBEGIN ), WORK( IBEGIN ),
618: $ IDUMMA, WORK( N+1 ), WORK( N+2*IN+1 ), IM,
619: $ IWORK, W( M+1 ), IBLOCK( M+1 ), IINFO )
620: *
621: NWL = NWL + IWORK( 1 )
622: NWU = NWU + IWORK( IN+1 )
623: IWOFF = M - IWORK( 1 )
624: *
625: * Compute Eigenvalues
626: *
627: ITMAX = INT( ( LOG( GU-GL+PIVMIN )-LOG( PIVMIN ) ) /
628: $ LOG( TWO ) ) + 2
629: CALL DLAEBZ( 2, ITMAX, IN, IN, 1, NB, ATOLI, RTOLI, PIVMIN,
630: $ D( IBEGIN ), E( IBEGIN ), WORK( IBEGIN ),
631: $ IDUMMA, WORK( N+1 ), WORK( N+2*IN+1 ), IOUT,
632: $ IWORK, W( M+1 ), IBLOCK( M+1 ), IINFO )
633: *
634: * Copy Eigenvalues Into W and IBLOCK
635: * Use -JB for block number for unconverged eigenvalues.
636: *
637: DO 60 J = 1, IOUT
638: TMP1 = HALF*( WORK( J+N )+WORK( J+IN+N ) )
639: *
640: * Flag non-convergence.
641: *
642: IF( J.GT.IOUT-IINFO ) THEN
643: NCNVRG = .TRUE.
644: IB = -JB
645: ELSE
646: IB = JB
647: END IF
648: DO 50 JE = IWORK( J ) + 1 + IWOFF,
649: $ IWORK( J+IN ) + IWOFF
650: W( JE ) = TMP1
651: IBLOCK( JE ) = IB
652: 50 CONTINUE
653: 60 CONTINUE
654: *
655: M = M + IM
656: END IF
657: 70 CONTINUE
658: *
659: * If RANGE='I', then (WL,WU) contains eigenvalues NWL+1,...,NWU
660: * If NWL+1 < IL or NWU > IU, discard extra eigenvalues.
661: *
662: IF( IRANGE.EQ.3 ) THEN
663: IM = 0
664: IDISCL = IL - 1 - NWL
665: IDISCU = NWU - IU
666: *
667: IF( IDISCL.GT.0 .OR. IDISCU.GT.0 ) THEN
668: DO 80 JE = 1, M
669: IF( W( JE ).LE.WLU .AND. IDISCL.GT.0 ) THEN
670: IDISCL = IDISCL - 1
671: ELSE IF( W( JE ).GE.WUL .AND. IDISCU.GT.0 ) THEN
672: IDISCU = IDISCU - 1
673: ELSE
674: IM = IM + 1
675: W( IM ) = W( JE )
676: IBLOCK( IM ) = IBLOCK( JE )
677: END IF
678: 80 CONTINUE
679: M = IM
680: END IF
681: IF( IDISCL.GT.0 .OR. IDISCU.GT.0 ) THEN
682: *
683: * Code to deal with effects of bad arithmetic:
684: * Some low eigenvalues to be discarded are not in (WL,WLU],
685: * or high eigenvalues to be discarded are not in (WUL,WU]
686: * so just kill off the smallest IDISCL/largest IDISCU
687: * eigenvalues, by simply finding the smallest/largest
688: * eigenvalue(s).
689: *
690: * (If N(w) is monotone non-decreasing, this should never
691: * happen.)
692: *
693: IF( IDISCL.GT.0 ) THEN
694: WKILL = WU
695: DO 100 JDISC = 1, IDISCL
696: IW = 0
697: DO 90 JE = 1, M
698: IF( IBLOCK( JE ).NE.0 .AND.
699: $ ( W( JE ).LT.WKILL .OR. IW.EQ.0 ) ) THEN
700: IW = JE
701: WKILL = W( JE )
702: END IF
703: 90 CONTINUE
704: IBLOCK( IW ) = 0
705: 100 CONTINUE
706: END IF
707: IF( IDISCU.GT.0 ) THEN
708: *
709: WKILL = WL
710: DO 120 JDISC = 1, IDISCU
711: IW = 0
712: DO 110 JE = 1, M
713: IF( IBLOCK( JE ).NE.0 .AND.
714: $ ( W( JE ).GT.WKILL .OR. IW.EQ.0 ) ) THEN
715: IW = JE
716: WKILL = W( JE )
717: END IF
718: 110 CONTINUE
719: IBLOCK( IW ) = 0
720: 120 CONTINUE
721: END IF
722: IM = 0
723: DO 130 JE = 1, M
724: IF( IBLOCK( JE ).NE.0 ) THEN
725: IM = IM + 1
726: W( IM ) = W( JE )
727: IBLOCK( IM ) = IBLOCK( JE )
728: END IF
729: 130 CONTINUE
730: M = IM
731: END IF
732: IF( IDISCL.LT.0 .OR. IDISCU.LT.0 ) THEN
733: TOOFEW = .TRUE.
734: END IF
735: END IF
736: *
737: * If ORDER='B', do nothing -- the eigenvalues are already sorted
738: * by block.
739: * If ORDER='E', sort the eigenvalues from smallest to largest
740: *
741: IF( IORDER.EQ.1 .AND. NSPLIT.GT.1 ) THEN
742: DO 150 JE = 1, M - 1
743: IE = 0
744: TMP1 = W( JE )
745: DO 140 J = JE + 1, M
746: IF( W( J ).LT.TMP1 ) THEN
747: IE = J
748: TMP1 = W( J )
749: END IF
750: 140 CONTINUE
751: *
752: IF( IE.NE.0 ) THEN
753: ITMP1 = IBLOCK( IE )
754: W( IE ) = W( JE )
755: IBLOCK( IE ) = IBLOCK( JE )
756: W( JE ) = TMP1
757: IBLOCK( JE ) = ITMP1
758: END IF
759: 150 CONTINUE
760: END IF
761: *
762: INFO = 0
763: IF( NCNVRG )
764: $ INFO = INFO + 1
765: IF( TOOFEW )
766: $ INFO = INFO + 2
767: RETURN
768: *
769: * End of DSTEBZ
770: *
771: END
CVSweb interface <joel.bertrand@systella.fr>