LAPACK 3.12.1
LAPACK: Linear Algebra PACKage
Loading...
Searching...
No Matches
slarrd.f
Go to the documentation of this file.
1*> \brief \b SLARRD computes the eigenvalues of a symmetric tridiagonal matrix to suitable accuracy.
2*
3* =========== DOCUMENTATION ===========
4*
5* Online html documentation available at
6* http://www.netlib.org/lapack/explore-html/
7*
8*> Download SLARRD + dependencies
9*> <a href="http://www.netlib.org/cgi-bin/netlibfiles.tgz?format=tgz&filename=/lapack/lapack_routine/slarrd.f">
10*> [TGZ]</a>
11*> <a href="http://www.netlib.org/cgi-bin/netlibfiles.zip?format=zip&filename=/lapack/lapack_routine/slarrd.f">
12*> [ZIP]</a>
13*> <a href="http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/slarrd.f">
14*> [TXT]</a>
15*
16* Definition:
17* ===========
18*
19* SUBROUTINE SLARRD( RANGE, ORDER, N, VL, VU, IL, IU, GERS,
20* RELTOL, D, E, E2, PIVMIN, NSPLIT, ISPLIT,
21* M, W, WERR, WL, WU, IBLOCK, INDEXW,
22* WORK, IWORK, INFO )
23*
24* .. Scalar Arguments ..
25* CHARACTER ORDER, RANGE
26* INTEGER IL, INFO, IU, M, N, NSPLIT
27* REAL PIVMIN, RELTOL, VL, VU, WL, WU
28* ..
29* .. Array Arguments ..
30* INTEGER IBLOCK( * ), INDEXW( * ),
31* $ ISPLIT( * ), IWORK( * )
32* REAL D( * ), E( * ), E2( * ),
33* $ GERS( * ), W( * ), WERR( * ), WORK( * )
34* ..
35*
36*
37*> \par Purpose:
38* =============
39*>
40*> \verbatim
41*>
42*> SLARRD computes the eigenvalues of a symmetric tridiagonal
43*> matrix T to suitable accuracy. This is an auxiliary code to be
44*> called from SSTEMR.
45*> The user may ask for all eigenvalues, all eigenvalues
46*> in the half-open interval (VL, VU], or the IL-th through IU-th
47*> eigenvalues.
48*>
49*> To avoid overflow, the matrix must be scaled so that its
50*> largest element is no greater than overflow**(1/2) * underflow**(1/4) in absolute value, and for greatest
51*> accuracy, it should not be much smaller than that.
52*>
53*> See W. Kahan "Accurate Eigenvalues of a Symmetric Tridiagonal
54*> Matrix", Report CS41, Computer Science Dept., Stanford
55*> University, July 21, 1966.
56*> \endverbatim
57*
58* Arguments:
59* ==========
60*
61*> \param[in] RANGE
62*> \verbatim
63*> RANGE is CHARACTER*1
64*> = 'A': ("All") all eigenvalues will be found.
65*> = 'V': ("Value") all eigenvalues in the half-open interval
66*> (VL, VU] will be found.
67*> = 'I': ("Index") the IL-th through IU-th eigenvalues (of the
68*> entire matrix) will be found.
69*> \endverbatim
70*>
71*> \param[in] ORDER
72*> \verbatim
73*> ORDER is CHARACTER*1
74*> = 'B': ("By Block") the eigenvalues will be grouped by
75*> split-off block (see IBLOCK, ISPLIT) and
76*> ordered from smallest to largest within
77*> the block.
78*> = 'E': ("Entire matrix")
79*> the eigenvalues for the entire matrix
80*> will be ordered from smallest to
81*> largest.
82*> \endverbatim
83*>
84*> \param[in] N
85*> \verbatim
86*> N is INTEGER
87*> The order of the tridiagonal matrix T. N >= 0.
88*> \endverbatim
89*>
90*> \param[in] VL
91*> \verbatim
92*> VL is REAL
93*> If RANGE='V', the lower bound of the interval to
94*> be searched for eigenvalues. Eigenvalues less than or equal
95*> to VL, or greater than VU, will not be returned. VL < VU.
96*> Not referenced if RANGE = 'A' or 'I'.
97*> \endverbatim
98*>
99*> \param[in] VU
100*> \verbatim
101*> VU is REAL
102*> If RANGE='V', the upper bound of the interval to
103*> be searched for eigenvalues. Eigenvalues less than or equal
104*> to VL, or greater than VU, will not be returned. VL < VU.
105*> Not referenced if RANGE = 'A' or 'I'.
106*> \endverbatim
107*>
108*> \param[in] IL
109*> \verbatim
110*> IL is INTEGER
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'.
115*> \endverbatim
116*>
117*> \param[in] IU
118*> \verbatim
119*> IU is INTEGER
120*> If RANGE='I', the index of the
121*> largest eigenvalue to be returned.
122*> 1 <= IL <= IU <= N, if N > 0; IL = 1 and IU = 0 if N = 0.
123*> Not referenced if RANGE = 'A' or 'V'.
124*> \endverbatim
125*>
126*> \param[in] GERS
127*> \verbatim
128*> GERS is REAL array, dimension (2*N)
129*> The N Gerschgorin intervals (the i-th Gerschgorin interval
130*> is (GERS(2*i-1), GERS(2*i)).
131*> \endverbatim
132*>
133*> \param[in] RELTOL
134*> \verbatim
135*> RELTOL is REAL
136*> The minimum relative width of an interval. When an interval
137*> is narrower than RELTOL times the larger (in
138*> magnitude) endpoint, then it is considered to be
139*> sufficiently small, i.e., converged. Note: this should
140*> always be at least radix*machine epsilon.
141*> \endverbatim
142*>
143*> \param[in] D
144*> \verbatim
145*> D is REAL array, dimension (N)
146*> The n diagonal elements of the tridiagonal matrix T.
147*> \endverbatim
148*>
149*> \param[in] E
150*> \verbatim
151*> E is REAL array, dimension (N-1)
152*> The (n-1) off-diagonal elements of the tridiagonal matrix T.
153*> \endverbatim
154*>
155*> \param[in] E2
156*> \verbatim
157*> E2 is REAL array, dimension (N-1)
158*> The (n-1) squared off-diagonal elements of the tridiagonal matrix T.
159*> \endverbatim
160*>
161*> \param[in] PIVMIN
162*> \verbatim
163*> PIVMIN is REAL
164*> The minimum pivot allowed in the Sturm sequence for T.
165*> \endverbatim
166*>
167*> \param[in] NSPLIT
168*> \verbatim
169*> NSPLIT is INTEGER
170*> The number of diagonal blocks in the matrix T.
171*> 1 <= NSPLIT <= N.
172*> \endverbatim
173*>
174*> \param[in] ISPLIT
175*> \verbatim
176*> ISPLIT is INTEGER array, dimension (N)
177*> The splitting points, at which T breaks up into submatrices.
178*> The first submatrix consists of rows/columns 1 to ISPLIT(1),
179*> the second of rows/columns ISPLIT(1)+1 through ISPLIT(2),
180*> etc., and the NSPLIT-th consists of rows/columns
181*> ISPLIT(NSPLIT-1)+1 through ISPLIT(NSPLIT)=N.
182*> (Only the first NSPLIT elements will actually be used, but
183*> since the user cannot know a priori what value NSPLIT will
184*> have, N words must be reserved for ISPLIT.)
185*> \endverbatim
186*>
187*> \param[out] M
188*> \verbatim
189*> M is INTEGER
190*> The actual number of eigenvalues found. 0 <= M <= N.
191*> (See also the description of INFO=2,3.)
192*> \endverbatim
193*>
194*> \param[out] W
195*> \verbatim
196*> W is REAL array, dimension (N)
197*> On exit, the first M elements of W will contain the
198*> eigenvalue approximations. SLARRD computes an interval
199*> I_j = (a_j, b_j] that includes eigenvalue j. The eigenvalue
200*> approximation is given as the interval midpoint
201*> W(j)= ( a_j + b_j)/2. The corresponding error is bounded by
202*> WERR(j) = abs( a_j - b_j)/2
203*> \endverbatim
204*>
205*> \param[out] WERR
206*> \verbatim
207*> WERR is REAL array, dimension (N)
208*> The error bound on the corresponding eigenvalue approximation
209*> in W.
210*> \endverbatim
211*>
212*> \param[out] WL
213*> \verbatim
214*> WL is REAL
215*> \endverbatim
216*>
217*> \param[out] WU
218*> \verbatim
219*> WU is REAL
220*> The interval (WL, WU] contains all the wanted eigenvalues.
221*> If RANGE='V', then WL=VL and WU=VU.
222*> If RANGE='A', then WL and WU are the global Gerschgorin bounds
223*> on the spectrum.
224*> If RANGE='I', then WL and WU are computed by SLAEBZ from the
225*> index range specified.
226*> \endverbatim
227*>
228*> \param[out] IBLOCK
229*> \verbatim
230*> IBLOCK is INTEGER array, dimension (N)
231*> At each row/column j where E(j) is zero or small, the
232*> matrix T is considered to split into a block diagonal
233*> matrix. On exit, if INFO = 0, IBLOCK(i) specifies to which
234*> block (from 1 to the number of blocks) the eigenvalue W(i)
235*> belongs. (SLARRD may use the remaining N-M elements as
236*> workspace.)
237*> \endverbatim
238*>
239*> \param[out] INDEXW
240*> \verbatim
241*> INDEXW is INTEGER array, dimension (N)
242*> The indices of the eigenvalues within each block (submatrix);
243*> for example, INDEXW(i)= j and IBLOCK(i)=k imply that the
244*> i-th eigenvalue W(i) is the j-th eigenvalue in block k.
245*> \endverbatim
246*>
247*> \param[out] WORK
248*> \verbatim
249*> WORK is REAL array, dimension (4*N)
250*> \endverbatim
251*>
252*> \param[out] IWORK
253*> \verbatim
254*> IWORK is INTEGER array, dimension (3*N)
255*> \endverbatim
256*>
257*> \param[out] INFO
258*> \verbatim
259*> INFO is INTEGER
260*> = 0: successful exit
261*> < 0: if INFO = -i, the i-th argument had an illegal value
262*> > 0: some or all of the eigenvalues failed to converge or
263*> were not computed:
264*> =1 or 3: Bisection failed to converge for some
265*> eigenvalues; these eigenvalues are flagged by a
266*> negative block number. The effect is that the
267*> eigenvalues may not be as accurate as the
268*> absolute and relative tolerances. This is
269*> generally caused by unexpectedly inaccurate
270*> arithmetic.
271*> =2 or 3: RANGE='I' only: Not all of the eigenvalues
272*> IL:IU were found.
273*> Effect: M < IU+1-IL
274*> Cause: non-monotonic arithmetic, causing the
275*> Sturm sequence to be non-monotonic.
276*> Cure: recalculate, using RANGE='A', and pick
277*> out eigenvalues IL:IU. In some cases,
278*> increasing the PARAMETER "FUDGE" may
279*> make things work.
280*> = 4: RANGE='I', and the Gershgorin interval
281*> initially used was too small. No eigenvalues
282*> were computed.
283*> Probable cause: your machine has sloppy
284*> floating-point arithmetic.
285*> Cure: Increase the PARAMETER "FUDGE",
286*> recompile, and try again.
287*> \endverbatim
288*
289*> \par Internal Parameters:
290* =========================
291*>
292*> \verbatim
293*> FUDGE REAL, default = 2
294*> A "fudge factor" to widen the Gershgorin intervals. Ideally,
295*> a value of 1 should work, but on machines with sloppy
296*> arithmetic, this needs to be larger. The default for
297*> publicly released versions should be large enough to handle
298*> the worst machine around. Note that this has no effect
299*> on accuracy of the solution.
300*> \endverbatim
301*>
302*> \par Contributors:
303* ==================
304*>
305*> W. Kahan, University of California, Berkeley, USA \n
306*> Beresford Parlett, University of California, Berkeley, USA \n
307*> Jim Demmel, University of California, Berkeley, USA \n
308*> Inderjit Dhillon, University of Texas, Austin, USA \n
309*> Osni Marques, LBNL/NERSC, USA \n
310*> Christof Voemel, University of California, Berkeley, USA \n
311*
312* Authors:
313* ========
314*
315*> \author Univ. of Tennessee
316*> \author Univ. of California Berkeley
317*> \author Univ. of Colorado Denver
318*> \author NAG Ltd.
319*
320*> \ingroup larrd
321*
322* =====================================================================
323 SUBROUTINE slarrd( RANGE, ORDER, N, VL, VU, IL, IU, GERS,
324 $ RELTOL, D, E, E2, PIVMIN, NSPLIT, ISPLIT,
325 $ M, W, WERR, WL, WU, IBLOCK, INDEXW,
326 $ WORK, IWORK, INFO )
327*
328* -- LAPACK auxiliary routine --
329* -- LAPACK is a software package provided by Univ. of Tennessee, --
330* -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..--
331*
332* .. Scalar Arguments ..
333 CHARACTER ORDER, RANGE
334 INTEGER IL, INFO, IU, M, N, NSPLIT
335 REAL PIVMIN, RELTOL, VL, VU, WL, WU
336* ..
337* .. Array Arguments ..
338 INTEGER IBLOCK( * ), INDEXW( * ),
339 $ ISPLIT( * ), IWORK( * )
340 REAL D( * ), E( * ), E2( * ),
341 $ gers( * ), w( * ), werr( * ), work( * )
342* ..
343*
344* =====================================================================
345*
346* .. Parameters ..
347 REAL ZERO, ONE, TWO, HALF, FUDGE
348 PARAMETER ( ZERO = 0.0e0, one = 1.0e0,
349 $ two = 2.0e0, half = one/two,
350 $ fudge = two )
351 INTEGER ALLRNG, VALRNG, INDRNG
352 PARAMETER ( ALLRNG = 1, valrng = 2, indrng = 3 )
353* ..
354* .. Local Scalars ..
355 LOGICAL NCNVRG, TOOFEW
356 INTEGER I, IB, IBEGIN, IDISCL, IDISCU, IE, IEND, IINFO,
357 $ IM, IN, IOFF, IOUT, IRANGE, ITMAX, ITMP1,
358 $ itmp2, iw, iwoff, j, jblk, jdisc, je, jee, nb,
359 $ nwl, nwu
360 REAL ATOLI, EPS, GL, GU, RTOLI, TMP1, TMP2,
361 $ TNORM, UFLOW, WKILL, WLU, WUL
362
363* ..
364* .. Local Arrays ..
365 INTEGER IDUMMA( 1 )
366* ..
367* .. External Functions ..
368 LOGICAL LSAME
369 INTEGER ILAENV
370 REAL SLAMCH
371 EXTERNAL lsame, ilaenv, slamch
372* ..
373* .. External Subroutines ..
374 EXTERNAL slaebz
375* ..
376* .. Intrinsic Functions ..
377 INTRINSIC abs, int, log, max, min
378* ..
379* .. Executable Statements ..
380*
381 info = 0
382 m = 0
383*
384* Quick return if possible
385*
386 IF( n.LE.0 ) THEN
387 RETURN
388 END IF
389*
390* Decode RANGE
391*
392 IF( lsame( range, 'A' ) ) THEN
393 irange = allrng
394 ELSE IF( lsame( range, 'V' ) ) THEN
395 irange = valrng
396 ELSE IF( lsame( range, 'I' ) ) THEN
397 irange = indrng
398 ELSE
399 irange = 0
400 END IF
401*
402* Check for Errors
403*
404 IF( irange.LE.0 ) THEN
405 info = -1
406 ELSE IF( .NOT.(lsame(order,'B').OR.lsame(order,'E')) ) THEN
407 info = -2
408 ELSE IF( n.LT.0 ) THEN
409 info = -3
410 ELSE IF( irange.EQ.valrng ) THEN
411 IF( vl.GE.vu )
412 $ info = -5
413 ELSE IF( irange.EQ.indrng .AND.
414 $ ( il.LT.1 .OR. il.GT.max( 1, n ) ) ) THEN
415 info = -6
416 ELSE IF( irange.EQ.indrng .AND.
417 $ ( iu.LT.min( n, il ) .OR. iu.GT.n ) ) THEN
418 info = -7
419 END IF
420*
421 IF( info.NE.0 ) THEN
422 RETURN
423 END IF
424
425* Initialize error flags
426 ncnvrg = .false.
427 toofew = .false.
428
429* Simplification:
430 IF( irange.EQ.indrng .AND. il.EQ.1 .AND. iu.EQ.n ) irange = 1
431
432* Get machine constants
433 eps = slamch( 'P' )
434 uflow = slamch( 'U' )
435
436
437* Special Case when N=1
438* Treat case of 1x1 matrix for quick return
439 IF( n.EQ.1 ) THEN
440 IF( (irange.EQ.allrng).OR.
441 $ ((irange.EQ.valrng).AND.(d(1).GT.vl).AND.(d(1).LE.vu)).OR.
442 $ ((irange.EQ.indrng).AND.(il.EQ.1).AND.(iu.EQ.1)) ) THEN
443 m = 1
444 w(1) = d(1)
445* The computation error of the eigenvalue is zero
446 werr(1) = zero
447 iblock( 1 ) = 1
448 indexw( 1 ) = 1
449 ENDIF
450 RETURN
451 END IF
452
453* NB is the minimum vector length for vector bisection, or 0
454* if only scalar is to be done.
455 nb = ilaenv( 1, 'SSTEBZ', ' ', n, -1, -1, -1 )
456 IF( nb.LE.1 ) nb = 0
457
458* Find global spectral radius
459 gl = d(1)
460 gu = d(1)
461 DO 5 i = 1,n
462 gl = min( gl, gers( 2*i - 1))
463 gu = max( gu, gers(2*i) )
464 5 CONTINUE
465* Compute global Gerschgorin bounds and spectral diameter
466 tnorm = max( abs( gl ), abs( gu ) )
467 gl = gl - fudge*tnorm*eps*real( n ) - fudge*two*pivmin
468 gu = gu + fudge*tnorm*eps*real( n ) + fudge*two*pivmin
469* [JAN/28/2009] remove the line below since SPDIAM variable not use
470* SPDIAM = GU - GL
471* Input arguments for SLAEBZ:
472* The relative tolerance. An interval (a,b] lies within
473* "relative tolerance" if b-a < RELTOL*max(|a|,|b|),
474 rtoli = reltol
475* Set the absolute tolerance for interval convergence to zero to force
476* interval convergence based on relative size of the interval.
477* This is dangerous because intervals might not converge when RELTOL is
478* small. But at least a very small number should be selected so that for
479* strongly graded matrices, the code can get relatively accurate
480* eigenvalues.
481 atoli = fudge*two*uflow + fudge*two*pivmin
482
483 IF( irange.EQ.indrng ) THEN
484
485* RANGE='I': Compute an interval containing eigenvalues
486* IL through IU. The initial interval [GL,GU] from the global
487* Gerschgorin bounds GL and GU is refined by SLAEBZ.
488 itmax = int( ( log( tnorm+pivmin )-log( pivmin ) ) /
489 $ log( two ) ) + 2
490 work( n+1 ) = gl
491 work( n+2 ) = gl
492 work( n+3 ) = gu
493 work( n+4 ) = gu
494 work( n+5 ) = gl
495 work( n+6 ) = gu
496 iwork( 1 ) = -1
497 iwork( 2 ) = -1
498 iwork( 3 ) = n + 1
499 iwork( 4 ) = n + 1
500 iwork( 5 ) = il - 1
501 iwork( 6 ) = iu
502*
503 CALL slaebz( 3, itmax, n, 2, 2, nb, atoli, rtoli, pivmin,
504 $ d, e, e2, iwork( 5 ), work( n+1 ), work( n+5 ), iout,
505 $ iwork, w, iblock, iinfo )
506 IF( iinfo .NE. 0 ) THEN
507 info = iinfo
508 RETURN
509 END IF
510* On exit, output intervals may not be ordered by ascending negcount
511 IF( iwork( 6 ).EQ.iu ) THEN
512 wl = work( n+1 )
513 wlu = work( n+3 )
514 nwl = iwork( 1 )
515 wu = work( n+4 )
516 wul = work( n+2 )
517 nwu = iwork( 4 )
518 ELSE
519 wl = work( n+2 )
520 wlu = work( n+4 )
521 nwl = iwork( 2 )
522 wu = work( n+3 )
523 wul = work( n+1 )
524 nwu = iwork( 3 )
525 END IF
526* On exit, the interval [WL, WLU] contains a value with negcount NWL,
527* and [WUL, WU] contains a value with negcount NWU.
528 IF( nwl.LT.0 .OR. nwl.GE.n .OR. nwu.LT.1 .OR. nwu.GT.n ) THEN
529 info = 4
530 RETURN
531 END IF
532
533 ELSEIF( irange.EQ.valrng ) THEN
534 wl = vl
535 wu = vu
536
537 ELSEIF( irange.EQ.allrng ) THEN
538 wl = gl
539 wu = gu
540 ENDIF
541
542
543
544* Find Eigenvalues -- Loop Over blocks and recompute NWL and NWU.
545* NWL accumulates the number of eigenvalues .le. WL,
546* NWU accumulates the number of eigenvalues .le. WU
547 m = 0
548 iend = 0
549 info = 0
550 nwl = 0
551 nwu = 0
552*
553 DO 70 jblk = 1, nsplit
554 ioff = iend
555 ibegin = ioff + 1
556 iend = isplit( jblk )
557 in = iend - ioff
558*
559 IF( in.EQ.1 ) THEN
560* 1x1 block
561 IF( wl.GE.d( ibegin )-pivmin )
562 $ nwl = nwl + 1
563 IF( wu.GE.d( ibegin )-pivmin )
564 $ nwu = nwu + 1
565 IF( irange.EQ.allrng .OR.
566 $ ( wl.LT.d( ibegin )-pivmin
567 $ .AND. wu.GE. d( ibegin )-pivmin ) ) THEN
568 m = m + 1
569 w( m ) = d( ibegin )
570 werr(m) = zero
571* The gap for a single block doesn't matter for the later
572* algorithm and is assigned an arbitrary large value
573 iblock( m ) = jblk
574 indexw( m ) = 1
575 END IF
576
577* Disabled 2x2 case because of a failure on the following matrix
578* RANGE = 'I', IL = IU = 4
579* Original Tridiagonal, d = [
580* -0.150102010615740E+00
581* -0.849897989384260E+00
582* -0.128208148052635E-15
583* 0.128257718286320E-15
584* ];
585* e = [
586* -0.357171383266986E+00
587* -0.180411241501588E-15
588* -0.175152352710251E-15
589* ];
590*
591* ELSE IF( IN.EQ.2 ) THEN
592** 2x2 block
593* DISC = SQRT( (HALF*(D(IBEGIN)-D(IEND)))**2 + E(IBEGIN)**2 )
594* TMP1 = HALF*(D(IBEGIN)+D(IEND))
595* L1 = TMP1 - DISC
596* IF( WL.GE. L1-PIVMIN )
597* $ NWL = NWL + 1
598* IF( WU.GE. L1-PIVMIN )
599* $ NWU = NWU + 1
600* IF( IRANGE.EQ.ALLRNG .OR. ( WL.LT.L1-PIVMIN .AND. WU.GE.
601* $ L1-PIVMIN ) ) THEN
602* M = M + 1
603* W( M ) = L1
604** The uncertainty of eigenvalues of a 2x2 matrix is very small
605* WERR( M ) = EPS * ABS( W( M ) ) * TWO
606* IBLOCK( M ) = JBLK
607* INDEXW( M ) = 1
608* ENDIF
609* L2 = TMP1 + DISC
610* IF( WL.GE. L2-PIVMIN )
611* $ NWL = NWL + 1
612* IF( WU.GE. L2-PIVMIN )
613* $ NWU = NWU + 1
614* IF( IRANGE.EQ.ALLRNG .OR. ( WL.LT.L2-PIVMIN .AND. WU.GE.
615* $ L2-PIVMIN ) ) THEN
616* M = M + 1
617* W( M ) = L2
618** The uncertainty of eigenvalues of a 2x2 matrix is very small
619* WERR( M ) = EPS * ABS( W( M ) ) * TWO
620* IBLOCK( M ) = JBLK
621* INDEXW( M ) = 2
622* ENDIF
623 ELSE
624* General Case - block of size IN >= 2
625* Compute local Gerschgorin interval and use it as the initial
626* interval for SLAEBZ
627 gu = d( ibegin )
628 gl = d( ibegin )
629 tmp1 = zero
630
631 DO 40 j = ibegin, iend
632 gl = min( gl, gers( 2*j - 1))
633 gu = max( gu, gers(2*j) )
634 40 CONTINUE
635* [JAN/28/2009]
636* change SPDIAM by TNORM in lines 2 and 3 thereafter
637* line 1: remove computation of SPDIAM (not useful anymore)
638* SPDIAM = GU - GL
639* GL = GL - FUDGE*SPDIAM*EPS*IN - FUDGE*PIVMIN
640* GU = GU + FUDGE*SPDIAM*EPS*IN + FUDGE*PIVMIN
641 gl = gl - fudge*tnorm*eps*real( in ) - fudge*pivmin
642 gu = gu + fudge*tnorm*eps*real( in ) + fudge*pivmin
643*
644 IF( irange.GT.1 ) THEN
645 IF( gu.LT.wl ) THEN
646* the local block contains none of the wanted eigenvalues
647 nwl = nwl + in
648 nwu = nwu + in
649 GO TO 70
650 END IF
651* refine search interval if possible, only range (WL,WU] matters
652 gl = max( gl, wl )
653 gu = min( gu, wu )
654 IF( gl.GE.gu )
655 $ GO TO 70
656 END IF
657
658* Find negcount of initial interval boundaries GL and GU
659 work( n+1 ) = gl
660 work( n+in+1 ) = gu
661 CALL slaebz( 1, 0, in, in, 1, nb, atoli, rtoli, pivmin,
662 $ d( ibegin ), e( ibegin ), e2( ibegin ),
663 $ idumma, work( n+1 ), work( n+2*in+1 ), im,
664 $ iwork, w( m+1 ), iblock( m+1 ), iinfo )
665 IF( iinfo .NE. 0 ) THEN
666 info = iinfo
667 RETURN
668 END IF
669*
670 nwl = nwl + iwork( 1 )
671 nwu = nwu + iwork( in+1 )
672 iwoff = m - iwork( 1 )
673
674* Compute Eigenvalues
675 itmax = int( ( log( gu-gl+pivmin )-log( pivmin ) ) /
676 $ log( two ) ) + 2
677 CALL slaebz( 2, itmax, in, in, 1, nb, atoli, rtoli,
678 $ pivmin,
679 $ d( ibegin ), e( ibegin ), e2( ibegin ),
680 $ idumma, work( n+1 ), work( n+2*in+1 ), iout,
681 $ iwork, w( m+1 ), iblock( m+1 ), iinfo )
682 IF( iinfo .NE. 0 ) THEN
683 info = iinfo
684 RETURN
685 END IF
686*
687* Copy eigenvalues into W and IBLOCK
688* Use -JBLK for block number for unconverged eigenvalues.
689* Loop over the number of output intervals from SLAEBZ
690 DO 60 j = 1, iout
691* eigenvalue approximation is middle point of interval
692 tmp1 = half*( work( j+n )+work( j+in+n ) )
693* semi length of error interval
694 tmp2 = half*abs( work( j+n )-work( j+in+n ) )
695 IF( j.GT.iout-iinfo ) THEN
696* Flag non-convergence.
697 ncnvrg = .true.
698 ib = -jblk
699 ELSE
700 ib = jblk
701 END IF
702 DO 50 je = iwork( j ) + 1 + iwoff,
703 $ iwork( j+in ) + iwoff
704 w( je ) = tmp1
705 werr( je ) = tmp2
706 indexw( je ) = je - iwoff
707 iblock( je ) = ib
708 50 CONTINUE
709 60 CONTINUE
710*
711 m = m + im
712 END IF
713 70 CONTINUE
714
715* If RANGE='I', then (WL,WU) contains eigenvalues NWL+1,...,NWU
716* If NWL+1 < IL or NWU > IU, discard extra eigenvalues.
717 IF( irange.EQ.indrng ) THEN
718 idiscl = il - 1 - nwl
719 idiscu = nwu - iu
720*
721 IF( idiscl.GT.0 ) THEN
722 im = 0
723 DO 80 je = 1, m
724* Remove some of the smallest eigenvalues from the left so that
725* at the end IDISCL =0. Move all eigenvalues up to the left.
726 IF( w( je ).LE.wlu .AND. idiscl.GT.0 ) THEN
727 idiscl = idiscl - 1
728 ELSE
729 im = im + 1
730 w( im ) = w( je )
731 werr( im ) = werr( je )
732 indexw( im ) = indexw( je )
733 iblock( im ) = iblock( je )
734 END IF
735 80 CONTINUE
736 m = im
737 END IF
738 IF( idiscu.GT.0 ) THEN
739* Remove some of the largest eigenvalues from the right so that
740* at the end IDISCU =0. Move all eigenvalues up to the left.
741 im=m+1
742 DO 81 je = m, 1, -1
743 IF( w( je ).GE.wul .AND. idiscu.GT.0 ) THEN
744 idiscu = idiscu - 1
745 ELSE
746 im = im - 1
747 w( im ) = w( je )
748 werr( im ) = werr( je )
749 indexw( im ) = indexw( je )
750 iblock( im ) = iblock( je )
751 END IF
752 81 CONTINUE
753 jee = 0
754 DO 82 je = im, m
755 jee = jee + 1
756 w( jee ) = w( je )
757 werr( jee ) = werr( je )
758 indexw( jee ) = indexw( je )
759 iblock( jee ) = iblock( je )
760 82 CONTINUE
761 m = m-im+1
762 END IF
763
764 IF( idiscl.GT.0 .OR. idiscu.GT.0 ) THEN
765* Code to deal with effects of bad arithmetic. (If N(w) is
766* monotone non-decreasing, this should never happen.)
767* Some low eigenvalues to be discarded are not in (WL,WLU],
768* or high eigenvalues to be discarded are not in (WUL,WU]
769* so just kill off the smallest IDISCL/largest IDISCU
770* eigenvalues, by marking the corresponding IBLOCK = 0
771 IF( idiscl.GT.0 ) THEN
772 wkill = wu
773 DO 100 jdisc = 1, idiscl
774 iw = 0
775 DO 90 je = 1, m
776 IF( iblock( je ).NE.0 .AND.
777 $ ( w( je ).LT.wkill .OR. iw.EQ.0 ) ) THEN
778 iw = je
779 wkill = w( je )
780 END IF
781 90 CONTINUE
782 iblock( iw ) = 0
783 100 CONTINUE
784 END IF
785 IF( idiscu.GT.0 ) THEN
786 wkill = wl
787 DO 120 jdisc = 1, idiscu
788 iw = 0
789 DO 110 je = 1, m
790 IF( iblock( je ).NE.0 .AND.
791 $ ( w( je ).GE.wkill .OR. iw.EQ.0 ) ) THEN
792 iw = je
793 wkill = w( je )
794 END IF
795 110 CONTINUE
796 iblock( iw ) = 0
797 120 CONTINUE
798 END IF
799* Now erase all eigenvalues with IBLOCK set to zero
800 im = 0
801 DO 130 je = 1, m
802 IF( iblock( je ).NE.0 ) THEN
803 im = im + 1
804 w( im ) = w( je )
805 werr( im ) = werr( je )
806 indexw( im ) = indexw( je )
807 iblock( im ) = iblock( je )
808 END IF
809 130 CONTINUE
810 m = im
811 END IF
812 IF( idiscl.LT.0 .OR. idiscu.LT.0 ) THEN
813 toofew = .true.
814 END IF
815 END IF
816*
817 IF(( irange.EQ.allrng .AND. m.NE.n ).OR.
818 $ ( irange.EQ.indrng .AND. m.NE.iu-il+1 ) ) THEN
819 toofew = .true.
820 END IF
821
822* If ORDER='B', do nothing the eigenvalues are already sorted by
823* block.
824* If ORDER='E', sort the eigenvalues from smallest to largest
825
826 IF( lsame(order,'E') .AND. nsplit.GT.1 ) THEN
827 DO 150 je = 1, m - 1
828 ie = 0
829 tmp1 = w( je )
830 DO 140 j = je + 1, m
831 IF( w( j ).LT.tmp1 ) THEN
832 ie = j
833 tmp1 = w( j )
834 END IF
835 140 CONTINUE
836 IF( ie.NE.0 ) THEN
837 tmp2 = werr( ie )
838 itmp1 = iblock( ie )
839 itmp2 = indexw( ie )
840 w( ie ) = w( je )
841 werr( ie ) = werr( je )
842 iblock( ie ) = iblock( je )
843 indexw( ie ) = indexw( je )
844 w( je ) = tmp1
845 werr( je ) = tmp2
846 iblock( je ) = itmp1
847 indexw( je ) = itmp2
848 END IF
849 150 CONTINUE
850 END IF
851*
852 info = 0
853 IF( ncnvrg )
854 $ info = info + 1
855 IF( toofew )
856 $ info = info + 2
857 RETURN
858*
859* End of SLARRD
860*
861 END
subroutine slaebz(ijob, nitmax, n, mmax, minp, nbmin, abstol, reltol, pivmin, d, e, e2, nval, ab, c, mout, nab, work, iwork, info)
SLAEBZ computes the number of eigenvalues of a real symmetric tridiagonal matrix which are less than ...
Definition slaebz.f:317
subroutine slarrd(range, order, n, vl, vu, il, iu, gers, reltol, d, e, e2, pivmin, nsplit, isplit, m, w, werr, wl, wu, iblock, indexw, work, iwork, info)
SLARRD computes the eigenvalues of a symmetric tridiagonal matrix to suitable accuracy.
Definition slarrd.f:327