3 * =========== DOCUMENTATION ===========
5 * Online html documentation available at
6 * http://www.netlib.org/lapack/explore-html/
9 *> Download SSTEBZ + dependencies
10 *> <a href="http://www.netlib.org/cgi-bin/netlibfiles.tgz?format=tgz&filename=/lapack/lapack_routine/sstebz.f">
12 *> <a href="http://www.netlib.org/cgi-bin/netlibfiles.zip?format=zip&filename=/lapack/lapack_routine/sstebz.f">
14 *> <a href="http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/sstebz.f">
21 * SUBROUTINE SSTEBZ( RANGE, ORDER, N, VL, VU, IL, IU, ABSTOL, D, E,
22 * M, NSPLIT, W, IBLOCK, ISPLIT, WORK, IWORK,
25 * .. Scalar Arguments ..
26 * CHARACTER ORDER, RANGE
27 * INTEGER IL, INFO, IU, M, N, NSPLIT
30 * .. Array Arguments ..
31 * INTEGER IBLOCK( * ), ISPLIT( * ), IWORK( * )
32 * REAL D( * ), E( * ), W( * ), WORK( * )
41 *> SSTEBZ 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
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.
50 *> See W. Kahan "Accurate Eigenvalues of a Symmetric Tridiagonal
51 *> Matrix", Report CS41, Computer Science Dept., Stanford
52 *> University, July 21, 1966.
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.
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
75 *> = 'E': ("Entire matrix")
76 *> the eigenvalues for the entire matrix
77 *> will be ordered from smallest to
84 *> The order of the tridiagonal matrix T. N >= 0.
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'.
101 *> If RANGE='V', the upper bound of the interval to
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'.
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'.
121 *> If RANGE='I', the index of the
122 *> largest eigenvalue to be returned.
123 *> 1 <= IL <= IU <= N, if N > 0; IL = 1 and IU = 0 if N = 0.
124 *> Not referenced if RANGE = 'A' or 'V'.
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.
136 *> Eigenvalues will be computed most accurately when ABSTOL is
137 *> set to twice the underflow threshold 2*SLAMCH('S'), not zero.
142 *> D is REAL array, dimension (N)
143 *> The n diagonal elements of the tridiagonal matrix T.
148 *> E is REAL array, dimension (N-1)
149 *> The (n-1) off-diagonal elements of the tridiagonal matrix T.
155 *> The actual number of eigenvalues found. 0 <= M <= N.
156 *> (See also the description of INFO=2,3.)
159 *> \param[out] NSPLIT
162 *> The number of diagonal blocks in the matrix T.
168 *> W is REAL array, dimension (N)
169 *> On exit, the first M elements of W will contain the
170 *> eigenvalues. (SSTEBZ may use the remaining N-M elements as
174 *> \param[out] IBLOCK
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. (SSTEBZ may use the remaining N-M elements as
185 *> \param[out] ISPLIT
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.)
200 *> WORK is REAL array, dimension (4*N)
205 *> IWORK is INTEGER array, dimension (3*N)
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
222 *> =2 or 3: RANGE='I' only: Not all of the eigenvalues
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
231 *> = 4: RANGE='I', and the Gershgorin interval
232 *> initially used was too small. No eigenvalues
234 *> Probable cause: your machine has sloppy
235 *> floating-point arithmetic.
236 *> Cure: Increase the PARAMETER "FUDGE",
237 *> recompile, and try again.
240 *> \par Internal Parameters:
241 * =========================
244 *> RELFAC REAL, 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.)
250 *> FUDGE REAL, 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.
262 *> \author Univ. of Tennessee
263 *> \author Univ. of California Berkeley
264 *> \author Univ. of Colorado Denver
269 *> \ingroup auxOTHERcomputational
271 * =====================================================================
272 SUBROUTINE SSTEBZ( RANGE, ORDER, N, VL, VU, IL, IU, ABSTOL, D, E,
273 $ M, NSPLIT, W, IBLOCK, ISPLIT, WORK, IWORK,
276 * -- LAPACK computational routine (version 3.6.1) --
277 * -- LAPACK is a software package provided by Univ. of Tennessee, --
278 * -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..--
281 * .. Scalar Arguments ..
282 CHARACTER ORDER, RANGE
283 INTEGER IL, INFO, IU, M, N, NSPLIT
286 * .. Array Arguments ..
287 INTEGER IBLOCK( * ), ISPLIT( * ), IWORK( * )
288 REAL D( * ), E( * ), W( * ), WORK( * )
291 * =====================================================================
294 REAL ZERO, ONE, TWO, HALF
295 PARAMETER ( ZERO = 0.0E0, ONE = 1.0E0, TWO = 2.0E0,
296 $ HALF = 1.0E0 / TWO )
298 PARAMETER ( FUDGE = 2.1E0, RELFAC = 2.0E0 )
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,
306 REAL ATOLI, BNORM, GL, GU, PIVMIN, RTOLI, SAFEMN,
307 $ TMP1, TMP2, TNORM, ULP, WKILL, WL, WLU, WU, WUL
312 * .. External Functions ..
316 EXTERNAL LSAME, ILAENV, SLAMCH
318 * .. External Subroutines ..
319 EXTERNAL SLAEBZ, XERBLA
321 * .. Intrinsic Functions ..
322 INTRINSIC ABS, INT, LOG, MAX, MIN, SQRT
324 * .. Executable Statements ..
330 IF( LSAME( RANGE, 'A' ) ) THEN
332 ELSE IF( LSAME( RANGE, 'V' ) ) THEN
334 ELSE IF( LSAME( RANGE, 'I' ) ) THEN
342 IF( LSAME( ORDER, 'B' ) ) THEN
344 ELSE IF( LSAME( ORDER, 'E' ) ) THEN
352 IF( IRANGE.LE.0 ) THEN
354 ELSE IF( IORDER.LE.0 ) THEN
356 ELSE IF( N.LT.0 ) THEN
358 ELSE IF( IRANGE.EQ.2 ) THEN
359 IF( VL.GE.VU ) INFO = -5
360 ELSE IF( IRANGE.EQ.3 .AND. ( IL.LT.1 .OR. IL.GT.MAX( 1, N ) ) )
363 ELSE IF( IRANGE.EQ.3 .AND. ( IU.LT.MIN( N, IL ) .OR. IU.GT.N ) )
369 CALL XERBLA( 'SSTEBZ', -INFO )
373 * Initialize error flags
379 * Quick return if possible
387 IF( IRANGE.EQ.3 .AND. IL.EQ.1 .AND. IU.EQ.N )
390 * Get machine constants
391 * NB is the minimum vector length for vector bisection, or 0
392 * if only scalar is to be done.
394 SAFEMN = SLAMCH( 'S' )
397 NB = ILAENV( 1, 'SSTEBZ', ' ', N, -1, -1, -1 )
401 * Special Case when N=1
406 IF( IRANGE.EQ.2 .AND. ( VL.GE.D( 1 ) .OR. VU.LT.D( 1 ) ) ) THEN
416 * Compute Splitting Points
424 IF( ABS( D( J )*D( J-1 ) )*ULP**2+SAFEMN.GT.TMP1 ) THEN
425 ISPLIT( NSPLIT ) = J - 1
430 PIVMIN = MAX( PIVMIN, TMP1 )
434 PIVMIN = PIVMIN*SAFEMN
436 * Compute Interval and ATOLI
438 IF( IRANGE.EQ.3 ) THEN
440 * RANGE='I': Compute the interval containing eigenvalues
443 * Compute Gershgorin interval for entire (split) matrix
444 * and use it as the initial interval
451 TMP2 = SQRT( WORK( J ) )
452 GU = MAX( GU, D( J )+TMP1+TMP2 )
453 GL = MIN( GL, D( J )-TMP1-TMP2 )
457 GU = MAX( GU, D( N )+TMP1 )
458 GL = MIN( GL, D( N )-TMP1 )
459 TNORM = MAX( ABS( GL ), ABS( GU ) )
460 GL = GL - FUDGE*TNORM*ULP*N - FUDGE*TWO*PIVMIN
461 GU = GU + FUDGE*TNORM*ULP*N + FUDGE*PIVMIN
463 * Compute Iteration parameters
465 ITMAX = INT( ( LOG( TNORM+PIVMIN )-LOG( PIVMIN ) ) /
467 IF( ABSTOL.LE.ZERO ) THEN
486 CALL SLAEBZ( 3, ITMAX, N, 2, 2, NB, ATOLI, RTOLI, PIVMIN, D, E,
487 $ WORK, IWORK( 5 ), WORK( N+1 ), WORK( N+5 ), IOUT,
488 $ IWORK, W, IBLOCK, IINFO )
490 IF( IWORK( 6 ).EQ.IU ) THEN
506 IF( NWL.LT.0 .OR. NWL.GE.N .OR. NWU.LT.1 .OR. NWU.GT.N ) THEN
512 * RANGE='A' or 'V' -- Set ATOLI
514 TNORM = MAX( ABS( D( 1 ) )+ABS( E( 1 ) ),
515 $ ABS( D( N ) )+ABS( E( N-1 ) ) )
518 TNORM = MAX( TNORM, ABS( D( J ) )+ABS( E( J-1 ) )+
522 IF( ABSTOL.LE.ZERO ) THEN
528 IF( IRANGE.EQ.2 ) THEN
537 * Find Eigenvalues -- Loop Over Blocks and recompute NWL and NWU.
538 * NWL accumulates the number of eigenvalues .le. WL,
539 * NWU accumulates the number of eigenvalues .le. WU
555 * Special Case -- IN=1
557 IF( IRANGE.EQ.1 .OR. WL.GE.D( IBEGIN )-PIVMIN )
559 IF( IRANGE.EQ.1 .OR. WU.GE.D( IBEGIN )-PIVMIN )
561 IF( IRANGE.EQ.1 .OR. ( WL.LT.D( IBEGIN )-PIVMIN .AND. WU.GE.
562 $ D( IBEGIN )-PIVMIN ) ) THEN
569 * General Case -- IN > 1
571 * Compute Gershgorin Interval
572 * and use it as the initial interval
578 DO 40 J = IBEGIN, IEND - 1
580 GU = MAX( GU, D( J )+TMP1+TMP2 )
581 GL = MIN( GL, D( J )-TMP1-TMP2 )
585 GU = MAX( GU, D( IEND )+TMP1 )
586 GL = MIN( GL, D( IEND )-TMP1 )
587 BNORM = MAX( ABS( GL ), ABS( GU ) )
588 GL = GL - FUDGE*BNORM*ULP*IN - FUDGE*PIVMIN
589 GU = GU + FUDGE*BNORM*ULP*IN + FUDGE*PIVMIN
591 * Compute ATOLI for the current submatrix
593 IF( ABSTOL.LE.ZERO ) THEN
594 ATOLI = ULP*MAX( ABS( GL ), ABS( GU ) )
599 IF( IRANGE.GT.1 ) THEN
611 * Set Up Initial Interval
615 CALL SLAEBZ( 1, 0, IN, IN, 1, NB, ATOLI, RTOLI, PIVMIN,
616 $ D( IBEGIN ), E( IBEGIN ), WORK( IBEGIN ),
617 $ IDUMMA, WORK( N+1 ), WORK( N+2*IN+1 ), IM,
618 $ IWORK, W( M+1 ), IBLOCK( M+1 ), IINFO )
620 NWL = NWL + IWORK( 1 )
621 NWU = NWU + IWORK( IN+1 )
622 IWOFF = M - IWORK( 1 )
624 * Compute Eigenvalues
626 ITMAX = INT( ( LOG( GU-GL+PIVMIN )-LOG( PIVMIN ) ) /
628 CALL SLAEBZ( 2, ITMAX, IN, IN, 1, NB, ATOLI, RTOLI, PIVMIN,
629 $ D( IBEGIN ), E( IBEGIN ), WORK( IBEGIN ),
630 $ IDUMMA, WORK( N+1 ), WORK( N+2*IN+1 ), IOUT,
631 $ IWORK, W( M+1 ), IBLOCK( M+1 ), IINFO )
633 * Copy Eigenvalues Into W and IBLOCK
634 * Use -JB for block number for unconverged eigenvalues.
637 TMP1 = HALF*( WORK( J+N )+WORK( J+IN+N ) )
639 * Flag non-convergence.
641 IF( J.GT.IOUT-IINFO ) THEN
647 DO 50 JE = IWORK( J ) + 1 + IWOFF,
648 $ IWORK( J+IN ) + IWOFF
658 * If RANGE='I', then (WL,WU) contains eigenvalues NWL+1,...,NWU
659 * If NWL+1 < IL or NWU > IU, discard extra eigenvalues.
661 IF( IRANGE.EQ.3 ) THEN
663 IDISCL = IL - 1 - NWL
666 IF( IDISCL.GT.0 .OR. IDISCU.GT.0 ) THEN
668 IF( W( JE ).LE.WLU .AND. IDISCL.GT.0 ) THEN
670 ELSE IF( W( JE ).GE.WUL .AND. IDISCU.GT.0 ) THEN
675 IBLOCK( IM ) = IBLOCK( JE )
680 IF( IDISCL.GT.0 .OR. IDISCU.GT.0 ) THEN
682 * Code to deal with effects of bad arithmetic:
683 * Some low eigenvalues to be discarded are not in (WL,WLU],
684 * or high eigenvalues to be discarded are not in (WUL,WU]
685 * so just kill off the smallest IDISCL/largest IDISCU
686 * eigenvalues, by simply finding the smallest/largest
689 * (If N(w) is monotone non-decreasing, this should never
692 IF( IDISCL.GT.0 ) THEN
694 DO 100 JDISC = 1, IDISCL
697 IF( IBLOCK( JE ).NE.0 .AND.
698 $ ( W( JE ).LT.WKILL .OR. IW.EQ.0 ) ) THEN
706 IF( IDISCU.GT.0 ) THEN
709 DO 120 JDISC = 1, IDISCU
712 IF( IBLOCK( JE ).NE.0 .AND.
713 $ ( W( JE ).GT.WKILL .OR. IW.EQ.0 ) ) THEN
723 IF( IBLOCK( JE ).NE.0 ) THEN
726 IBLOCK( IM ) = IBLOCK( JE )
731 IF( IDISCL.LT.0 .OR. IDISCU.LT.0 ) THEN
736 * If ORDER='B', do nothing -- the eigenvalues are already sorted
738 * If ORDER='E', sort the eigenvalues from smallest to largest
740 IF( IORDER.EQ.1 .AND. NSPLIT.GT.1 ) THEN
745 IF( W( J ).LT.TMP1 ) THEN
754 IBLOCK( IE ) = IBLOCK( JE )