LAPACK 3.12.1
LAPACK: Linear Algebra PACKage
Loading...
Searching...
No Matches
sstemr.f
Go to the documentation of this file.
1*> \brief \b SSTEMR
2*
3* =========== DOCUMENTATION ===========
4*
5* Online html documentation available at
6* http://www.netlib.org/lapack/explore-html/
7*
8*> Download SSTEMR + dependencies
9*> <a href="http://www.netlib.org/cgi-bin/netlibfiles.tgz?format=tgz&filename=/lapack/lapack_routine/sstemr.f">
10*> [TGZ]</a>
11*> <a href="http://www.netlib.org/cgi-bin/netlibfiles.zip?format=zip&filename=/lapack/lapack_routine/sstemr.f">
12*> [ZIP]</a>
13*> <a href="http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/sstemr.f">
14*> [TXT]</a>
15*
16* Definition:
17* ===========
18*
19* SUBROUTINE SSTEMR( JOBZ, RANGE, N, D, E, VL, VU, IL, IU,
20* M, W, Z, LDZ, NZC, ISUPPZ, TRYRAC, WORK, LWORK,
21* IWORK, LIWORK, INFO )
22*
23* .. Scalar Arguments ..
24* CHARACTER JOBZ, RANGE
25* LOGICAL TRYRAC
26* INTEGER IL, INFO, IU, LDZ, NZC, LIWORK, LWORK, M, N
27* REAL VL, VU
28* ..
29* .. Array Arguments ..
30* INTEGER ISUPPZ( * ), IWORK( * )
31* REAL D( * ), E( * ), W( * ), WORK( * )
32* REAL Z( LDZ, * )
33* ..
34*
35*
36*> \par Purpose:
37* =============
38*>
39*> \verbatim
40*>
41*> SSTEMR computes selected eigenvalues and, optionally, eigenvectors
42*> of a real symmetric tridiagonal matrix T. Any such unreduced matrix has
43*> a well defined set of pairwise different real eigenvalues, the corresponding
44*> real eigenvectors are pairwise orthogonal.
45*>
46*> The spectrum may be computed either completely or partially by specifying
47*> either an interval (VL,VU] or a range of indices IL:IU for the desired
48*> eigenvalues.
49*>
50*> Depending on the number of desired eigenvalues, these are computed either
51*> by bisection or the dqds algorithm. Numerically orthogonal eigenvectors are
52*> computed by the use of various suitable L D L^T factorizations near clusters
53*> of close eigenvalues (referred to as RRRs, Relatively Robust
54*> Representations). An informal sketch of the algorithm follows.
55*>
56*> For each unreduced block (submatrix) of T,
57*> (a) Compute T - sigma I = L D L^T, so that L and D
58*> define all the wanted eigenvalues to high relative accuracy.
59*> This means that small relative changes in the entries of D and L
60*> cause only small relative changes in the eigenvalues and
61*> eigenvectors. The standard (unfactored) representation of the
62*> tridiagonal matrix T does not have this property in general.
63*> (b) Compute the eigenvalues to suitable accuracy.
64*> If the eigenvectors are desired, the algorithm attains full
65*> accuracy of the computed eigenvalues only right before
66*> the corresponding vectors have to be computed, see steps c) and d).
67*> (c) For each cluster of close eigenvalues, select a new
68*> shift close to the cluster, find a new factorization, and refine
69*> the shifted eigenvalues to suitable accuracy.
70*> (d) For each eigenvalue with a large enough relative separation compute
71*> the corresponding eigenvector by forming a rank revealing twisted
72*> factorization. Go back to (c) for any clusters that remain.
73*>
74*> For more details, see:
75*> - Inderjit S. Dhillon and Beresford N. Parlett: "Multiple representations
76*> to compute orthogonal eigenvectors of symmetric tridiagonal matrices,"
77*> Linear Algebra and its Applications, 387(1), pp. 1-28, August 2004.
78*> - Inderjit Dhillon and Beresford Parlett: "Orthogonal Eigenvectors and
79*> Relative Gaps," SIAM Journal on Matrix Analysis and Applications, Vol. 25,
80*> 2004. Also LAPACK Working Note 154.
81*> - Inderjit Dhillon: "A new O(n^2) algorithm for the symmetric
82*> tridiagonal eigenvalue/eigenvector problem",
83*> Computer Science Division Technical Report No. UCB/CSD-97-971,
84*> UC Berkeley, May 1997.
85*>
86*> Further Details
87*> 1.SSTEMR works only on machines which follow IEEE-754
88*> floating-point standard in their handling of infinities and NaNs.
89*> This permits the use of efficient inner loops avoiding a check for
90*> zero divisors.
91*> \endverbatim
92*
93* Arguments:
94* ==========
95*
96*> \param[in] JOBZ
97*> \verbatim
98*> JOBZ is CHARACTER*1
99*> = 'N': Compute eigenvalues only;
100*> = 'V': Compute eigenvalues and eigenvectors.
101*> \endverbatim
102*>
103*> \param[in] RANGE
104*> \verbatim
105*> RANGE is CHARACTER*1
106*> = 'A': all eigenvalues will be found.
107*> = 'V': all eigenvalues in the half-open interval (VL,VU]
108*> will be found.
109*> = 'I': the IL-th through IU-th eigenvalues will be found.
110*> \endverbatim
111*>
112*> \param[in] N
113*> \verbatim
114*> N is INTEGER
115*> The order of the matrix. N >= 0.
116*> \endverbatim
117*>
118*> \param[in,out] D
119*> \verbatim
120*> D is REAL array, dimension (N)
121*> On entry, the N diagonal elements of the tridiagonal matrix
122*> T. On exit, D is overwritten.
123*> \endverbatim
124*>
125*> \param[in,out] E
126*> \verbatim
127*> E is REAL array, dimension (N)
128*> On entry, the (N-1) subdiagonal elements of the tridiagonal
129*> matrix T in elements 1 to N-1 of E. E(N) need not be set on
130*> input, but is used internally as workspace.
131*> On exit, E is overwritten.
132*> \endverbatim
133*>
134*> \param[in] VL
135*> \verbatim
136*> VL is REAL
137*>
138*> If RANGE='V', the lower bound of the interval to
139*> be searched for eigenvalues. VL < VU.
140*> Not referenced if RANGE = 'A' or 'I'.
141*> \endverbatim
142*>
143*> \param[in] VU
144*> \verbatim
145*> VU is REAL
146*>
147*> If RANGE='V', the upper bound of the interval to
148*> be searched for eigenvalues. VL < VU.
149*> Not referenced if RANGE = 'A' or 'I'.
150*> \endverbatim
151*>
152*> \param[in] IL
153*> \verbatim
154*> IL is INTEGER
155*>
156*> If RANGE='I', the index of the
157*> smallest eigenvalue to be returned.
158*> 1 <= IL <= IU <= N, if N > 0.
159*> Not referenced if RANGE = 'A' or 'V'.
160*> \endverbatim
161*>
162*> \param[in] IU
163*> \verbatim
164*> IU is INTEGER
165*>
166*> If RANGE='I', the index of the
167*> largest eigenvalue to be returned.
168*> 1 <= IL <= IU <= N, if N > 0.
169*> Not referenced if RANGE = 'A' or 'V'.
170*> \endverbatim
171*>
172*> \param[out] M
173*> \verbatim
174*> M is INTEGER
175*> The total number of eigenvalues found. 0 <= M <= N.
176*> If RANGE = 'A', M = N, and if RANGE = 'I', M = IU-IL+1.
177*> \endverbatim
178*>
179*> \param[out] W
180*> \verbatim
181*> W is REAL array, dimension (N)
182*> The first M elements contain the selected eigenvalues in
183*> ascending order.
184*> \endverbatim
185*>
186*> \param[out] Z
187*> \verbatim
188*> Z is REAL array, dimension (LDZ, max(1,M) )
189*> If JOBZ = 'V', and if INFO = 0, then the first M columns of Z
190*> contain the orthonormal eigenvectors of the matrix T
191*> corresponding to the selected eigenvalues, with the i-th
192*> column of Z holding the eigenvector associated with W(i).
193*> If JOBZ = 'N', then Z is not referenced.
194*> Note: the user must ensure that at least max(1,M) columns are
195*> supplied in the array Z; if RANGE = 'V', the exact value of M
196*> is not known in advance and can be computed with a workspace
197*> query by setting NZC = -1, see below.
198*> \endverbatim
199*>
200*> \param[in] LDZ
201*> \verbatim
202*> LDZ is INTEGER
203*> The leading dimension of the array Z. LDZ >= 1, and if
204*> JOBZ = 'V', then LDZ >= max(1,N).
205*> \endverbatim
206*>
207*> \param[in] NZC
208*> \verbatim
209*> NZC is INTEGER
210*> The number of eigenvectors to be held in the array Z.
211*> If RANGE = 'A', then NZC >= max(1,N).
212*> If RANGE = 'V', then NZC >= the number of eigenvalues in (VL,VU].
213*> If RANGE = 'I', then NZC >= IU-IL+1.
214*> If NZC = -1, then a workspace query is assumed; the
215*> routine calculates the number of columns of the array Z that
216*> are needed to hold the eigenvectors.
217*> This value is returned as the first entry of the Z array, and
218*> no error message related to NZC is issued by XERBLA.
219*> \endverbatim
220*>
221*> \param[out] ISUPPZ
222*> \verbatim
223*> ISUPPZ is INTEGER array, dimension ( 2*max(1,M) )
224*> The support of the eigenvectors in Z, i.e., the indices
225*> indicating the nonzero elements in Z. The i-th computed eigenvector
226*> is nonzero only in elements ISUPPZ( 2*i-1 ) through
227*> ISUPPZ( 2*i ). This is relevant in the case when the matrix
228*> is split. ISUPPZ is only accessed when JOBZ is 'V' and N > 0.
229*> \endverbatim
230*>
231*> \param[in,out] TRYRAC
232*> \verbatim
233*> TRYRAC is LOGICAL
234*> If TRYRAC = .TRUE., indicates that the code should check whether
235*> the tridiagonal matrix defines its eigenvalues to high relative
236*> accuracy. If so, the code uses relative-accuracy preserving
237*> algorithms that might be (a bit) slower depending on the matrix.
238*> If the matrix does not define its eigenvalues to high relative
239*> accuracy, the code can uses possibly faster algorithms.
240*> If TRYRAC = .FALSE., the code is not required to guarantee
241*> relatively accurate eigenvalues and can use the fastest possible
242*> techniques.
243*> On exit, a .TRUE. TRYRAC will be set to .FALSE. if the matrix
244*> does not define its eigenvalues to high relative accuracy.
245*> \endverbatim
246*>
247*> \param[out] WORK
248*> \verbatim
249*> WORK is REAL array, dimension (LWORK)
250*> On exit, if INFO = 0, WORK(1) returns the optimal
251*> (and minimal) LWORK.
252*> \endverbatim
253*>
254*> \param[in] LWORK
255*> \verbatim
256*> LWORK is INTEGER
257*> The dimension of the array WORK. LWORK >= max(1,18*N)
258*> if JOBZ = 'V', and LWORK >= max(1,12*N) if JOBZ = 'N'.
259*> If LWORK = -1, then a workspace query is assumed; the routine
260*> only calculates the optimal size of the WORK array, returns
261*> this value as the first entry of the WORK array, and no error
262*> message related to LWORK is issued by XERBLA.
263*> \endverbatim
264*>
265*> \param[out] IWORK
266*> \verbatim
267*> IWORK is INTEGER array, dimension (LIWORK)
268*> On exit, if INFO = 0, IWORK(1) returns the optimal LIWORK.
269*> \endverbatim
270*>
271*> \param[in] LIWORK
272*> \verbatim
273*> LIWORK is INTEGER
274*> The dimension of the array IWORK. LIWORK >= max(1,10*N)
275*> if the eigenvectors are desired, and LIWORK >= max(1,8*N)
276*> if only the eigenvalues are to be computed.
277*> If LIWORK = -1, then a workspace query is assumed; the
278*> routine only calculates the optimal size of the IWORK array,
279*> returns this value as the first entry of the IWORK array, and
280*> no error message related to LIWORK is issued by XERBLA.
281*> \endverbatim
282*>
283*> \param[out] INFO
284*> \verbatim
285*> INFO is INTEGER
286*> On exit, INFO
287*> = 0: successful exit
288*> < 0: if INFO = -i, the i-th argument had an illegal value
289*> > 0: if INFO = 1X, internal error in SLARRE,
290*> if INFO = 2X, internal error in SLARRV.
291*> Here, the digit X = ABS( IINFO ) < 10, where IINFO is
292*> the nonzero error code returned by SLARRE or
293*> SLARRV, respectively.
294*> \endverbatim
295*
296* Authors:
297* ========
298*
299*> \author Univ. of Tennessee
300*> \author Univ. of California Berkeley
301*> \author Univ. of Colorado Denver
302*> \author NAG Ltd.
303*
304*> \ingroup stemr
305*
306*> \par Contributors:
307* ==================
308*>
309*> Beresford Parlett, University of California, Berkeley, USA \n
310*> Jim Demmel, University of California, Berkeley, USA \n
311*> Inderjit Dhillon, University of Texas, Austin, USA \n
312*> Osni Marques, LBNL/NERSC, USA \n
313*> Christof Voemel, University of California, Berkeley, USA \n
314*> Aravindh Krishnamoorthy, FAU, Erlangen, Germany \n
315*
316* =====================================================================
317 SUBROUTINE sstemr( JOBZ, RANGE, N, D, E, VL, VU, IL, IU,
318 $ M, W, Z, LDZ, NZC, ISUPPZ, TRYRAC, WORK, LWORK,
319 $ IWORK, LIWORK, INFO )
320*
321* -- LAPACK computational routine --
322* -- LAPACK is a software package provided by Univ. of Tennessee, --
323* -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..--
324*
325* .. Scalar Arguments ..
326 CHARACTER JOBZ, RANGE
327 LOGICAL TRYRAC
328 INTEGER IL, INFO, IU, LDZ, NZC, LIWORK, LWORK, M, N
329 REAL VL, VU
330* ..
331* .. Array Arguments ..
332 INTEGER ISUPPZ( * ), IWORK( * )
333 REAL D( * ), E( * ), W( * ), WORK( * )
334 REAL Z( LDZ, * )
335* ..
336*
337* =====================================================================
338*
339* .. Parameters ..
340 REAL ZERO, ONE, FOUR, MINRGP
341 PARAMETER ( ZERO = 0.0e0, one = 1.0e0,
342 $ four = 4.0e0,
343 $ minrgp = 3.0e-3 )
344* ..
345* .. Local Scalars ..
346 LOGICAL ALLEIG, INDEIG, LQUERY, VALEIG, WANTZ, ZQUERY,
347 $ LAESWAP
348 INTEGER I, IBEGIN, IEND, IFIRST, IIL, IINDBL, IINDW,
349 $ IINDWK, IINFO, IINSPL, IIU, ILAST, IN, INDD,
350 $ inde2, inderr, indgp, indgrs, indwrk, itmp,
351 $ itmp2, j, jblk, jj, liwmin, lwmin, nsplit,
352 $ nzcmin, offset, wbegin, wend
353 REAL BIGNUM, CS, EPS, PIVMIN, R1, R2, RMAX, RMIN,
354 $ RTOL1, RTOL2, SAFMIN, SCALE, SMLNUM, SN,
355 $ thresh, tmp, tnrm, wl, wu
356* ..
357* ..
358* .. External Functions ..
359 LOGICAL LSAME
360 REAL SLAMCH, SLANST, SROUNDUP_LWORK
361 EXTERNAL lsame, slamch, slanst, sroundup_lwork
362* ..
363* .. External Subroutines ..
364 EXTERNAL scopy, slae2, slaev2, slarrc, slarre,
365 $ slarrj,
367* ..
368* .. Intrinsic Functions ..
369 INTRINSIC max, min, sqrt
370* ..
371* .. Executable Statements ..
372*
373* Test the input parameters.
374*
375 wantz = lsame( jobz, 'V' )
376 alleig = lsame( range, 'A' )
377 valeig = lsame( range, 'V' )
378 indeig = lsame( range, 'I' )
379*
380 lquery = ( ( lwork.EQ.-1 ).OR.( liwork.EQ.-1 ) )
381 zquery = ( nzc.EQ.-1 )
382 laeswap = .false.
383
384* SSTEMR needs WORK of size 6*N, IWORK of size 3*N.
385* In addition, SLARRE needs WORK of size 6*N, IWORK of size 5*N.
386* Furthermore, SLARRV needs WORK of size 12*N, IWORK of size 7*N.
387 IF( wantz ) THEN
388 lwmin = 18*n
389 liwmin = 10*n
390 ELSE
391* need less workspace if only the eigenvalues are wanted
392 lwmin = 12*n
393 liwmin = 8*n
394 ENDIF
395
396 wl = zero
397 wu = zero
398 iil = 0
399 iiu = 0
400 nsplit = 0
401
402 IF( valeig ) THEN
403* We do not reference VL, VU in the cases RANGE = 'I','A'
404* The interval (WL, WU] contains all the wanted eigenvalues.
405* It is either given by the user or computed in SLARRE.
406 wl = vl
407 wu = vu
408 ELSEIF( indeig ) THEN
409* We do not reference IL, IU in the cases RANGE = 'V','A'
410 iil = il
411 iiu = iu
412 ENDIF
413*
414 info = 0
415 IF( .NOT.( wantz .OR. lsame( jobz, 'N' ) ) ) THEN
416 info = -1
417 ELSE IF( .NOT.( alleig .OR. valeig .OR. indeig ) ) THEN
418 info = -2
419 ELSE IF( n.LT.0 ) THEN
420 info = -3
421 ELSE IF( valeig .AND. n.GT.0 .AND. wu.LE.wl ) THEN
422 info = -7
423 ELSE IF( indeig .AND. ( iil.LT.1 .OR. iil.GT.n ) ) THEN
424 info = -8
425 ELSE IF( indeig .AND. ( iiu.LT.iil .OR. iiu.GT.n ) ) THEN
426 info = -9
427 ELSE IF( ldz.LT.1 .OR. ( wantz .AND. ldz.LT.n ) ) THEN
428 info = -13
429 ELSE IF( lwork.LT.lwmin .AND. .NOT.lquery ) THEN
430 info = -17
431 ELSE IF( liwork.LT.liwmin .AND. .NOT.lquery ) THEN
432 info = -19
433 END IF
434*
435* Get machine constants.
436*
437 safmin = slamch( 'Safe minimum' )
438 eps = slamch( 'Precision' )
439 smlnum = safmin / eps
440 bignum = one / smlnum
441 rmin = sqrt( smlnum )
442 rmax = min( sqrt( bignum ), one / sqrt( sqrt( safmin ) ) )
443*
444 IF( info.EQ.0 ) THEN
445 work( 1 ) = sroundup_lwork(lwmin)
446 iwork( 1 ) = liwmin
447*
448 IF( wantz .AND. alleig ) THEN
449 nzcmin = n
450 ELSE IF( wantz .AND. valeig ) THEN
451 CALL slarrc( 'T', n, vl, vu, d, e, safmin,
452 $ nzcmin, itmp, itmp2, info )
453 ELSE IF( wantz .AND. indeig ) THEN
454 nzcmin = iiu-iil+1
455 ELSE
456* WANTZ .EQ. FALSE.
457 nzcmin = 0
458 ENDIF
459 IF( zquery .AND. info.EQ.0 ) THEN
460 z( 1,1 ) = real( nzcmin )
461 ELSE IF( nzc.LT.nzcmin .AND. .NOT.zquery ) THEN
462 info = -14
463 END IF
464 END IF
465
466 IF( info.NE.0 ) THEN
467*
468 CALL xerbla( 'SSTEMR', -info )
469*
470 RETURN
471 ELSE IF( lquery .OR. zquery ) THEN
472 RETURN
473 END IF
474*
475* Handle N = 0, 1, and 2 cases immediately
476*
477 m = 0
478 IF( n.EQ.0 )
479 $ RETURN
480*
481 IF( n.EQ.1 ) THEN
482 IF( alleig .OR. indeig ) THEN
483 m = 1
484 w( 1 ) = d( 1 )
485 ELSE
486 IF( wl.LT.d( 1 ) .AND. wu.GE.d( 1 ) ) THEN
487 m = 1
488 w( 1 ) = d( 1 )
489 END IF
490 END IF
491 IF( wantz.AND.(.NOT.zquery) ) THEN
492 z( 1, 1 ) = one
493 isuppz(1) = 1
494 isuppz(2) = 1
495 END IF
496 RETURN
497 END IF
498*
499 IF( n.EQ.2 ) THEN
500 IF( .NOT.wantz ) THEN
501 CALL slae2( d(1), e(1), d(2), r1, r2 )
502 ELSE IF( wantz.AND.(.NOT.zquery) ) THEN
503 CALL slaev2( d(1), e(1), d(2), r1, r2, cs, sn )
504 END IF
505* D/S/LAE2 and D/S/LAEV2 outputs satisfy |R1| >= |R2|. However,
506* the following code requires R1 >= R2. Hence, we correct
507* the order of R1, R2, CS, SN if R1 < R2 before further processing.
508 IF( r1.LT.r2 ) THEN
509 e(2) = r1
510 r1 = r2
511 r2 = e(2)
512 laeswap = .true.
513 ENDIF
514 IF( alleig.OR.
515 $ (valeig.AND.(r2.GT.wl).AND.
516 $ (r2.LE.wu)).OR.
517 $ (indeig.AND.(iil.EQ.1)) ) THEN
518 m = m+1
519 w( m ) = r2
520 IF( wantz.AND.(.NOT.zquery) ) THEN
521 IF( laeswap ) THEN
522 z( 1, m ) = cs
523 z( 2, m ) = sn
524 ELSE
525 z( 1, m ) = -sn
526 z( 2, m ) = cs
527 ENDIF
528* Note: At most one of SN and CS can be zero.
529 IF (sn.NE.zero) THEN
530 IF (cs.NE.zero) THEN
531 isuppz(2*m-1) = 1
532 isuppz(2*m) = 2
533 ELSE
534 isuppz(2*m-1) = 1
535 isuppz(2*m) = 1
536 END IF
537 ELSE
538 isuppz(2*m-1) = 2
539 isuppz(2*m) = 2
540 END IF
541 ENDIF
542 ENDIF
543 IF( alleig.OR.
544 $ (valeig.AND.(r1.GT.wl).AND.
545 $ (r1.LE.wu)).OR.
546 $ (indeig.AND.(iiu.EQ.2)) ) THEN
547 m = m+1
548 w( m ) = r1
549 IF( wantz.AND.(.NOT.zquery) ) THEN
550 IF( laeswap ) THEN
551 z( 1, m ) = -sn
552 z( 2, m ) = cs
553 ELSE
554 z( 1, m ) = cs
555 z( 2, m ) = sn
556 ENDIF
557* Note: At most one of SN and CS can be zero.
558 IF (sn.NE.zero) THEN
559 IF (cs.NE.zero) THEN
560 isuppz(2*m-1) = 1
561 isuppz(2*m) = 2
562 ELSE
563 isuppz(2*m-1) = 1
564 isuppz(2*m) = 1
565 END IF
566 ELSE
567 isuppz(2*m-1) = 2
568 isuppz(2*m) = 2
569 END IF
570 ENDIF
571 ENDIF
572 ELSE
573
574* Continue with general N
575
576 indgrs = 1
577 inderr = 2*n + 1
578 indgp = 3*n + 1
579 indd = 4*n + 1
580 inde2 = 5*n + 1
581 indwrk = 6*n + 1
582*
583 iinspl = 1
584 iindbl = n + 1
585 iindw = 2*n + 1
586 iindwk = 3*n + 1
587*
588* Scale matrix to allowable range, if necessary.
589* The allowable range is related to the PIVMIN parameter; see the
590* comments in SLARRD. The preference for scaling small values
591* up is heuristic; we expect users' matrices not to be close to the
592* RMAX threshold.
593*
594 scale = one
595 tnrm = slanst( 'M', n, d, e )
596 IF( tnrm.GT.zero .AND. tnrm.LT.rmin ) THEN
597 scale = rmin / tnrm
598 ELSE IF( tnrm.GT.rmax ) THEN
599 scale = rmax / tnrm
600 END IF
601 IF( scale.NE.one ) THEN
602 CALL sscal( n, scale, d, 1 )
603 CALL sscal( n-1, scale, e, 1 )
604 tnrm = tnrm*scale
605 IF( valeig ) THEN
606* If eigenvalues in interval have to be found,
607* scale (WL, WU] accordingly
608 wl = wl*scale
609 wu = wu*scale
610 ENDIF
611 END IF
612*
613* Compute the desired eigenvalues of the tridiagonal after splitting
614* into smaller subblocks if the corresponding off-diagonal elements
615* are small
616* THRESH is the splitting parameter for SLARRE
617* A negative THRESH forces the old splitting criterion based on the
618* size of the off-diagonal. A positive THRESH switches to splitting
619* which preserves relative accuracy.
620*
621 IF( tryrac ) THEN
622* Test whether the matrix warrants the more expensive relative approach.
623 CALL slarrr( n, d, e, iinfo )
624 ELSE
625* The user does not care about relative accurately eigenvalues
626 iinfo = -1
627 ENDIF
628* Set the splitting criterion
629 IF (iinfo.EQ.0) THEN
630 thresh = eps
631 ELSE
632 thresh = -eps
633* relative accuracy is desired but T does not guarantee it
634 tryrac = .false.
635 ENDIF
636*
637 IF( tryrac ) THEN
638* Copy original diagonal, needed to guarantee relative accuracy
639 CALL scopy(n,d,1,work(indd),1)
640 ENDIF
641* Store the squares of the offdiagonal values of T
642 DO 5 j = 1, n-1
643 work( inde2+j-1 ) = e(j)**2
644 5 CONTINUE
645
646* Set the tolerance parameters for bisection
647 IF( .NOT.wantz ) THEN
648* SLARRE computes the eigenvalues to full precision.
649 rtol1 = four * eps
650 rtol2 = four * eps
651 ELSE
652* SLARRE computes the eigenvalues to less than full precision.
653* SLARRV will refine the eigenvalue approximations, and we can
654* need less accurate initial bisection in SLARRE.
655* Note: these settings do only affect the subset case and SLARRE
656 rtol1 = max( sqrt(eps)*5.0e-2, four * eps )
657 rtol2 = max( sqrt(eps)*5.0e-3, four * eps )
658 ENDIF
659 CALL slarre( range, n, wl, wu, iil, iiu, d, e,
660 $ work(inde2), rtol1, rtol2, thresh, nsplit,
661 $ iwork( iinspl ), m, w, work( inderr ),
662 $ work( indgp ), iwork( iindbl ),
663 $ iwork( iindw ), work( indgrs ), pivmin,
664 $ work( indwrk ), iwork( iindwk ), iinfo )
665 IF( iinfo.NE.0 ) THEN
666 info = 10 + abs( iinfo )
667 RETURN
668 END IF
669* Note that if RANGE .NE. 'V', SLARRE computes bounds on the desired
670* part of the spectrum. All desired eigenvalues are contained in
671* (WL,WU]
672
673
674 IF( wantz ) THEN
675*
676* Compute the desired eigenvectors corresponding to the computed
677* eigenvalues
678*
679 CALL slarrv( n, wl, wu, d, e,
680 $ pivmin, iwork( iinspl ), m,
681 $ 1, m, minrgp, rtol1, rtol2,
682 $ w, work( inderr ), work( indgp ), iwork( iindbl ),
683 $ iwork( iindw ), work( indgrs ), z, ldz,
684 $ isuppz, work( indwrk ), iwork( iindwk ), iinfo )
685 IF( iinfo.NE.0 ) THEN
686 info = 20 + abs( iinfo )
687 RETURN
688 END IF
689 ELSE
690* SLARRE computes eigenvalues of the (shifted) root representation
691* SLARRV returns the eigenvalues of the unshifted matrix.
692* However, if the eigenvectors are not desired by the user, we need
693* to apply the corresponding shifts from SLARRE to obtain the
694* eigenvalues of the original matrix.
695 DO 20 j = 1, m
696 itmp = iwork( iindbl+j-1 )
697 w( j ) = w( j ) + e( iwork( iinspl+itmp-1 ) )
698 20 CONTINUE
699 END IF
700*
701
702 IF ( tryrac ) THEN
703* Refine computed eigenvalues so that they are relatively accurate
704* with respect to the original matrix T.
705 ibegin = 1
706 wbegin = 1
707 DO 39 jblk = 1, iwork( iindbl+m-1 )
708 iend = iwork( iinspl+jblk-1 )
709 in = iend - ibegin + 1
710 wend = wbegin - 1
711* check if any eigenvalues have to be refined in this block
712 36 CONTINUE
713 IF( wend.LT.m ) THEN
714 IF( iwork( iindbl+wend ).EQ.jblk ) THEN
715 wend = wend + 1
716 GO TO 36
717 END IF
718 END IF
719 IF( wend.LT.wbegin ) THEN
720 ibegin = iend + 1
721 GO TO 39
722 END IF
723
724 offset = iwork(iindw+wbegin-1)-1
725 ifirst = iwork(iindw+wbegin-1)
726 ilast = iwork(iindw+wend-1)
727 rtol2 = four * eps
728 CALL slarrj( in,
729 $ work(indd+ibegin-1), work(inde2+ibegin-1),
730 $ ifirst, ilast, rtol2, offset, w(wbegin),
731 $ work( inderr+wbegin-1 ),
732 $ work( indwrk ), iwork( iindwk ), pivmin,
733 $ tnrm, iinfo )
734 ibegin = iend + 1
735 wbegin = wend + 1
736 39 CONTINUE
737 ENDIF
738*
739* If matrix was scaled, then rescale eigenvalues appropriately.
740*
741 IF( scale.NE.one ) THEN
742 CALL sscal( m, one / scale, w, 1 )
743 END IF
744 END IF
745*
746* If eigenvalues are not in increasing order, then sort them,
747* possibly along with eigenvectors.
748*
749 IF( nsplit.GT.1 .OR. n.EQ.2 ) THEN
750 IF( .NOT. wantz ) THEN
751 CALL slasrt( 'I', m, w, iinfo )
752 IF( iinfo.NE.0 ) THEN
753 info = 3
754 RETURN
755 END IF
756 ELSE
757 DO 60 j = 1, m - 1
758 i = 0
759 tmp = w( j )
760 DO 50 jj = j + 1, m
761 IF( w( jj ).LT.tmp ) THEN
762 i = jj
763 tmp = w( jj )
764 END IF
765 50 CONTINUE
766 IF( i.NE.0 ) THEN
767 w( i ) = w( j )
768 w( j ) = tmp
769 IF( wantz ) THEN
770 CALL sswap( n, z( 1, i ), 1, z( 1, j ), 1 )
771 itmp = isuppz( 2*i-1 )
772 isuppz( 2*i-1 ) = isuppz( 2*j-1 )
773 isuppz( 2*j-1 ) = itmp
774 itmp = isuppz( 2*i )
775 isuppz( 2*i ) = isuppz( 2*j )
776 isuppz( 2*j ) = itmp
777 END IF
778 END IF
779 60 CONTINUE
780 END IF
781 ENDIF
782*
783*
784 work( 1 ) = sroundup_lwork(lwmin)
785 iwork( 1 ) = liwmin
786 RETURN
787*
788* End of SSTEMR
789*
790 END
subroutine xerbla(srname, info)
Definition cblat2.f:3285
subroutine scopy(n, sx, incx, sy, incy)
SCOPY
Definition scopy.f:82
subroutine slae2(a, b, c, rt1, rt2)
SLAE2 computes the eigenvalues of a 2-by-2 symmetric matrix.
Definition slae2.f:100
subroutine slaev2(a, b, c, rt1, rt2, cs1, sn1)
SLAEV2 computes the eigenvalues and eigenvectors of a 2-by-2 symmetric/Hermitian matrix.
Definition slaev2.f:118
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 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 slarrj(n, d, e2, ifirst, ilast, rtol, offset, w, werr, work, iwork, pivmin, spdiam, info)
SLARRJ performs refinement of the initial estimates of the eigenvalues of the matrix T.
Definition slarrj.f:166
subroutine slarrr(n, d, e, info)
SLARRR performs tests to decide whether the symmetric tridiagonal matrix T warrants expensive computa...
Definition slarrr.f:92
subroutine slarrv(n, vl, vu, d, l, pivmin, isplit, m, dol, dou, minrgp, rtol1, rtol2, w, werr, wgap, iblock, indexw, gers, z, ldz, isuppz, work, iwork, info)
SLARRV computes the eigenvectors of the tridiagonal matrix T = L D LT given L, D and the eigenvalues ...
Definition slarrv.f:290
subroutine slasrt(id, n, d, info)
SLASRT sorts numbers in increasing or decreasing order.
Definition slasrt.f:86
subroutine sscal(n, sa, sx, incx)
SSCAL
Definition sscal.f:79
subroutine sstemr(jobz, range, n, d, e, vl, vu, il, iu, m, w, z, ldz, nzc, isuppz, tryrac, work, lwork, iwork, liwork, info)
SSTEMR
Definition sstemr.f:320
subroutine sswap(n, sx, incx, sy, incy)
SSWAP
Definition sswap.f:82