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