LAPACK  3.11.0
LAPACK: Linear Algebra PACKage
dlarrd.f
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 larrd
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  m = 0
385 *
386 * Quick return if possible
387 *
388  IF( n.LE.0 ) THEN
389  RETURN
390  END IF
391 *
392 * Decode RANGE
393 *
394  IF( lsame( range, 'A' ) ) THEN
395  irange = allrng
396  ELSE IF( lsame( range, 'V' ) ) THEN
397  irange = valrng
398  ELSE IF( lsame( range, 'I' ) ) THEN
399  irange = indrng
400  ELSE
401  irange = 0
402  END IF
403 *
404 * Check for Errors
405 *
406  IF( irange.LE.0 ) THEN
407  info = -1
408  ELSE IF( .NOT.(lsame(order,'B').OR.lsame(order,'E')) ) THEN
409  info = -2
410  ELSE IF( n.LT.0 ) THEN
411  info = -3
412  ELSE IF( irange.EQ.valrng ) THEN
413  IF( vl.GE.vu )
414  $ info = -5
415  ELSE IF( irange.EQ.indrng .AND.
416  $ ( il.LT.1 .OR. il.GT.max( 1, n ) ) ) THEN
417  info = -6
418  ELSE IF( irange.EQ.indrng .AND.
419  $ ( iu.LT.min( n, il ) .OR. iu.GT.n ) ) THEN
420  info = -7
421  END IF
422 *
423  IF( info.NE.0 ) THEN
424  RETURN
425  END IF
426 
427 * Initialize error flags
428  ncnvrg = .false.
429  toofew = .false.
430 
431 * Simplification:
432  IF( irange.EQ.indrng .AND. il.EQ.1 .AND. iu.EQ.n ) irange = 1
433 
434 * Get machine constants
435  eps = dlamch( 'P' )
436  uflow = dlamch( 'U' )
437 
438 
439 * Special Case when N=1
440 * Treat case of 1x1 matrix for quick return
441  IF( n.EQ.1 ) THEN
442  IF( (irange.EQ.allrng).OR.
443  $ ((irange.EQ.valrng).AND.(d(1).GT.vl).AND.(d(1).LE.vu)).OR.
444  $ ((irange.EQ.indrng).AND.(il.EQ.1).AND.(iu.EQ.1)) ) THEN
445  m = 1
446  w(1) = d(1)
447 * The computation error of the eigenvalue is zero
448  werr(1) = zero
449  iblock( 1 ) = 1
450  indexw( 1 ) = 1
451  ENDIF
452  RETURN
453  END IF
454 
455 * NB is the minimum vector length for vector bisection, or 0
456 * if only scalar is to be done.
457  nb = ilaenv( 1, 'DSTEBZ', ' ', n, -1, -1, -1 )
458  IF( nb.LE.1 ) nb = 0
459 
460 * Find global spectral radius
461  gl = d(1)
462  gu = d(1)
463  DO 5 i = 1,n
464  gl = min( gl, gers( 2*i - 1))
465  gu = max( gu, gers(2*i) )
466  5 CONTINUE
467 * Compute global Gerschgorin bounds and spectral diameter
468  tnorm = max( abs( gl ), abs( gu ) )
469  gl = gl - fudge*tnorm*eps*n - fudge*two*pivmin
470  gu = gu + fudge*tnorm*eps*n + fudge*two*pivmin
471 * [JAN/28/2009] remove the line below since SPDIAM variable not use
472 * SPDIAM = GU - GL
473 * Input arguments for DLAEBZ:
474 * The relative tolerance. An interval (a,b] lies within
475 * "relative tolerance" if b-a < RELTOL*max(|a|,|b|),
476  rtoli = reltol
477 * Set the absolute tolerance for interval convergence to zero to force
478 * interval convergence based on relative size of the interval.
479 * This is dangerous because intervals might not converge when RELTOL is
480 * small. But at least a very small number should be selected so that for
481 * strongly graded matrices, the code can get relatively accurate
482 * eigenvalues.
483  atoli = fudge*two*uflow + fudge*two*pivmin
484 
485  IF( irange.EQ.indrng ) THEN
486 
487 * RANGE='I': Compute an interval containing eigenvalues
488 * IL through IU. The initial interval [GL,GU] from the global
489 * Gerschgorin bounds GL and GU is refined by DLAEBZ.
490  itmax = int( ( log( tnorm+pivmin )-log( pivmin ) ) /
491  $ log( two ) ) + 2
492  work( n+1 ) = gl
493  work( n+2 ) = gl
494  work( n+3 ) = gu
495  work( n+4 ) = gu
496  work( n+5 ) = gl
497  work( n+6 ) = gu
498  iwork( 1 ) = -1
499  iwork( 2 ) = -1
500  iwork( 3 ) = n + 1
501  iwork( 4 ) = n + 1
502  iwork( 5 ) = il - 1
503  iwork( 6 ) = iu
504 *
505  CALL dlaebz( 3, itmax, n, 2, 2, nb, atoli, rtoli, pivmin,
506  $ d, e, e2, iwork( 5 ), work( n+1 ), work( n+5 ), iout,
507  $ iwork, w, iblock, iinfo )
508  IF( iinfo .NE. 0 ) THEN
509  info = iinfo
510  RETURN
511  END IF
512 * On exit, output intervals may not be ordered by ascending negcount
513  IF( iwork( 6 ).EQ.iu ) THEN
514  wl = work( n+1 )
515  wlu = work( n+3 )
516  nwl = iwork( 1 )
517  wu = work( n+4 )
518  wul = work( n+2 )
519  nwu = iwork( 4 )
520  ELSE
521  wl = work( n+2 )
522  wlu = work( n+4 )
523  nwl = iwork( 2 )
524  wu = work( n+3 )
525  wul = work( n+1 )
526  nwu = iwork( 3 )
527  END IF
528 * On exit, the interval [WL, WLU] contains a value with negcount NWL,
529 * and [WUL, WU] contains a value with negcount NWU.
530  IF( nwl.LT.0 .OR. nwl.GE.n .OR. nwu.LT.1 .OR. nwu.GT.n ) THEN
531  info = 4
532  RETURN
533  END IF
534 
535  ELSEIF( irange.EQ.valrng ) THEN
536  wl = vl
537  wu = vu
538 
539  ELSEIF( irange.EQ.allrng ) THEN
540  wl = gl
541  wu = gu
542  ENDIF
543 
544 
545 
546 * Find Eigenvalues -- Loop Over blocks and recompute NWL and NWU.
547 * NWL accumulates the number of eigenvalues .le. WL,
548 * NWU accumulates the number of eigenvalues .le. WU
549  m = 0
550  iend = 0
551  info = 0
552  nwl = 0
553  nwu = 0
554 *
555  DO 70 jblk = 1, nsplit
556  ioff = iend
557  ibegin = ioff + 1
558  iend = isplit( jblk )
559  in = iend - ioff
560 *
561  IF( in.EQ.1 ) THEN
562 * 1x1 block
563  IF( wl.GE.d( ibegin )-pivmin )
564  $ nwl = nwl + 1
565  IF( wu.GE.d( ibegin )-pivmin )
566  $ nwu = nwu + 1
567  IF( irange.EQ.allrng .OR.
568  $ ( wl.LT.d( ibegin )-pivmin
569  $ .AND. wu.GE. d( ibegin )-pivmin ) ) THEN
570  m = m + 1
571  w( m ) = d( ibegin )
572  werr(m) = zero
573 * The gap for a single block doesn't matter for the later
574 * algorithm and is assigned an arbitrary large value
575  iblock( m ) = jblk
576  indexw( m ) = 1
577  END IF
578 
579 * Disabled 2x2 case because of a failure on the following matrix
580 * RANGE = 'I', IL = IU = 4
581 * Original Tridiagonal, d = [
582 * -0.150102010615740E+00
583 * -0.849897989384260E+00
584 * -0.128208148052635E-15
585 * 0.128257718286320E-15
586 * ];
587 * e = [
588 * -0.357171383266986E+00
589 * -0.180411241501588E-15
590 * -0.175152352710251E-15
591 * ];
592 *
593 * ELSE IF( IN.EQ.2 ) THEN
594 ** 2x2 block
595 * DISC = SQRT( (HALF*(D(IBEGIN)-D(IEND)))**2 + E(IBEGIN)**2 )
596 * TMP1 = HALF*(D(IBEGIN)+D(IEND))
597 * L1 = TMP1 - DISC
598 * IF( WL.GE. L1-PIVMIN )
599 * $ NWL = NWL + 1
600 * IF( WU.GE. L1-PIVMIN )
601 * $ NWU = NWU + 1
602 * IF( IRANGE.EQ.ALLRNG .OR. ( WL.LT.L1-PIVMIN .AND. WU.GE.
603 * $ L1-PIVMIN ) ) THEN
604 * M = M + 1
605 * W( M ) = L1
606 ** The uncertainty of eigenvalues of a 2x2 matrix is very small
607 * WERR( M ) = EPS * ABS( W( M ) ) * TWO
608 * IBLOCK( M ) = JBLK
609 * INDEXW( M ) = 1
610 * ENDIF
611 * L2 = TMP1 + DISC
612 * IF( WL.GE. L2-PIVMIN )
613 * $ NWL = NWL + 1
614 * IF( WU.GE. L2-PIVMIN )
615 * $ NWU = NWU + 1
616 * IF( IRANGE.EQ.ALLRNG .OR. ( WL.LT.L2-PIVMIN .AND. WU.GE.
617 * $ L2-PIVMIN ) ) THEN
618 * M = M + 1
619 * W( M ) = L2
620 ** The uncertainty of eigenvalues of a 2x2 matrix is very small
621 * WERR( M ) = EPS * ABS( W( M ) ) * TWO
622 * IBLOCK( M ) = JBLK
623 * INDEXW( M ) = 2
624 * ENDIF
625  ELSE
626 * General Case - block of size IN >= 2
627 * Compute local Gerschgorin interval and use it as the initial
628 * interval for DLAEBZ
629  gu = d( ibegin )
630  gl = d( ibegin )
631  tmp1 = zero
632 
633  DO 40 j = ibegin, iend
634  gl = min( gl, gers( 2*j - 1))
635  gu = max( gu, gers(2*j) )
636  40 CONTINUE
637 * [JAN/28/2009]
638 * change SPDIAM by TNORM in lines 2 and 3 thereafter
639 * line 1: remove computation of SPDIAM (not useful anymore)
640 * SPDIAM = GU - GL
641 * GL = GL - FUDGE*SPDIAM*EPS*IN - FUDGE*PIVMIN
642 * GU = GU + FUDGE*SPDIAM*EPS*IN + FUDGE*PIVMIN
643  gl = gl - fudge*tnorm*eps*in - fudge*pivmin
644  gu = gu + fudge*tnorm*eps*in + fudge*pivmin
645 *
646  IF( irange.GT.1 ) THEN
647  IF( gu.LT.wl ) THEN
648 * the local block contains none of the wanted eigenvalues
649  nwl = nwl + in
650  nwu = nwu + in
651  GO TO 70
652  END IF
653 * refine search interval if possible, only range (WL,WU] matters
654  gl = max( gl, wl )
655  gu = min( gu, wu )
656  IF( gl.GE.gu )
657  $ GO TO 70
658  END IF
659 
660 * Find negcount of initial interval boundaries GL and GU
661  work( n+1 ) = gl
662  work( n+in+1 ) = gu
663  CALL dlaebz( 1, 0, in, in, 1, nb, atoli, rtoli, pivmin,
664  $ d( ibegin ), e( ibegin ), e2( ibegin ),
665  $ idumma, work( n+1 ), work( n+2*in+1 ), im,
666  $ iwork, w( m+1 ), iblock( m+1 ), iinfo )
667  IF( iinfo .NE. 0 ) THEN
668  info = iinfo
669  RETURN
670  END IF
671 *
672  nwl = nwl + iwork( 1 )
673  nwu = nwu + iwork( in+1 )
674  iwoff = m - iwork( 1 )
675 
676 * Compute Eigenvalues
677  itmax = int( ( log( gu-gl+pivmin )-log( pivmin ) ) /
678  $ log( two ) ) + 2
679  CALL dlaebz( 2, itmax, in, in, 1, nb, atoli, rtoli, pivmin,
680  $ d( ibegin ), e( ibegin ), e2( ibegin ),
681  $ idumma, work( n+1 ), work( n+2*in+1 ), iout,
682  $ iwork, w( m+1 ), iblock( m+1 ), iinfo )
683  IF( iinfo .NE. 0 ) THEN
684  info = iinfo
685  RETURN
686  END IF
687 *
688 * Copy eigenvalues into W and IBLOCK
689 * Use -JBLK for block number for unconverged eigenvalues.
690 * Loop over the number of output intervals from DLAEBZ
691  DO 60 j = 1, iout
692 * eigenvalue approximation is middle point of interval
693  tmp1 = half*( work( j+n )+work( j+in+n ) )
694 * semi length of error interval
695  tmp2 = half*abs( work( j+n )-work( j+in+n ) )
696  IF( j.GT.iout-iinfo ) THEN
697 * Flag non-convergence.
698  ncnvrg = .true.
699  ib = -jblk
700  ELSE
701  ib = jblk
702  END IF
703  DO 50 je = iwork( j ) + 1 + iwoff,
704  $ iwork( j+in ) + iwoff
705  w( je ) = tmp1
706  werr( je ) = tmp2
707  indexw( je ) = je - iwoff
708  iblock( je ) = ib
709  50 CONTINUE
710  60 CONTINUE
711 *
712  m = m + im
713  END IF
714  70 CONTINUE
715 
716 * If RANGE='I', then (WL,WU) contains eigenvalues NWL+1,...,NWU
717 * If NWL+1 < IL or NWU > IU, discard extra eigenvalues.
718  IF( irange.EQ.indrng ) THEN
719  idiscl = il - 1 - nwl
720  idiscu = nwu - iu
721 *
722  IF( idiscl.GT.0 ) THEN
723  im = 0
724  DO 80 je = 1, m
725 * Remove some of the smallest eigenvalues from the left so that
726 * at the end IDISCL =0. Move all eigenvalues up to the left.
727  IF( w( je ).LE.wlu .AND. idiscl.GT.0 ) THEN
728  idiscl = idiscl - 1
729  ELSE
730  im = im + 1
731  w( im ) = w( je )
732  werr( im ) = werr( je )
733  indexw( im ) = indexw( je )
734  iblock( im ) = iblock( je )
735  END IF
736  80 CONTINUE
737  m = im
738  END IF
739  IF( idiscu.GT.0 ) THEN
740 * Remove some of the largest eigenvalues from the right so that
741 * at the end IDISCU =0. Move all eigenvalues up to the left.
742  im=m+1
743  DO 81 je = m, 1, -1
744  IF( w( je ).GE.wul .AND. idiscu.GT.0 ) THEN
745  idiscu = idiscu - 1
746  ELSE
747  im = im - 1
748  w( im ) = w( je )
749  werr( im ) = werr( je )
750  indexw( im ) = indexw( je )
751  iblock( im ) = iblock( je )
752  END IF
753  81 CONTINUE
754  jee = 0
755  DO 82 je = im, m
756  jee = jee + 1
757  w( jee ) = w( je )
758  werr( jee ) = werr( je )
759  indexw( jee ) = indexw( je )
760  iblock( jee ) = iblock( je )
761  82 CONTINUE
762  m = m-im+1
763  END IF
764 
765  IF( idiscl.GT.0 .OR. idiscu.GT.0 ) THEN
766 * Code to deal with effects of bad arithmetic. (If N(w) is
767 * monotone non-decreasing, this should never happen.)
768 * Some low eigenvalues to be discarded are not in (WL,WLU],
769 * or high eigenvalues to be discarded are not in (WUL,WU]
770 * so just kill off the smallest IDISCL/largest IDISCU
771 * eigenvalues, by marking the corresponding IBLOCK = 0
772  IF( idiscl.GT.0 ) THEN
773  wkill = wu
774  DO 100 jdisc = 1, idiscl
775  iw = 0
776  DO 90 je = 1, m
777  IF( iblock( je ).NE.0 .AND.
778  $ ( w( je ).LT.wkill .OR. iw.EQ.0 ) ) THEN
779  iw = je
780  wkill = w( je )
781  END IF
782  90 CONTINUE
783  iblock( iw ) = 0
784  100 CONTINUE
785  END IF
786  IF( idiscu.GT.0 ) THEN
787  wkill = wl
788  DO 120 jdisc = 1, idiscu
789  iw = 0
790  DO 110 je = 1, m
791  IF( iblock( je ).NE.0 .AND.
792  $ ( w( je ).GE.wkill .OR. iw.EQ.0 ) ) THEN
793  iw = je
794  wkill = w( je )
795  END IF
796  110 CONTINUE
797  iblock( iw ) = 0
798  120 CONTINUE
799  END IF
800 * Now erase all eigenvalues with IBLOCK set to zero
801  im = 0
802  DO 130 je = 1, m
803  IF( iblock( je ).NE.0 ) THEN
804  im = im + 1
805  w( im ) = w( je )
806  werr( im ) = werr( je )
807  indexw( im ) = indexw( je )
808  iblock( im ) = iblock( je )
809  END IF
810  130 CONTINUE
811  m = im
812  END IF
813  IF( idiscl.LT.0 .OR. idiscu.LT.0 ) THEN
814  toofew = .true.
815  END IF
816  END IF
817 *
818  IF(( irange.EQ.allrng .AND. m.NE.n ).OR.
819  $ ( irange.EQ.indrng .AND. m.NE.iu-il+1 ) ) THEN
820  toofew = .true.
821  END IF
822 
823 * If ORDER='B', do nothing the eigenvalues are already sorted by
824 * block.
825 * If ORDER='E', sort the eigenvalues from smallest to largest
826 
827  IF( lsame(order,'E') .AND. nsplit.GT.1 ) THEN
828  DO 150 je = 1, m - 1
829  ie = 0
830  tmp1 = w( je )
831  DO 140 j = je + 1, m
832  IF( w( j ).LT.tmp1 ) THEN
833  ie = j
834  tmp1 = w( j )
835  END IF
836  140 CONTINUE
837  IF( ie.NE.0 ) THEN
838  tmp2 = werr( ie )
839  itmp1 = iblock( ie )
840  itmp2 = indexw( ie )
841  w( ie ) = w( je )
842  werr( ie ) = werr( je )
843  iblock( ie ) = iblock( je )
844  indexw( ie ) = indexw( je )
845  w( je ) = tmp1
846  werr( je ) = tmp2
847  iblock( je ) = itmp1
848  indexw( je ) = itmp2
849  END IF
850  150 CONTINUE
851  END IF
852 *
853  info = 0
854  IF( ncnvrg )
855  $ info = info + 1
856  IF( toofew )
857  $ info = info + 2
858  RETURN
859 *
860 * End of DLARRD
861 *
862  END
subroutine dlaebz(IJOB, NITMAX, N, MMAX, MINP, NBMIN, ABSTOL, RELTOL, PIVMIN, D, E, E2, NVAL, AB, C, MOUT, NAB, WORK, IWORK, INFO)
DLAEBZ computes the number of eigenvalues of a real symmetric tridiagonal matrix which are less than ...
Definition: dlaebz.f:319
subroutine dlarrd(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)
DLARRD computes the eigenvalues of a symmetric tridiagonal matrix to suitable accuracy.
Definition: dlarrd.f:329