LAPACK 3.12.1
LAPACK: Linear Algebra PACKage
Loading...
Searching...
No Matches
cheevr_2stage.f
Go to the documentation of this file.
1*> \brief <b> CHEEVR_2STAGE computes the eigenvalues and, optionally, the left and/or right eigenvectors for HE matrices</b>
2*
3* @generated from zheevr_2stage.f, fortran z -> c, Sat Nov 5 23:18:11 2016
4*
5* =========== DOCUMENTATION ===========
6*
7* Online html documentation available at
8* http://www.netlib.org/lapack/explore-html/
9*
10*> Download CHEEVR_2STAGE + dependencies
11*> <a href="http://www.netlib.org/cgi-bin/netlibfiles.tgz?format=tgz&filename=/lapack/lapack_routine/cheevr_2stage.f">
12*> [TGZ]</a>
13*> <a href="http://www.netlib.org/cgi-bin/netlibfiles.zip?format=zip&filename=/lapack/lapack_routine/cheevr_2stage.f">
14*> [ZIP]</a>
15*> <a href="http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/cheevr_2stage.f">
16*> [TXT]</a>
17*
18* Definition:
19* ===========
20*
21* SUBROUTINE CHEEVR_2STAGE( JOBZ, RANGE, UPLO, N, A, LDA, VL, VU,
22* IL, IU, ABSTOL, M, W, Z, LDZ, ISUPPZ,
23* WORK, LWORK, RWORK, LRWORK, IWORK,
24* LIWORK, INFO )
25*
26* IMPLICIT NONE
27*
28* .. Scalar Arguments ..
29* CHARACTER JOBZ, RANGE, UPLO
30* INTEGER IL, INFO, IU, LDA, LDZ, LIWORK, LRWORK, LWORK,
31* $ M, N
32* REAL ABSTOL, VL, VU
33* ..
34* .. Array Arguments ..
35* INTEGER ISUPPZ( * ), IWORK( * )
36* REAL RWORK( * ), W( * )
37* COMPLEX A( LDA, * ), WORK( * ), Z( LDZ, * )
38* ..
39*
40*
41*> \par Purpose:
42* =============
43*>
44*> \verbatim
45*>
46*> CHEEVR_2STAGE computes selected eigenvalues and, optionally, eigenvectors
47*> of a complex Hermitian matrix A using the 2stage technique for
48*> the reduction to tridiagonal. Eigenvalues and eigenvectors can
49*> be selected by specifying either a range of values or a range of
50*> indices for the desired eigenvalues.
51*>
52*> CHEEVR_2STAGE first reduces the matrix A to tridiagonal form T with a call
53*> to CHETRD. Then, whenever possible, CHEEVR_2STAGE calls CSTEMR to compute
54*> eigenspectrum using Relatively Robust Representations. CSTEMR
55*> computes eigenvalues by the dqds algorithm, while orthogonal
56*> eigenvectors are computed from various "good" L D L^T representations
57*> (also known as Relatively Robust Representations). Gram-Schmidt
58*> orthogonalization is avoided as far as possible. More specifically,
59*> the various steps of the algorithm are as follows.
60*>
61*> For each unreduced block (submatrix) of T,
62*> (a) Compute T - sigma I = L D L^T, so that L and D
63*> define all the wanted eigenvalues to high relative accuracy.
64*> This means that small relative changes in the entries of D and L
65*> cause only small relative changes in the eigenvalues and
66*> eigenvectors. The standard (unfactored) representation of the
67*> tridiagonal matrix T does not have this property in general.
68*> (b) Compute the eigenvalues to suitable accuracy.
69*> If the eigenvectors are desired, the algorithm attains full
70*> accuracy of the computed eigenvalues only right before
71*> the corresponding vectors have to be computed, see steps c) and d).
72*> (c) For each cluster of close eigenvalues, select a new
73*> shift close to the cluster, find a new factorization, and refine
74*> the shifted eigenvalues to suitable accuracy.
75*> (d) For each eigenvalue with a large enough relative separation compute
76*> the corresponding eigenvector by forming a rank revealing twisted
77*> factorization. Go back to (c) for any clusters that remain.
78*>
79*> The desired accuracy of the output can be specified by the input
80*> parameter ABSTOL.
81*>
82*> For more details, see CSTEMR's documentation and:
83*> - Inderjit S. Dhillon and Beresford N. Parlett: "Multiple representations
84*> to compute orthogonal eigenvectors of symmetric tridiagonal matrices,"
85*> Linear Algebra and its Applications, 387(1), pp. 1-28, August 2004.
86*> - Inderjit Dhillon and Beresford Parlett: "Orthogonal Eigenvectors and
87*> Relative Gaps," SIAM Journal on Matrix Analysis and Applications, Vol. 25,
88*> 2004. Also LAPACK Working Note 154.
89*> - Inderjit Dhillon: "A new O(n^2) algorithm for the symmetric
90*> tridiagonal eigenvalue/eigenvector problem",
91*> Computer Science Division Technical Report No. UCB/CSD-97-971,
92*> UC Berkeley, May 1997.
93*>
94*>
95*> Note 1 : CHEEVR_2STAGE calls CSTEMR when the full spectrum is requested
96*> on machines which conform to the ieee-754 floating point standard.
97*> CHEEVR_2STAGE calls SSTEBZ and CSTEIN on non-ieee machines and
98*> when partial spectrum requests are made.
99*>
100*> Normal execution of CSTEMR may create NaNs and infinities and
101*> hence may abort due to a floating point exception in environments
102*> which do not handle NaNs and infinities in the ieee standard default
103*> manner.
104*> \endverbatim
105*
106* Arguments:
107* ==========
108*
109*> \param[in] JOBZ
110*> \verbatim
111*> JOBZ is CHARACTER*1
112*> = 'N': Compute eigenvalues only;
113*> = 'V': Compute eigenvalues and eigenvectors.
114*> Not available in this release.
115*> \endverbatim
116*>
117*> \param[in] RANGE
118*> \verbatim
119*> RANGE is CHARACTER*1
120*> = 'A': all eigenvalues will be found.
121*> = 'V': all eigenvalues in the half-open interval (VL,VU]
122*> will be found.
123*> = 'I': the IL-th through IU-th eigenvalues will be found.
124*> For RANGE = 'V' or 'I' and IU - IL < N - 1, SSTEBZ and
125*> CSTEIN are called
126*> \endverbatim
127*>
128*> \param[in] UPLO
129*> \verbatim
130*> UPLO is CHARACTER*1
131*> = 'U': Upper triangle of A is stored;
132*> = 'L': Lower triangle of A is stored.
133*> \endverbatim
134*>
135*> \param[in] N
136*> \verbatim
137*> N is INTEGER
138*> The order of the matrix A. N >= 0.
139*> \endverbatim
140*>
141*> \param[in,out] A
142*> \verbatim
143*> A is COMPLEX array, dimension (LDA, N)
144*> On entry, the Hermitian matrix A. If UPLO = 'U', the
145*> leading N-by-N upper triangular part of A contains the
146*> upper triangular part of the matrix A. If UPLO = 'L',
147*> the leading N-by-N lower triangular part of A contains
148*> the lower triangular part of the matrix A.
149*> On exit, the lower triangle (if UPLO='L') or the upper
150*> triangle (if UPLO='U') of A, including the diagonal, is
151*> destroyed.
152*> \endverbatim
153*>
154*> \param[in] LDA
155*> \verbatim
156*> LDA is INTEGER
157*> The leading dimension of the array A. LDA >= max(1,N).
158*> \endverbatim
159*>
160*> \param[in] VL
161*> \verbatim
162*> VL is REAL
163*> If RANGE='V', the lower bound of the interval to
164*> be searched for eigenvalues. VL < VU.
165*> Not referenced if RANGE = 'A' or 'I'.
166*> \endverbatim
167*>
168*> \param[in] VU
169*> \verbatim
170*> VU is REAL
171*> If RANGE='V', the upper bound of the interval to
172*> be searched for eigenvalues. VL < VU.
173*> Not referenced if RANGE = 'A' or 'I'.
174*> \endverbatim
175*>
176*> \param[in] IL
177*> \verbatim
178*> IL is INTEGER
179*> If RANGE='I', the index of the
180*> smallest eigenvalue to be returned.
181*> 1 <= IL <= IU <= N, if N > 0; IL = 1 and IU = 0 if N = 0.
182*> Not referenced if RANGE = 'A' or 'V'.
183*> \endverbatim
184*>
185*> \param[in] IU
186*> \verbatim
187*> IU is INTEGER
188*> If RANGE='I', the index of the
189*> largest eigenvalue to be returned.
190*> 1 <= IL <= IU <= N, if N > 0; IL = 1 and IU = 0 if N = 0.
191*> Not referenced if RANGE = 'A' or 'V'.
192*> \endverbatim
193*>
194*> \param[in] ABSTOL
195*> \verbatim
196*> ABSTOL is REAL
197*> The absolute error tolerance for the eigenvalues.
198*> An approximate eigenvalue is accepted as converged
199*> when it is determined to lie in an interval [a,b]
200*> of width less than or equal to
201*>
202*> ABSTOL + EPS * max( |a|,|b| ) ,
203*>
204*> where EPS is the machine precision. If ABSTOL is less than
205*> or equal to zero, then EPS*|T| will be used in its place,
206*> where |T| is the 1-norm of the tridiagonal matrix obtained
207*> by reducing A to tridiagonal form.
208*>
209*> See "Computing Small Singular Values of Bidiagonal Matrices
210*> with Guaranteed High Relative Accuracy," by Demmel and
211*> Kahan, LAPACK Working Note #3.
212*>
213*> If high relative accuracy is important, set ABSTOL to
214*> SLAMCH( 'Safe minimum' ). Doing so will guarantee that
215*> eigenvalues are computed to high relative accuracy when
216*> possible in future releases. The current code does not
217*> make any guarantees about high relative accuracy, but
218*> future releases will. See J. Barlow and J. Demmel,
219*> "Computing Accurate Eigensystems of Scaled Diagonally
220*> Dominant Matrices", LAPACK Working Note #7, for a discussion
221*> of which matrices define their eigenvalues to high relative
222*> accuracy.
223*> \endverbatim
224*>
225*> \param[out] M
226*> \verbatim
227*> M is INTEGER
228*> The total number of eigenvalues found. 0 <= M <= N.
229*> If RANGE = 'A', M = N, and if RANGE = 'I', M = IU-IL+1.
230*> \endverbatim
231*>
232*> \param[out] W
233*> \verbatim
234*> W is REAL array, dimension (N)
235*> The first M elements contain the selected eigenvalues in
236*> ascending order.
237*> \endverbatim
238*>
239*> \param[out] Z
240*> \verbatim
241*> Z is COMPLEX array, dimension (LDZ, max(1,M))
242*> If JOBZ = 'V', then if INFO = 0, the first M columns of Z
243*> contain the orthonormal eigenvectors of the matrix A
244*> corresponding to the selected eigenvalues, with the i-th
245*> column of Z holding the eigenvector associated with W(i).
246*> If JOBZ = 'N', then Z is not referenced.
247*> Note: the user must ensure that at least max(1,M) columns are
248*> supplied in the array Z; if RANGE = 'V', the exact value of M
249*> is not known in advance and an upper bound must be used.
250*> \endverbatim
251*>
252*> \param[in] LDZ
253*> \verbatim
254*> LDZ is INTEGER
255*> The leading dimension of the array Z. LDZ >= 1, and if
256*> JOBZ = 'V', LDZ >= max(1,N).
257*> \endverbatim
258*>
259*> \param[out] ISUPPZ
260*> \verbatim
261*> ISUPPZ is INTEGER array, dimension ( 2*max(1,M) )
262*> The support of the eigenvectors in Z, i.e., the indices
263*> indicating the nonzero elements in Z. The i-th eigenvector
264*> is nonzero only in elements ISUPPZ( 2*i-1 ) through
265*> ISUPPZ( 2*i ). This is an output of CSTEMR (tridiagonal
266*> matrix). The support of the eigenvectors of A is typically
267*> 1:N because of the unitary transformations applied by CUNMTR.
268*> Implemented only for RANGE = 'A' or 'I' and IU - IL = N - 1
269*> \endverbatim
270*>
271*> \param[out] WORK
272*> \verbatim
273*> WORK is COMPLEX array, dimension (MAX(1,LWORK))
274*> On exit, if INFO = 0, WORK(1) returns the optimal LWORK.
275*> \endverbatim
276*>
277*> \param[in] LWORK
278*> \verbatim
279*> LWORK is INTEGER
280*> The dimension of the array WORK.
281*> If N <= 1, LWORK must be at least 1.
282*> If JOBZ = 'N' and N > 1, LWORK must be queried.
283*> LWORK = MAX(1, 26*N, dimension) where
284*> dimension = max(stage1,stage2) + (KD+1)*N + N
285*> = N*KD + N*max(KD+1,FACTOPTNB)
286*> + max(2*KD*KD, KD*NTHREADS)
287*> + (KD+1)*N + N
288*> where KD is the blocking size of the reduction,
289*> FACTOPTNB is the blocking used by the QR or LQ
290*> algorithm, usually FACTOPTNB=128 is a good choice
291*> NTHREADS is the number of threads used when
292*> openMP compilation is enabled, otherwise =1.
293*> If JOBZ = 'V' and N > 1, LWORK must be queried. Not yet available
294*>
295*> If LWORK = -1, then a workspace query is assumed; the routine
296*> only calculates the optimal sizes of the WORK, RWORK and
297*> IWORK arrays, returns these values as the first entries of
298*> the WORK, RWORK and IWORK arrays, and no error message
299*> related to LWORK or LRWORK or LIWORK is issued by XERBLA.
300*> \endverbatim
301*>
302*> \param[out] RWORK
303*> \verbatim
304*> RWORK is REAL array, dimension (MAX(1,LRWORK))
305*> On exit, if INFO = 0, RWORK(1) returns the optimal
306*> (and minimal) LRWORK.
307*> \endverbatim
308*>
309*> \param[in] LRWORK
310*> \verbatim
311*> LRWORK is INTEGER
312*> The length of the array RWORK.
313*> If N <= 1, LRWORK >= 1, else LRWORK >= 24*N.
314*>
315*> If LRWORK = -1, then a workspace query is assumed; the
316*> routine only calculates the optimal sizes of the WORK, RWORK
317*> and IWORK arrays, returns these values as the first entries
318*> of the WORK, RWORK and IWORK arrays, and no error message
319*> related to LWORK or LRWORK or LIWORK is issued by XERBLA.
320*> \endverbatim
321*>
322*> \param[out] IWORK
323*> \verbatim
324*> IWORK is INTEGER array, dimension (MAX(1,LIWORK))
325*> On exit, if INFO = 0, IWORK(1) returns the optimal
326*> (and minimal) LIWORK.
327*> \endverbatim
328*>
329*> \param[in] LIWORK
330*> \verbatim
331*> LIWORK is INTEGER
332*> The dimension of the array IWORK.
333*> If N <= 1, LIWORK >= 1, else LIWORK >= 10*N.
334*>
335*> If LIWORK = -1, then a workspace query is assumed; the
336*> routine only calculates the optimal sizes of the WORK, RWORK
337*> and IWORK arrays, returns these values as the first entries
338*> of the WORK, RWORK and IWORK arrays, and no error message
339*> related to LWORK or LRWORK or LIWORK is issued by XERBLA.
340*> \endverbatim
341*>
342*> \param[out] INFO
343*> \verbatim
344*> INFO is INTEGER
345*> = 0: successful exit
346*> < 0: if INFO = -i, the i-th argument had an illegal value
347*> > 0: Internal error
348*> \endverbatim
349*
350* Authors:
351* ========
352*
353*> \author Univ. of Tennessee
354*> \author Univ. of California Berkeley
355*> \author Univ. of Colorado Denver
356*> \author NAG Ltd.
357*
358*> \ingroup heevr_2stage
359*
360*> \par Contributors:
361* ==================
362*>
363*> Inderjit Dhillon, IBM Almaden, USA \n
364*> Osni Marques, LBNL/NERSC, USA \n
365*> Ken Stanley, Computer Science Division, University of
366*> California at Berkeley, USA \n
367*> Jason Riedy, Computer Science Division, University of
368*> California at Berkeley, USA \n
369*>
370*> \par Further Details:
371* =====================
372*>
373*> \verbatim
374*>
375*> All details about the 2stage techniques are available in:
376*>
377*> Azzam Haidar, Hatem Ltaief, and Jack Dongarra.
378*> Parallel reduction to condensed forms for symmetric eigenvalue problems
379*> using aggregated fine-grained and memory-aware kernels. In Proceedings
380*> of 2011 International Conference for High Performance Computing,
381*> Networking, Storage and Analysis (SC '11), New York, NY, USA,
382*> Article 8 , 11 pages.
383*> http://doi.acm.org/10.1145/2063384.2063394
384*>
385*> A. Haidar, J. Kurzak, P. Luszczek, 2013.
386*> An improved parallel singular value algorithm and its implementation
387*> for multicore hardware, In Proceedings of 2013 International Conference
388*> for High Performance Computing, Networking, Storage and Analysis (SC '13).
389*> Denver, Colorado, USA, 2013.
390*> Article 90, 12 pages.
391*> http://doi.acm.org/10.1145/2503210.2503292
392*>
393*> A. Haidar, R. Solca, S. Tomov, T. Schulthess and J. Dongarra.
394*> A novel hybrid CPU-GPU generalized eigensolver for electronic structure
395*> calculations based on fine-grained memory aware tasks.
396*> International Journal of High Performance Computing Applications.
397*> Volume 28 Issue 2, Pages 196-209, May 2014.
398*> http://hpc.sagepub.com/content/28/2/196
399*>
400*> \endverbatim
401*
402* =====================================================================
403 SUBROUTINE cheevr_2stage( JOBZ, RANGE, UPLO, N, A, LDA, VL, VU,
404 $ IL, IU, ABSTOL, M, W, Z, LDZ, ISUPPZ,
405 $ WORK, LWORK, RWORK, LRWORK, IWORK,
406 $ LIWORK, INFO )
407*
408 IMPLICIT NONE
409*
410* -- LAPACK driver routine --
411* -- LAPACK is a software package provided by Univ. of Tennessee, --
412* -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..--
413*
414* .. Scalar Arguments ..
415 CHARACTER JOBZ, RANGE, UPLO
416 INTEGER IL, INFO, IU, LDA, LDZ, LIWORK, LRWORK, LWORK,
417 $ M, N
418 REAL ABSTOL, VL, VU
419* ..
420* .. Array Arguments ..
421 INTEGER ISUPPZ( * ), IWORK( * )
422 REAL RWORK( * ), W( * )
423 COMPLEX A( LDA, * ), WORK( * ), Z( LDZ, * )
424* ..
425*
426* =====================================================================
427*
428* .. Parameters ..
429 REAL ZERO, ONE, TWO
430 PARAMETER ( ZERO = 0.0e+0, one = 1.0e+0, two = 2.0e+0 )
431* ..
432* .. Local Scalars ..
433 LOGICAL ALLEIG, INDEIG, LOWER, LQUERY, TEST, VALEIG,
434 $ WANTZ, TRYRAC
435 CHARACTER ORDER
436 INTEGER I, IEEEOK, IINFO, IMAX, INDIBL, INDIFL, INDISP,
437 $ INDIWO, INDRD, INDRDD, INDRE, INDREE, INDRWK,
438 $ indtau, indwk, indwkn, iscale, itmp1, j, jj,
439 $ liwmin, llwork, llrwork, llwrkn, lrwmin,
440 $ lwmin, nsplit, lhtrd, lwtrd, kd, ib, indhous
441 REAL ABSTLL, ANRM, BIGNUM, EPS, RMAX, RMIN, SAFMIN,
442 $ SIGMA, SMLNUM, TMP1, VLL, VUU
443* ..
444* .. External Functions ..
445 LOGICAL LSAME
446 INTEGER ILAENV, ILAENV2STAGE
447 REAL SLAMCH, CLANSY, SROUNDUP_LWORK
448 EXTERNAL lsame, slamch, clansy, ilaenv, ilaenv2stage,
449 $ sroundup_lwork
450* ..
451* .. External Subroutines ..
452 EXTERNAL scopy, sscal, sstebz, ssterf, xerbla,
453 $ csscal,
455* ..
456* .. Intrinsic Functions ..
457 INTRINSIC real, max, min, sqrt
458* ..
459* .. Executable Statements ..
460*
461* Test the input parameters.
462*
463 ieeeok = ilaenv( 10, 'CHEEVR', 'N', 1, 2, 3, 4 )
464*
465 lower = lsame( uplo, 'L' )
466 wantz = lsame( jobz, 'V' )
467 alleig = lsame( range, 'A' )
468 valeig = lsame( range, 'V' )
469 indeig = lsame( range, 'I' )
470*
471 lquery = ( ( lwork.EQ.-1 ) .OR. ( lrwork.EQ.-1 ) .OR.
472 $ ( liwork.EQ.-1 ) )
473*
474 kd = ilaenv2stage( 1, 'CHETRD_2STAGE', jobz, n, -1, -1,
475 $ -1 )
476 ib = ilaenv2stage( 2, 'CHETRD_2STAGE', jobz, n, kd, -1,
477 $ -1 )
478 lhtrd = ilaenv2stage( 3, 'CHETRD_2STAGE', jobz, n, kd, ib,
479 $ -1 )
480 lwtrd = ilaenv2stage( 4, 'CHETRD_2STAGE', jobz, n, kd, ib,
481 $ -1 )
482*
483 IF( n.LE.1 ) THEN
484 lwmin = 1
485 lrwmin = 1
486 liwmin = 1
487 ELSE
488 lwmin = n + lhtrd + lwtrd
489 lrwmin = 24*n
490 liwmin = 10*n
491 END IF
492*
493 info = 0
494 IF( .NOT.( lsame( jobz, 'N' ) ) ) THEN
495 info = -1
496 ELSE IF( .NOT.( alleig .OR. valeig .OR. indeig ) ) THEN
497 info = -2
498 ELSE IF( .NOT.( lower .OR. lsame( uplo, 'U' ) ) ) THEN
499 info = -3
500 ELSE IF( n.LT.0 ) THEN
501 info = -4
502 ELSE IF( lda.LT.max( 1, n ) ) THEN
503 info = -6
504 ELSE
505 IF( valeig ) THEN
506 IF( n.GT.0 .AND. vu.LE.vl )
507 $ info = -8
508 ELSE IF( indeig ) THEN
509 IF( il.LT.1 .OR. il.GT.max( 1, n ) ) THEN
510 info = -9
511 ELSE IF( iu.LT.min( n, il ) .OR. iu.GT.n ) THEN
512 info = -10
513 END IF
514 END IF
515 END IF
516 IF( info.EQ.0 ) THEN
517 IF( ldz.LT.1 .OR. ( wantz .AND. ldz.LT.n ) ) THEN
518 info = -15
519 END IF
520 END IF
521*
522 IF( info.EQ.0 ) THEN
523 work( 1 ) = sroundup_lwork( lwmin )
524 rwork( 1 ) = sroundup_lwork( lrwmin )
525 iwork( 1 ) = liwmin
526*
527 IF( lwork.LT.lwmin .AND. .NOT.lquery ) THEN
528 info = -18
529 ELSE IF( lrwork.LT.lrwmin .AND. .NOT.lquery ) THEN
530 info = -20
531 ELSE IF( liwork.LT.liwmin .AND. .NOT.lquery ) THEN
532 info = -22
533 END IF
534 END IF
535*
536 IF( info.NE.0 ) THEN
537 CALL xerbla( 'CHEEVR_2STAGE', -info )
538 RETURN
539 ELSE IF( lquery ) THEN
540 RETURN
541 END IF
542*
543* Quick return if possible
544*
545 m = 0
546 IF( n.EQ.0 ) THEN
547 work( 1 ) = 1
548 RETURN
549 END IF
550*
551 IF( n.EQ.1 ) THEN
552 work( 1 ) = 1
553 IF( alleig .OR. indeig ) THEN
554 m = 1
555 w( 1 ) = real( a( 1, 1 ) )
556 ELSE
557 IF( vl.LT.real( a( 1, 1 ) ) .AND. vu.GE.real( a( 1, 1 ) ) )
558 $ THEN
559 m = 1
560 w( 1 ) = real( a( 1, 1 ) )
561 END IF
562 END IF
563 IF( wantz ) THEN
564 z( 1, 1 ) = one
565 isuppz( 1 ) = 1
566 isuppz( 2 ) = 1
567 END IF
568 RETURN
569 END IF
570*
571* Get machine constants.
572*
573 safmin = slamch( 'Safe minimum' )
574 eps = slamch( 'Precision' )
575 smlnum = safmin / eps
576 bignum = one / smlnum
577 rmin = sqrt( smlnum )
578 rmax = min( sqrt( bignum ), one / sqrt( sqrt( safmin ) ) )
579*
580* Scale matrix to allowable range, if necessary.
581*
582 iscale = 0
583 abstll = abstol
584 IF (valeig) THEN
585 vll = vl
586 vuu = vu
587 END IF
588 anrm = clansy( 'M', uplo, n, a, lda, rwork )
589 IF( anrm.GT.zero .AND. anrm.LT.rmin ) THEN
590 iscale = 1
591 sigma = rmin / anrm
592 ELSE IF( anrm.GT.rmax ) THEN
593 iscale = 1
594 sigma = rmax / anrm
595 END IF
596 IF( iscale.EQ.1 ) THEN
597 IF( lower ) THEN
598 DO 10 j = 1, n
599 CALL csscal( n-j+1, sigma, a( j, j ), 1 )
600 10 CONTINUE
601 ELSE
602 DO 20 j = 1, n
603 CALL csscal( j, sigma, a( 1, j ), 1 )
604 20 CONTINUE
605 END IF
606 IF( abstol.GT.0 )
607 $ abstll = abstol*sigma
608 IF( valeig ) THEN
609 vll = vl*sigma
610 vuu = vu*sigma
611 END IF
612 END IF
613
614* Initialize indices into workspaces. Note: The IWORK indices are
615* used only if SSTERF or CSTEMR fail.
616
617* WORK(INDTAU:INDTAU+N-1) stores the complex scalar factors of the
618* elementary reflectors used in CHETRD.
619 indtau = 1
620* INDWK is the starting offset of the remaining complex workspace,
621* and LLWORK is the remaining complex workspace size.
622 indhous = indtau + n
623 indwk = indhous + lhtrd
624 llwork = lwork - indwk + 1
625
626* RWORK(INDRD:INDRD+N-1) stores the real tridiagonal's diagonal
627* entries.
628 indrd = 1
629* RWORK(INDRE:INDRE+N-1) stores the off-diagonal entries of the
630* tridiagonal matrix from CHETRD.
631 indre = indrd + n
632* RWORK(INDRDD:INDRDD+N-1) is a copy of the diagonal entries over
633* -written by CSTEMR (the SSTERF path copies the diagonal to W).
634 indrdd = indre + n
635* RWORK(INDREE:INDREE+N-1) is a copy of the off-diagonal entries over
636* -written while computing the eigenvalues in SSTERF and CSTEMR.
637 indree = indrdd + n
638* INDRWK is the starting offset of the left-over real workspace, and
639* LLRWORK is the remaining workspace size.
640 indrwk = indree + n
641 llrwork = lrwork - indrwk + 1
642
643* IWORK(INDIBL:INDIBL+M-1) corresponds to IBLOCK in SSTEBZ and
644* stores the block indices of each of the M<=N eigenvalues.
645 indibl = 1
646* IWORK(INDISP:INDISP+NSPLIT-1) corresponds to ISPLIT in SSTEBZ and
647* stores the starting and finishing indices of each block.
648 indisp = indibl + n
649* IWORK(INDIFL:INDIFL+N-1) stores the indices of eigenvectors
650* that corresponding to eigenvectors that fail to converge in
651* CSTEIN. This information is discarded; if any fail, the driver
652* returns INFO > 0.
653 indifl = indisp + n
654* INDIWO is the offset of the remaining integer workspace.
655 indiwo = indifl + n
656
657*
658* Call CHETRD_2STAGE to reduce Hermitian matrix to tridiagonal form.
659*
660 CALL chetrd_2stage( jobz, uplo, n, a, lda, rwork( indrd ),
661 $ rwork( indre ), work( indtau ),
662 $ work( indhous ), lhtrd,
663 $ work( indwk ), llwork, iinfo )
664*
665* If all eigenvalues are desired
666* then call SSTERF or CSTEMR and CUNMTR.
667*
668 test = .false.
669 IF( indeig ) THEN
670 IF( il.EQ.1 .AND. iu.EQ.n ) THEN
671 test = .true.
672 END IF
673 END IF
674 IF( ( alleig.OR.test ) .AND. ( ieeeok.EQ.1 ) ) THEN
675 IF( .NOT.wantz ) THEN
676 CALL scopy( n, rwork( indrd ), 1, w, 1 )
677 CALL scopy( n-1, rwork( indre ), 1, rwork( indree ), 1 )
678 CALL ssterf( n, w, rwork( indree ), info )
679 ELSE
680 CALL scopy( n-1, rwork( indre ), 1, rwork( indree ), 1 )
681 CALL scopy( n, rwork( indrd ), 1, rwork( indrdd ), 1 )
682*
683 IF ( abstol .LE. two*real( n )*eps ) THEN
684 tryrac = .true.
685 ELSE
686 tryrac = .false.
687 END IF
688 CALL cstemr( jobz, 'A', n, rwork( indrdd ),
689 $ rwork( indree ), vl, vu, il, iu, m, w,
690 $ z, ldz, n, isuppz, tryrac,
691 $ rwork( indrwk ), llrwork,
692 $ iwork, liwork, info )
693*
694* Apply unitary matrix used in reduction to tridiagonal
695* form to eigenvectors returned by CSTEMR.
696*
697 IF( wantz .AND. info.EQ.0 ) THEN
698 indwkn = indwk
699 llwrkn = lwork - indwkn + 1
700 CALL cunmtr( 'L', uplo, 'N', n, m, a, lda,
701 $ work( indtau ), z, ldz, work( indwkn ),
702 $ llwrkn, iinfo )
703 END IF
704 END IF
705*
706*
707 IF( info.EQ.0 ) THEN
708 m = n
709 GO TO 30
710 END IF
711 info = 0
712 END IF
713*
714* Otherwise, call SSTEBZ and, if eigenvectors are desired, CSTEIN.
715* Also call SSTEBZ and CSTEIN if CSTEMR fails.
716*
717 IF( wantz ) THEN
718 order = 'B'
719 ELSE
720 order = 'E'
721 END IF
722
723 CALL sstebz( range, order, n, vll, vuu, il, iu, abstll,
724 $ rwork( indrd ), rwork( indre ), m, nsplit, w,
725 $ iwork( indibl ), iwork( indisp ), rwork( indrwk ),
726 $ iwork( indiwo ), info )
727*
728 IF( wantz ) THEN
729 CALL cstein( n, rwork( indrd ), rwork( indre ), m, w,
730 $ iwork( indibl ), iwork( indisp ), z, ldz,
731 $ rwork( indrwk ), iwork( indiwo ), iwork( indifl ),
732 $ info )
733*
734* Apply unitary matrix used in reduction to tridiagonal
735* form to eigenvectors returned by CSTEIN.
736*
737 indwkn = indwk
738 llwrkn = lwork - indwkn + 1
739 CALL cunmtr( 'L', uplo, 'N', n, m, a, lda, work( indtau ),
740 $ z,
741 $ ldz, work( indwkn ), llwrkn, iinfo )
742 END IF
743*
744* If matrix was scaled, then rescale eigenvalues appropriately.
745*
746 30 CONTINUE
747 IF( iscale.EQ.1 ) THEN
748 IF( info.EQ.0 ) THEN
749 imax = m
750 ELSE
751 imax = info - 1
752 END IF
753 CALL sscal( imax, one / sigma, w, 1 )
754 END IF
755*
756* If eigenvalues are not in order, then sort them, along with
757* eigenvectors.
758*
759 IF( wantz ) THEN
760 DO 50 j = 1, m - 1
761 i = 0
762 tmp1 = w( j )
763 DO 40 jj = j + 1, m
764 IF( w( jj ).LT.tmp1 ) THEN
765 i = jj
766 tmp1 = w( jj )
767 END IF
768 40 CONTINUE
769*
770 IF( i.NE.0 ) THEN
771 itmp1 = iwork( indibl+i-1 )
772 w( i ) = w( j )
773 iwork( indibl+i-1 ) = iwork( indibl+j-1 )
774 w( j ) = tmp1
775 iwork( indibl+j-1 ) = itmp1
776 CALL cswap( n, z( 1, i ), 1, z( 1, j ), 1 )
777 END IF
778 50 CONTINUE
779 END IF
780*
781* Set WORK(1) to optimal workspace size.
782*
783 work( 1 ) = sroundup_lwork( lwmin )
784 rwork( 1 ) = sroundup_lwork( lrwmin )
785 iwork( 1 ) = liwmin
786*
787 RETURN
788*
789* End of CHEEVR_2STAGE
790*
791 END
subroutine xerbla(srname, info)
Definition cblat2.f:3285
subroutine scopy(n, sx, incx, sy, incy)
SCOPY
Definition scopy.f:82
subroutine cheevr_2stage(jobz, range, uplo, n, a, lda, vl, vu, il, iu, abstol, m, w, z, ldz, isuppz, work, lwork, rwork, lrwork, iwork, liwork, info)
CHEEVR_2STAGE computes the eigenvalues and, optionally, the left and/or right eigenvectors for HE mat...
subroutine chetrd_2stage(vect, uplo, n, a, lda, d, e, tau, hous2, lhous2, work, lwork, info)
CHETRD_2STAGE
subroutine csscal(n, sa, cx, incx)
CSSCAL
Definition csscal.f:78
subroutine sscal(n, sa, sx, incx)
SSCAL
Definition sscal.f:79
subroutine sstebz(range, order, n, vl, vu, il, iu, abstol, d, e, m, nsplit, w, iblock, isplit, work, iwork, info)
SSTEBZ
Definition sstebz.f:272
subroutine cstein(n, d, e, m, w, iblock, isplit, z, ldz, work, iwork, ifail, info)
CSTEIN
Definition cstein.f:180
subroutine cstemr(jobz, range, n, d, e, vl, vu, il, iu, m, w, z, ldz, nzc, isuppz, tryrac, work, lwork, iwork, liwork, info)
CSTEMR
Definition cstemr.f:337
subroutine ssterf(n, d, e, info)
SSTERF
Definition ssterf.f:84
subroutine cswap(n, cx, incx, cy, incy)
CSWAP
Definition cswap.f:81
subroutine cunmtr(side, uplo, trans, m, n, a, lda, tau, c, ldc, work, lwork, info)
CUNMTR
Definition cunmtr.f:171