1*> \brief \b DLARRE given the tridiagonal matrix T, sets small off-diagonal elements to zero and for each unreduced block Ti, finds base representations and eigenvalues.
2*
3*  =========== DOCUMENTATION ===========
4*
5* Online html documentation available at
6*            http://www.netlib.org/lapack/explore-html/
7*
8*> \htmlonly
9*> Download DLARRE + dependencies
10*> <a href="http://www.netlib.org/cgi-bin/netlibfiles.tgz?format=tgz&filename=/lapack/lapack_routine/dlarre.f">
11*> [TGZ]</a>
12*> <a href="http://www.netlib.org/cgi-bin/netlibfiles.zip?format=zip&filename=/lapack/lapack_routine/dlarre.f">
13*> [ZIP]</a>
14*> <a href="http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/dlarre.f">
15*> [TXT]</a>
16*> \endhtmlonly
17*
18*  Definition:
19*  ===========
20*
21*       SUBROUTINE DLARRE( RANGE, N, VL, VU, IL, IU, D, E, E2,
22*                           RTOL1, RTOL2, SPLTOL, NSPLIT, ISPLIT, M,
23*                           W, WERR, WGAP, IBLOCK, INDEXW, GERS, PIVMIN,
24*                           WORK, IWORK, INFO )
25*
26*       .. Scalar Arguments ..
27*       CHARACTER          RANGE
28*       INTEGER            IL, INFO, IU, M, N, NSPLIT
29*       DOUBLE PRECISION  PIVMIN, RTOL1, RTOL2, SPLTOL, VL, VU
30*       ..
31*       .. Array Arguments ..
32*       INTEGER            IBLOCK( * ), ISPLIT( * ), IWORK( * ),
33*      $                   INDEXW( * )
34*       DOUBLE PRECISION   D( * ), E( * ), E2( * ), GERS( * ),
35*      $                   W( * ),WERR( * ), WGAP( * ), WORK( * )
36*       ..
37*
38*
39*> \par Purpose:
40*  =============
41*>
42*> \verbatim
43*>
44*> To find the desired eigenvalues of a given real symmetric
45*> tridiagonal matrix T, DLARRE sets any "small" off-diagonal
46*> elements to zero, and for each unreduced block T_i, it finds
47*> (a) a suitable shift at one end of the block's spectrum,
48*> (b) the base representation, T_i - sigma_i I = L_i D_i L_i^T, and
49*> (c) eigenvalues of each L_i D_i L_i^T.
50*> The representations and eigenvalues found are then used by
51*> DSTEMR to compute the eigenvectors of T.
52*> The accuracy varies depending on whether bisection is used to
53*> find a few eigenvalues or the dqds algorithm (subroutine DLASQ2) to
54*> conpute all and then discard any unwanted one.
55*> As an added benefit, DLARRE also outputs the n
56*> Gerschgorin intervals for the matrices L_i D_i L_i^T.
57*> \endverbatim
58*
59*  Arguments:
60*  ==========
61*
62*> \param[in] RANGE
63*> \verbatim
64*>          RANGE is CHARACTER*1
65*>          = 'A': ("All")   all eigenvalues will be found.
66*>          = 'V': ("Value") all eigenvalues in the half-open interval
67*>                           (VL, VU] will be found.
68*>          = 'I': ("Index") the IL-th through IU-th eigenvalues (of the
69*>                           entire matrix) will be found.
70*> \endverbatim
71*>
72*> \param[in] N
73*> \verbatim
74*>          N is INTEGER
75*>          The order of the matrix. N > 0.
76*> \endverbatim
77*>
78*> \param[in,out] VL
79*> \verbatim
80*>          VL is DOUBLE PRECISION
81*>          If RANGE='V', the lower bound for the eigenvalues.
82*>          Eigenvalues less than or equal to VL, or greater than VU,
83*>          will not be returned.  VL < VU.
84*>          If RANGE='I' or ='A', DLARRE computes bounds on the desired
85*>          part of the spectrum.
86*> \endverbatim
87*>
88*> \param[in,out] VU
89*> \verbatim
90*>          VU is DOUBLE PRECISION
91*>          If RANGE='V', the upper bound for the eigenvalues.
92*>          Eigenvalues less than or equal to VL, or greater than VU,
93*>          will not be returned.  VL < VU.
94*>          If RANGE='I' or ='A', DLARRE computes bounds on the desired
95*>          part of the spectrum.
96*> \endverbatim
97*>
98*> \param[in] IL
99*> \verbatim
100*>          IL is INTEGER
101*>          If RANGE='I', the index of the
102*>          smallest eigenvalue to be returned.
103*>          1 <= IL <= IU <= N.
104*> \endverbatim
105*>
106*> \param[in] IU
107*> \verbatim
108*>          IU is INTEGER
109*>          If RANGE='I', the index of the
110*>          largest eigenvalue to be returned.
111*>          1 <= IL <= IU <= N.
112*> \endverbatim
113*>
114*> \param[in,out] D
115*> \verbatim
116*>          D is DOUBLE PRECISION array, dimension (N)
117*>          On entry, the N diagonal elements of the tridiagonal
118*>          matrix T.
119*>          On exit, the N diagonal elements of the diagonal
120*>          matrices D_i.
121*> \endverbatim
122*>
123*> \param[in,out] E
124*> \verbatim
125*>          E is DOUBLE PRECISION array, dimension (N)
126*>          On entry, the first (N-1) entries contain the subdiagonal
127*>          elements of the tridiagonal matrix T; E(N) need not be set.
128*>          On exit, E contains the subdiagonal elements of the unit
129*>          bidiagonal matrices L_i. The entries E( ISPLIT( I ) ),
130*>          1 <= I <= NSPLIT, contain the base points sigma_i on output.
131*> \endverbatim
132*>
133*> \param[in,out] E2
134*> \verbatim
135*>          E2 is DOUBLE PRECISION array, dimension (N)
136*>          On entry, the first (N-1) entries contain the SQUARES of the
137*>          subdiagonal elements of the tridiagonal matrix T;
138*>          E2(N) need not be set.
139*>          On exit, the entries E2( ISPLIT( I ) ),
140*>          1 <= I <= NSPLIT, have been set to zero
141*> \endverbatim
142*>
143*> \param[in] RTOL1
144*> \verbatim
145*>          RTOL1 is DOUBLE PRECISION
146*> \endverbatim
147*>
148*> \param[in] RTOL2
149*> \verbatim
150*>          RTOL2 is DOUBLE PRECISION
151*>           Parameters for bisection.
152*>           An interval [LEFT,RIGHT] has converged if
153*>           RIGHT-LEFT < MAX( RTOL1*GAP, RTOL2*MAX(|LEFT|,|RIGHT|) )
154*> \endverbatim
155*>
156*> \param[in] SPLTOL
157*> \verbatim
158*>          SPLTOL is DOUBLE PRECISION
159*>          The threshold for splitting.
160*> \endverbatim
161*>
162*> \param[out] NSPLIT
163*> \verbatim
164*>          NSPLIT is INTEGER
165*>          The number of blocks T splits into. 1 <= NSPLIT <= N.
166*> \endverbatim
167*>
168*> \param[out] ISPLIT
169*> \verbatim
170*>          ISPLIT is INTEGER array, dimension (N)
171*>          The splitting points, at which T breaks up into blocks.
172*>          The first block consists of rows/columns 1 to ISPLIT(1),
173*>          the second of rows/columns ISPLIT(1)+1 through ISPLIT(2),
174*>          etc., and the NSPLIT-th consists of rows/columns
175*>          ISPLIT(NSPLIT-1)+1 through ISPLIT(NSPLIT)=N.
176*> \endverbatim
177*>
178*> \param[out] M
179*> \verbatim
180*>          M is INTEGER
181*>          The total number of eigenvalues (of all L_i D_i L_i^T)
182*>          found.
183*> \endverbatim
184*>
185*> \param[out] W
186*> \verbatim
187*>          W is DOUBLE PRECISION array, dimension (N)
188*>          The first M elements contain the eigenvalues. The
189*>          eigenvalues of each of the blocks, L_i D_i L_i^T, are
190*>          sorted in ascending order ( DLARRE may use the
191*>          remaining N-M elements as workspace).
192*> \endverbatim
193*>
194*> \param[out] WERR
195*> \verbatim
196*>          WERR is DOUBLE PRECISION array, dimension (N)
197*>          The error bound on the corresponding eigenvalue in W.
198*> \endverbatim
199*>
200*> \param[out] WGAP
201*> \verbatim
202*>          WGAP is DOUBLE PRECISION array, dimension (N)
203*>          The separation from the right neighbor eigenvalue in W.
204*>          The gap is only with respect to the eigenvalues of the same block
205*>          as each block has its own representation tree.
206*>          Exception: at the right end of a block we store the left gap
207*> \endverbatim
208*>
209*> \param[out] IBLOCK
210*> \verbatim
211*>          IBLOCK is INTEGER array, dimension (N)
212*>          The indices of the blocks (submatrices) associated with the
213*>          corresponding eigenvalues in W; IBLOCK(i)=1 if eigenvalue
214*>          W(i) belongs to the first block from the top, =2 if W(i)
215*>          belongs to the second block, etc.
216*> \endverbatim
217*>
218*> \param[out] INDEXW
219*> \verbatim
220*>          INDEXW is INTEGER array, dimension (N)
221*>          The indices of the eigenvalues within each block (submatrix);
222*>          for example, INDEXW(i)= 10 and IBLOCK(i)=2 imply that the
223*>          i-th eigenvalue W(i) is the 10-th eigenvalue in block 2
224*> \endverbatim
225*>
226*> \param[out] GERS
227*> \verbatim
228*>          GERS is DOUBLE PRECISION array, dimension (2*N)
229*>          The N Gerschgorin intervals (the i-th Gerschgorin interval
230*>          is (GERS(2*i-1), GERS(2*i)).
231*> \endverbatim
232*>
233*> \param[out] PIVMIN
234*> \verbatim
235*>          PIVMIN is DOUBLE PRECISION
236*>          The minimum pivot in the Sturm sequence for T.
237*> \endverbatim
238*>
239*> \param[out] WORK
240*> \verbatim
241*>          WORK is DOUBLE PRECISION array, dimension (6*N)
242*>          Workspace.
243*> \endverbatim
244*>
245*> \param[out] IWORK
246*> \verbatim
247*>          IWORK is INTEGER array, dimension (5*N)
248*>          Workspace.
249*> \endverbatim
250*>
251*> \param[out] INFO
252*> \verbatim
253*>          INFO is INTEGER
254*>          = 0:  successful exit
255*>          > 0:  A problem occurred in DLARRE.
256*>          < 0:  One of the called subroutines signaled an internal problem.
257*>                Needs inspection of the corresponding parameter IINFO
258*>                for further information.
259*>
260*>          =-1:  Problem in DLARRD.
261*>          = 2:  No base representation could be found in MAXTRY iterations.
262*>                Increasing MAXTRY and recompilation might be a remedy.
263*>          =-3:  Problem in DLARRB when computing the refined root
264*>                representation for DLASQ2.
265*>          =-4:  Problem in DLARRB when preforming bisection on the
266*>                desired part of the spectrum.
267*>          =-5:  Problem in DLASQ2.
268*>          =-6:  Problem in DLASQ2.
269*> \endverbatim
270*
271*  Authors:
272*  ========
273*
274*> \author Univ. of Tennessee
275*> \author Univ. of California Berkeley
276*> \author Univ. of Colorado Denver
277*> \author NAG Ltd.
278*
279*> \ingroup OTHERauxiliary
280*
281*> \par Further Details:
282*  =====================
283*>
284*> \verbatim
285*>
286*>  The base representations are required to suffer very little
287*>  element growth and consequently define all their eigenvalues to
288*>  high relative accuracy.
289*> \endverbatim
290*
291*> \par Contributors:
292*  ==================
293*>
294*>     Beresford Parlett, University of California, Berkeley, USA \n
295*>     Jim Demmel, University of California, Berkeley, USA \n
296*>     Inderjit Dhillon, University of Texas, Austin, USA \n
297*>     Osni Marques, LBNL/NERSC, USA \n
298*>     Christof Voemel, University of California, Berkeley, USA \n
299*>
300*  =====================================================================
301      SUBROUTINE DLARRE( RANGE, N, VL, VU, IL, IU, D, E, E2,
302     $                    RTOL1, RTOL2, SPLTOL, NSPLIT, ISPLIT, M,
303     $                    W, WERR, WGAP, IBLOCK, INDEXW, GERS, PIVMIN,
304     $                    WORK, IWORK, INFO )
305*
306*  -- LAPACK auxiliary routine --
307*  -- LAPACK is a software package provided by Univ. of Tennessee,    --
308*  -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..--
309*
310*     .. Scalar Arguments ..
311      CHARACTER          RANGE
312      INTEGER            IL, INFO, IU, M, N, NSPLIT
313      DOUBLE PRECISION  PIVMIN, RTOL1, RTOL2, SPLTOL, VL, VU
314*     ..
315*     .. Array Arguments ..
316      INTEGER            IBLOCK( * ), ISPLIT( * ), IWORK( * ),
317     $                   INDEXW( * )
318      DOUBLE PRECISION   D( * ), E( * ), E2( * ), GERS( * ),
319     $                   W( * ),WERR( * ), WGAP( * ), WORK( * )
320*     ..
321*
322*  =====================================================================
323*
324*     .. Parameters ..
325      DOUBLE PRECISION   FAC, FOUR, FOURTH, FUDGE, HALF, HNDRD,
326     $                   MAXGROWTH, ONE, PERT, TWO, ZERO
327      PARAMETER          ( ZERO = 0.0D0, ONE = 1.0D0,
328     $                     TWO = 2.0D0, FOUR=4.0D0,
329     $                     HNDRD = 100.0D0,
330     $                     PERT = 8.0D0,
331     $                     HALF = ONE/TWO, FOURTH = ONE/FOUR, FAC= HALF,
332     $                     MAXGROWTH = 64.0D0, FUDGE = 2.0D0 )
333      INTEGER            MAXTRY, ALLRNG, INDRNG, VALRNG
334      PARAMETER          ( MAXTRY = 6, ALLRNG = 1, INDRNG = 2,
335     $                     VALRNG = 3 )
336*     ..
337*     .. Local Scalars ..
338      LOGICAL            FORCEB, NOREP, USEDQD
339      INTEGER            CNT, CNT1, CNT2, I, IBEGIN, IDUM, IEND, IINFO,
340     $                   IN, INDL, INDU, IRANGE, J, JBLK, MB, MM,
341     $                   WBEGIN, WEND
342      DOUBLE PRECISION   AVGAP, BSRTOL, CLWDTH, DMAX, DPIVOT, EABS,
343     $                   EMAX, EOLD, EPS, GL, GU, ISLEFT, ISRGHT, RTL,
344     $                   RTOL, S1, S2, SAFMIN, SGNDEF, SIGMA, SPDIAM,
345     $                   TAU, TMP, TMP1
346
347
348*     ..
349*     .. Local Arrays ..
350      INTEGER            ISEED( 4 )
351*     ..
352*     .. External Functions ..
353      LOGICAL            LSAME
354      DOUBLE PRECISION            DLAMCH
355      EXTERNAL           DLAMCH, LSAME
356
357*     ..
358*     .. External Subroutines ..
359      EXTERNAL           DCOPY, DLARNV, DLARRA, DLARRB, DLARRC, DLARRD,
360     $                   DLASQ2, DLARRK
361*     ..
362*     .. Intrinsic Functions ..
363      INTRINSIC          ABS, MAX, MIN
364
365*     ..
366*     .. Executable Statements ..
367*
368
369      INFO = 0
370*
371*     Quick return if possible
372*
373      IF( N.LE.0 ) THEN
374         RETURN
375      END IF
376*
377*     Decode RANGE
378*
379      IF( LSAME( RANGE, 'A' ) ) THEN
380         IRANGE = ALLRNG
381      ELSE IF( LSAME( RANGE, 'V' ) ) THEN
382         IRANGE = VALRNG
383      ELSE IF( LSAME( RANGE, 'I' ) ) THEN
384         IRANGE = INDRNG
385      END IF
386
387      M = 0
388
389*     Get machine constants
390      SAFMIN = DLAMCH( 'S' )
391      EPS = DLAMCH( 'P' )
392
393*     Set parameters
394      RTL = SQRT(EPS)
395      BSRTOL = SQRT(EPS)
396
397*     Treat case of 1x1 matrix for quick return
398      IF( N.EQ.1 ) THEN
399         IF( (IRANGE.EQ.ALLRNG).OR.
400     $       ((IRANGE.EQ.VALRNG).AND.(D(1).GT.VL).AND.(D(1).LE.VU)).OR.
401     $       ((IRANGE.EQ.INDRNG).AND.(IL.EQ.1).AND.(IU.EQ.1)) ) THEN
402            M = 1
403            W(1) = D(1)
404*           The computation error of the eigenvalue is zero
405            WERR(1) = ZERO
406            WGAP(1) = ZERO
407            IBLOCK( 1 ) = 1
408            INDEXW( 1 ) = 1
409            GERS(1) = D( 1 )
410            GERS(2) = D( 1 )
411         ENDIF
412*        store the shift for the initial RRR, which is zero in this case
413         E(1) = ZERO
414         RETURN
415      END IF
416
417*     General case: tridiagonal matrix of order > 1
418*
419*     Init WERR, WGAP. Compute Gerschgorin intervals and spectral diameter.
420*     Compute maximum off-diagonal entry and pivmin.
421      GL = D(1)
422      GU = D(1)
423      EOLD = ZERO
424      EMAX = ZERO
425      E(N) = ZERO
426      DO 5 I = 1,N
427         WERR(I) = ZERO
428         WGAP(I) = ZERO
429         EABS = ABS( E(I) )
430         IF( EABS .GE. EMAX ) THEN
431            EMAX = EABS
432         END IF
433         TMP1 = EABS + EOLD
434         GERS( 2*I-1) = D(I) - TMP1
435         GL =  MIN( GL, GERS( 2*I - 1))
436         GERS( 2*I ) = D(I) + TMP1
437         GU = MAX( GU, GERS(2*I) )
438         EOLD  = EABS
439 5    CONTINUE
440*     The minimum pivot allowed in the Sturm sequence for T
441      PIVMIN = SAFMIN * MAX( ONE, EMAX**2 )
442*     Compute spectral diameter. The Gerschgorin bounds give an
443*     estimate that is wrong by at most a factor of SQRT(2)
444      SPDIAM = GU - GL
445
446*     Compute splitting points
447      CALL DLARRA( N, D, E, E2, SPLTOL, SPDIAM,
448     $                    NSPLIT, ISPLIT, IINFO )
449
450*     Can force use of bisection instead of faster DQDS.
451*     Option left in the code for future multisection work.
452      FORCEB = .FALSE.
453
454*     Initialize USEDQD, DQDS should be used for ALLRNG unless someone
455*     explicitly wants bisection.
456      USEDQD = (( IRANGE.EQ.ALLRNG ) .AND. (.NOT.FORCEB))
457
458      IF( (IRANGE.EQ.ALLRNG) .AND. (.NOT. FORCEB) ) THEN
459*        Set interval [VL,VU] that contains all eigenvalues
460         VL = GL
461         VU = GU
462      ELSE
463*        We call DLARRD to find crude approximations to the eigenvalues
464*        in the desired range. In case IRANGE = INDRNG, we also obtain the
465*        interval (VL,VU] that contains all the wanted eigenvalues.
466*        An interval [LEFT,RIGHT] has converged if
467*        RIGHT-LEFT.LT.RTOL*MAX(ABS(LEFT),ABS(RIGHT))
468*        DLARRD needs a WORK of size 4*N, IWORK of size 3*N
469         CALL DLARRD( RANGE, 'B', N, VL, VU, IL, IU, GERS,
470     $                    BSRTOL, D, E, E2, PIVMIN, NSPLIT, ISPLIT,
471     $                    MM, W, WERR, VL, VU, IBLOCK, INDEXW,
472     $                    WORK, IWORK, IINFO )
473         IF( IINFO.NE.0 ) THEN
474            INFO = -1
475            RETURN
476         ENDIF
477*        Make sure that the entries M+1 to N in W, WERR, IBLOCK, INDEXW are 0
478         DO 14 I = MM+1,N
479            W( I ) = ZERO
480            WERR( I ) = ZERO
481            IBLOCK( I ) = 0
482            INDEXW( I ) = 0
483 14      CONTINUE
484      END IF
485
486
487***
488*     Loop over unreduced blocks
489      IBEGIN = 1
490      WBEGIN = 1
491      DO 170 JBLK = 1, NSPLIT
492         IEND = ISPLIT( JBLK )
493         IN = IEND - IBEGIN + 1
494
495*        1 X 1 block
496         IF( IN.EQ.1 ) THEN
497            IF( (IRANGE.EQ.ALLRNG).OR.( (IRANGE.EQ.VALRNG).AND.
498     $         ( D( IBEGIN ).GT.VL ).AND.( D( IBEGIN ).LE.VU ) )
499     $        .OR. ( (IRANGE.EQ.INDRNG).AND.(IBLOCK(WBEGIN).EQ.JBLK))
500     $        ) THEN
501               M = M + 1
502               W( M ) = D( IBEGIN )
503               WERR(M) = ZERO
504*              The gap for a single block doesn't matter for the later
505*              algorithm and is assigned an arbitrary large value
506               WGAP(M) = ZERO
507               IBLOCK( M ) = JBLK
508               INDEXW( M ) = 1
509               WBEGIN = WBEGIN + 1
510            ENDIF
511*           E( IEND ) holds the shift for the initial RRR
512            E( IEND ) = ZERO
513            IBEGIN = IEND + 1
514            GO TO 170
515         END IF
516*
517*        Blocks of size larger than 1x1
518*
519*        E( IEND ) will hold the shift for the initial RRR, for now set it =0
520         E( IEND ) = ZERO
521*
522*        Find local outer bounds GL,GU for the block
523         GL = D(IBEGIN)
524         GU = D(IBEGIN)
525         DO 15 I = IBEGIN , IEND
526            GL = MIN( GERS( 2*I-1 ), GL )
527            GU = MAX( GERS( 2*I ), GU )
528 15      CONTINUE
529         SPDIAM = GU - GL
530
531         IF(.NOT. ((IRANGE.EQ.ALLRNG).AND.(.NOT.FORCEB)) ) THEN
532*           Count the number of eigenvalues in the current block.
533            MB = 0
534            DO 20 I = WBEGIN,MM
535               IF( IBLOCK(I).EQ.JBLK ) THEN
536                  MB = MB+1
537               ELSE
538                  GOTO 21
539               ENDIF
540 20         CONTINUE
541 21         CONTINUE
542
543            IF( MB.EQ.0) THEN
544*              No eigenvalue in the current block lies in the desired range
545*              E( IEND ) holds the shift for the initial RRR
546               E( IEND ) = ZERO
547               IBEGIN = IEND + 1
548               GO TO 170
549            ELSE
550
551*              Decide whether dqds or bisection is more efficient
552               USEDQD = ( (MB .GT. FAC*IN) .AND. (.NOT.FORCEB) )
553               WEND = WBEGIN + MB - 1
554*              Calculate gaps for the current block
555*              In later stages, when representations for individual
556*              eigenvalues are different, we use SIGMA = E( IEND ).
557               SIGMA = ZERO
558               DO 30 I = WBEGIN, WEND - 1
559                  WGAP( I ) = MAX( ZERO,
560     $                        W(I+1)-WERR(I+1) - (W(I)+WERR(I)) )
561 30            CONTINUE
562               WGAP( WEND ) = MAX( ZERO,
563     $                     VU - SIGMA - (W( WEND )+WERR( WEND )))
564*              Find local index of the first and last desired evalue.
565               INDL = INDEXW(WBEGIN)
566               INDU = INDEXW( WEND )
567            ENDIF
568         ENDIF
569         IF(( (IRANGE.EQ.ALLRNG) .AND. (.NOT. FORCEB) ).OR.USEDQD) THEN
570*           Case of DQDS
571*           Find approximations to the extremal eigenvalues of the block
572            CALL DLARRK( IN, 1, GL, GU, D(IBEGIN),
573     $               E2(IBEGIN), PIVMIN, RTL, TMP, TMP1, IINFO )
574            IF( IINFO.NE.0 ) THEN
575               INFO = -1
576               RETURN
577            ENDIF
578            ISLEFT = MAX(GL, TMP - TMP1
579     $               - HNDRD * EPS* ABS(TMP - TMP1))
580
581            CALL DLARRK( IN, IN, GL, GU, D(IBEGIN),
582     $               E2(IBEGIN), PIVMIN, RTL, TMP, TMP1, IINFO )
583            IF( IINFO.NE.0 ) THEN
584               INFO = -1
585               RETURN
586            ENDIF
587            ISRGHT = MIN(GU, TMP + TMP1
588     $                 + HNDRD * EPS * ABS(TMP + TMP1))
589*           Improve the estimate of the spectral diameter
590            SPDIAM = ISRGHT - ISLEFT
591         ELSE
592*           Case of bisection
593*           Find approximations to the wanted extremal eigenvalues
594            ISLEFT = MAX(GL, W(WBEGIN) - WERR(WBEGIN)
595     $                  - HNDRD * EPS*ABS(W(WBEGIN)- WERR(WBEGIN) ))
596            ISRGHT = MIN(GU,W(WEND) + WERR(WEND)
597     $                  + HNDRD * EPS * ABS(W(WEND)+ WERR(WEND)))
598         ENDIF
599
600
601*        Decide whether the base representation for the current block
602*        L_JBLK D_JBLK L_JBLK^T = T_JBLK - sigma_JBLK I
603*        should be on the left or the right end of the current block.
604*        The strategy is to shift to the end which is "more populated"
605*        Furthermore, decide whether to use DQDS for the computation of
606*        the eigenvalue approximations at the end of DLARRE or bisection.
607*        dqds is chosen if all eigenvalues are desired or the number of
608*        eigenvalues to be computed is large compared to the blocksize.
609         IF( ( IRANGE.EQ.ALLRNG ) .AND. (.NOT.FORCEB) ) THEN
610*           If all the eigenvalues have to be computed, we use dqd
611            USEDQD = .TRUE.
612*           INDL is the local index of the first eigenvalue to compute
613            INDL = 1
614            INDU = IN
615*           MB =  number of eigenvalues to compute
616            MB = IN
617            WEND = WBEGIN + MB - 1
618*           Define 1/4 and 3/4 points of the spectrum
619            S1 = ISLEFT + FOURTH * SPDIAM
620            S2 = ISRGHT - FOURTH * SPDIAM
621         ELSE
622*           DLARRD has computed IBLOCK and INDEXW for each eigenvalue
623*           approximation.
624*           choose sigma
625            IF( USEDQD ) THEN
626               S1 = ISLEFT + FOURTH * SPDIAM
627               S2 = ISRGHT - FOURTH * SPDIAM
628            ELSE
629               TMP = MIN(ISRGHT,VU) -  MAX(ISLEFT,VL)
630               S1 =  MAX(ISLEFT,VL) + FOURTH * TMP
631               S2 =  MIN(ISRGHT,VU) - FOURTH * TMP
632            ENDIF
633         ENDIF
634
635*        Compute the negcount at the 1/4 and 3/4 points
636         IF(MB.GT.1) THEN
637            CALL DLARRC( 'T', IN, S1, S2, D(IBEGIN),
638     $                    E(IBEGIN), PIVMIN, CNT, CNT1, CNT2, IINFO)
639         ENDIF
640
641         IF(MB.EQ.1) THEN
642            SIGMA = GL
643            SGNDEF = ONE
644         ELSEIF( CNT1 - INDL .GE. INDU - CNT2 ) THEN
645            IF( ( IRANGE.EQ.ALLRNG ) .AND. (.NOT.FORCEB) ) THEN
646               SIGMA = MAX(ISLEFT,GL)
647            ELSEIF( USEDQD ) THEN
648*              use Gerschgorin bound as shift to get pos def matrix
649*              for dqds
650               SIGMA = ISLEFT
651            ELSE
652*              use approximation of the first desired eigenvalue of the
653*              block as shift
654               SIGMA = MAX(ISLEFT,VL)
655            ENDIF
656            SGNDEF = ONE
657         ELSE
658            IF( ( IRANGE.EQ.ALLRNG ) .AND. (.NOT.FORCEB) ) THEN
659               SIGMA = MIN(ISRGHT,GU)
660            ELSEIF( USEDQD ) THEN
661*              use Gerschgorin bound as shift to get neg def matrix
662*              for dqds
663               SIGMA = ISRGHT
664            ELSE
665*              use approximation of the first desired eigenvalue of the
666*              block as shift
667               SIGMA = MIN(ISRGHT,VU)
668            ENDIF
669            SGNDEF = -ONE
670         ENDIF
671
672
673*        An initial SIGMA has been chosen that will be used for computing
674*        T - SIGMA I = L D L^T
675*        Define the increment TAU of the shift in case the initial shift
676*        needs to be refined to obtain a factorization with not too much
677*        element growth.
678         IF( USEDQD ) THEN
679*           The initial SIGMA was to the outer end of the spectrum
680*           the matrix is definite and we need not retreat.
681            TAU = SPDIAM*EPS*N + TWO*PIVMIN
682            TAU = MAX( TAU,TWO*EPS*ABS(SIGMA) )
683         ELSE
684            IF(MB.GT.1) THEN
685               CLWDTH = W(WEND) + WERR(WEND) - W(WBEGIN) - WERR(WBEGIN)
686               AVGAP = ABS(CLWDTH / DBLE(WEND-WBEGIN))
687               IF( SGNDEF.EQ.ONE ) THEN
688                  TAU = HALF*MAX(WGAP(WBEGIN),AVGAP)
689                  TAU = MAX(TAU,WERR(WBEGIN))
690               ELSE
691                  TAU = HALF*MAX(WGAP(WEND-1),AVGAP)
692                  TAU = MAX(TAU,WERR(WEND))
693               ENDIF
694            ELSE
695               TAU = WERR(WBEGIN)
696            ENDIF
697         ENDIF
698*
699         DO 80 IDUM = 1, MAXTRY
700*           Compute L D L^T factorization of tridiagonal matrix T - sigma I.
701*           Store D in WORK(1:IN), L in WORK(IN+1:2*IN), and reciprocals of
702*           pivots in WORK(2*IN+1:3*IN)
703            DPIVOT = D( IBEGIN ) - SIGMA
704            WORK( 1 ) = DPIVOT
705            DMAX = ABS( WORK(1) )
706            J = IBEGIN
707            DO 70 I = 1, IN - 1
708               WORK( 2*IN+I ) = ONE / WORK( I )
709               TMP = E( J )*WORK( 2*IN+I )
710               WORK( IN+I ) = TMP
711               DPIVOT = ( D( J+1 )-SIGMA ) - TMP*E( J )
712               WORK( I+1 ) = DPIVOT
713               DMAX = MAX( DMAX, ABS(DPIVOT) )
714               J = J + 1
715 70         CONTINUE
716*           check for element growth
717            IF( DMAX .GT. MAXGROWTH*SPDIAM ) THEN
718               NOREP = .TRUE.
719            ELSE
720               NOREP = .FALSE.
721            ENDIF
722            IF( USEDQD .AND. .NOT.NOREP ) THEN
723*              Ensure the definiteness of the representation
724*              All entries of D (of L D L^T) must have the same sign
725               DO 71 I = 1, IN
726                  TMP = SGNDEF*WORK( I )
727                  IF( TMP.LT.ZERO ) NOREP = .TRUE.
728 71            CONTINUE
729            ENDIF
730            IF(NOREP) THEN
731*              Note that in the case of IRANGE=ALLRNG, we use the Gerschgorin
732*              shift which makes the matrix definite. So we should end up
733*              here really only in the case of IRANGE = VALRNG or INDRNG.
734               IF( IDUM.EQ.MAXTRY-1 ) THEN
735                  IF( SGNDEF.EQ.ONE ) THEN
736*                    The fudged Gerschgorin shift should succeed
737                     SIGMA =
738     $                    GL - FUDGE*SPDIAM*EPS*N - FUDGE*TWO*PIVMIN
739                  ELSE
740                     SIGMA =
741     $                    GU + FUDGE*SPDIAM*EPS*N + FUDGE*TWO*PIVMIN
742                  END IF
743               ELSE
744                  SIGMA = SIGMA - SGNDEF * TAU
745                  TAU = TWO * TAU
746               END IF
747            ELSE
748*              an initial RRR is found
749               GO TO 83
750            END IF
751 80      CONTINUE
752*        if the program reaches this point, no base representation could be
753*        found in MAXTRY iterations.
754         INFO = 2
755         RETURN
756
757 83      CONTINUE
758*        At this point, we have found an initial base representation
759*        T - SIGMA I = L D L^T with not too much element growth.
760*        Store the shift.
761         E( IEND ) = SIGMA
762*        Store D and L.
763         CALL DCOPY( IN, WORK, 1, D( IBEGIN ), 1 )
764         CALL DCOPY( IN-1, WORK( IN+1 ), 1, E( IBEGIN ), 1 )
765
766
767         IF(MB.GT.1 ) THEN
768*
769*           Perturb each entry of the base representation by a small
770*           (but random) relative amount to overcome difficulties with
771*           glued matrices.
772*
773            DO 122 I = 1, 4
774               ISEED( I ) = 1
775 122        CONTINUE
776
777            CALL DLARNV(2, ISEED, 2*IN-1, WORK(1))
778            DO 125 I = 1,IN-1
779               D(IBEGIN+I-1) = D(IBEGIN+I-1)*(ONE+EPS*PERT*WORK(I))
780               E(IBEGIN+I-1) = E(IBEGIN+I-1)*(ONE+EPS*PERT*WORK(IN+I))
781 125        CONTINUE
782            D(IEND) = D(IEND)*(ONE+EPS*FOUR*WORK(IN))
783*
784         ENDIF
785*
786*        Don't update the Gerschgorin intervals because keeping track
787*        of the updates would be too much work in DLARRV.
788*        We update W instead and use it to locate the proper Gerschgorin
789*        intervals.
790
791*        Compute the required eigenvalues of L D L' by bisection or dqds
792         IF ( .NOT.USEDQD ) THEN
793*           If DLARRD has been used, shift the eigenvalue approximations
794*           according to their representation. This is necessary for
795*           a uniform DLARRV since dqds computes eigenvalues of the
796*           shifted representation. In DLARRV, W will always hold the
797*           UNshifted eigenvalue approximation.
798            DO 134 J=WBEGIN,WEND
799               W(J) = W(J) - SIGMA
800               WERR(J) = WERR(J) + ABS(W(J)) * EPS
801 134        CONTINUE
802*           call DLARRB to reduce eigenvalue error of the approximations
803*           from DLARRD
804            DO 135 I = IBEGIN, IEND-1
805               WORK( I ) = D( I ) * E( I )**2
806 135        CONTINUE
807*           use bisection to find EV from INDL to INDU
808            CALL DLARRB(IN, D(IBEGIN), WORK(IBEGIN),
809     $                  INDL, INDU, RTOL1, RTOL2, INDL-1,
810     $                  W(WBEGIN), WGAP(WBEGIN), WERR(WBEGIN),
811     $                  WORK( 2*N+1 ), IWORK, PIVMIN, SPDIAM,
812     $                  IN, IINFO )
813            IF( IINFO .NE. 0 ) THEN
814               INFO = -4
815               RETURN
816            END IF
817*           DLARRB computes all gaps correctly except for the last one
818*           Record distance to VU/GU
819            WGAP( WEND ) = MAX( ZERO,
820     $           ( VU-SIGMA ) - ( W( WEND ) + WERR( WEND ) ) )
821            DO 138 I = INDL, INDU
822               M = M + 1
823               IBLOCK(M) = JBLK
824               INDEXW(M) = I
825 138        CONTINUE
826         ELSE
827*           Call dqds to get all eigs (and then possibly delete unwanted
828*           eigenvalues).
829*           Note that dqds finds the eigenvalues of the L D L^T representation
830*           of T to high relative accuracy. High relative accuracy
831*           might be lost when the shift of the RRR is subtracted to obtain
832*           the eigenvalues of T. However, T is not guaranteed to define its
833*           eigenvalues to high relative accuracy anyway.
834*           Set RTOL to the order of the tolerance used in DLASQ2
835*           This is an ESTIMATED error, the worst case bound is 4*N*EPS
836*           which is usually too large and requires unnecessary work to be
837*           done by bisection when computing the eigenvectors
838            RTOL = LOG(DBLE(IN)) * FOUR * EPS
839            J = IBEGIN
840            DO 140 I = 1, IN - 1
841               WORK( 2*I-1 ) = ABS( D( J ) )
842               WORK( 2*I ) = E( J )*E( J )*WORK( 2*I-1 )
843               J = J + 1
844  140       CONTINUE
845            WORK( 2*IN-1 ) = ABS( D( IEND ) )
846            WORK( 2*IN ) = ZERO
847            CALL DLASQ2( IN, WORK, IINFO )
848            IF( IINFO .NE. 0 ) THEN
849*              If IINFO = -5 then an index is part of a tight cluster
850*              and should be changed. The index is in IWORK(1) and the
851*              gap is in WORK(N+1)
852               INFO = -5
853               RETURN
854            ELSE
855*              Test that all eigenvalues are positive as expected
856               DO 149 I = 1, IN
857                  IF( WORK( I ).LT.ZERO ) THEN
858                     INFO = -6
859                     RETURN
860                  ENDIF
861 149           CONTINUE
862            END IF
863            IF( SGNDEF.GT.ZERO ) THEN
864               DO 150 I = INDL, INDU
865                  M = M + 1
866                  W( M ) = WORK( IN-I+1 )
867                  IBLOCK( M ) = JBLK
868                  INDEXW( M ) = I
869 150           CONTINUE
870            ELSE
871               DO 160 I = INDL, INDU
872                  M = M + 1
873                  W( M ) = -WORK( I )
874                  IBLOCK( M ) = JBLK
875                  INDEXW( M ) = I
876 160           CONTINUE
877            END IF
878
879            DO 165 I = M - MB + 1, M
880*              the value of RTOL below should be the tolerance in DLASQ2
881               WERR( I ) = RTOL * ABS( W(I) )
882 165        CONTINUE
883            DO 166 I = M - MB + 1, M - 1
884*              compute the right gap between the intervals
885               WGAP( I ) = MAX( ZERO,
886     $                          W(I+1)-WERR(I+1) - (W(I)+WERR(I)) )
887 166        CONTINUE
888            WGAP( M ) = MAX( ZERO,
889     $           ( VU-SIGMA ) - ( W( M ) + WERR( M ) ) )
890         END IF
891*        proceed with next block
892         IBEGIN = IEND + 1
893         WBEGIN = WEND + 1
894 170  CONTINUE
895*
896
897      RETURN
898*
899*     End of DLARRE
900*
901      END
902