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