1*> \brief \b ZHEGVD
2*
3*  =========== DOCUMENTATION ===========
4*
5* Online html documentation available at
6*            http://www.netlib.org/lapack/explore-html/
7*
8*> \htmlonly
9*> Download ZHEGVD + dependencies
10*> <a href="http://www.netlib.org/cgi-bin/netlibfiles.tgz?format=tgz&filename=/lapack/lapack_routine/zhegvd.f">
11*> [TGZ]</a>
12*> <a href="http://www.netlib.org/cgi-bin/netlibfiles.zip?format=zip&filename=/lapack/lapack_routine/zhegvd.f">
13*> [ZIP]</a>
14*> <a href="http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/zhegvd.f">
15*> [TXT]</a>
16*> \endhtmlonly
17*
18*  Definition:
19*  ===========
20*
21*       SUBROUTINE ZHEGVD( ITYPE, JOBZ, UPLO, N, A, LDA, B, LDB, W, WORK,
22*                          LWORK, RWORK, LRWORK, IWORK, LIWORK, INFO )
23*
24*       .. Scalar Arguments ..
25*       CHARACTER          JOBZ, UPLO
26*       INTEGER            INFO, ITYPE, LDA, LDB, LIWORK, LRWORK, LWORK, N
27*       ..
28*       .. Array Arguments ..
29*       INTEGER            IWORK( * )
30*       DOUBLE PRECISION   RWORK( * ), W( * )
31*       COMPLEX*16         A( LDA, * ), B( LDB, * ), WORK( * )
32*       ..
33*
34*
35*> \par Purpose:
36*  =============
37*>
38*> \verbatim
39*>
40*> ZHEGVD computes all the eigenvalues, and optionally, the eigenvectors
41*> of a complex generalized Hermitian-definite eigenproblem, of the form
42*> A*x=(lambda)*B*x,  A*Bx=(lambda)*x,  or B*A*x=(lambda)*x.  Here A and
43*> B are assumed to be Hermitian and B is also positive definite.
44*> If eigenvectors are desired, it uses a divide and conquer algorithm.
45*>
46*> The divide and conquer algorithm makes very mild assumptions about
47*> floating point arithmetic. It will work on machines with a guard
48*> digit in add/subtract, or on those binary machines without guard
49*> digits which subtract like the Cray X-MP, Cray Y-MP, Cray C-90, or
50*> Cray-2. It could conceivably fail on hexadecimal or decimal machines
51*> without guard digits, but we know of none.
52*> \endverbatim
53*
54*  Arguments:
55*  ==========
56*
57*> \param[in] ITYPE
58*> \verbatim
59*>          ITYPE is INTEGER
60*>          Specifies the problem type to be solved:
61*>          = 1:  A*x = (lambda)*B*x
62*>          = 2:  A*B*x = (lambda)*x
63*>          = 3:  B*A*x = (lambda)*x
64*> \endverbatim
65*>
66*> \param[in] JOBZ
67*> \verbatim
68*>          JOBZ is CHARACTER*1
69*>          = 'N':  Compute eigenvalues only;
70*>          = 'V':  Compute eigenvalues and eigenvectors.
71*> \endverbatim
72*>
73*> \param[in] UPLO
74*> \verbatim
75*>          UPLO is CHARACTER*1
76*>          = 'U':  Upper triangles of A and B are stored;
77*>          = 'L':  Lower triangles of A and B are stored.
78*> \endverbatim
79*>
80*> \param[in] N
81*> \verbatim
82*>          N is INTEGER
83*>          The order of the matrices A and B.  N >= 0.
84*> \endverbatim
85*>
86*> \param[in,out] A
87*> \verbatim
88*>          A is COMPLEX*16 array, dimension (LDA, N)
89*>          On entry, the Hermitian matrix A.  If UPLO = 'U', the
90*>          leading N-by-N upper triangular part of A contains the
91*>          upper triangular part of the matrix A.  If UPLO = 'L',
92*>          the leading N-by-N lower triangular part of A contains
93*>          the lower triangular part of the matrix A.
94*>
95*>          On exit, if JOBZ = 'V', then if INFO = 0, A contains the
96*>          matrix Z of eigenvectors.  The eigenvectors are normalized
97*>          as follows:
98*>          if ITYPE = 1 or 2, Z**H*B*Z = I;
99*>          if ITYPE = 3, Z**H*inv(B)*Z = I.
100*>          If JOBZ = 'N', then on exit the upper triangle (if UPLO='U')
101*>          or the lower triangle (if UPLO='L') of A, including the
102*>          diagonal, is destroyed.
103*> \endverbatim
104*>
105*> \param[in] LDA
106*> \verbatim
107*>          LDA is INTEGER
108*>          The leading dimension of the array A.  LDA >= max(1,N).
109*> \endverbatim
110*>
111*> \param[in,out] B
112*> \verbatim
113*>          B is COMPLEX*16 array, dimension (LDB, N)
114*>          On entry, the Hermitian matrix B.  If UPLO = 'U', the
115*>          leading N-by-N upper triangular part of B contains the
116*>          upper triangular part of the matrix B.  If UPLO = 'L',
117*>          the leading N-by-N lower triangular part of B contains
118*>          the lower triangular part of the matrix B.
119*>
120*>          On exit, if INFO <= N, the part of B containing the matrix is
121*>          overwritten by the triangular factor U or L from the Cholesky
122*>          factorization B = U**H*U or B = L*L**H.
123*> \endverbatim
124*>
125*> \param[in] LDB
126*> \verbatim
127*>          LDB is INTEGER
128*>          The leading dimension of the array B.  LDB >= max(1,N).
129*> \endverbatim
130*>
131*> \param[out] W
132*> \verbatim
133*>          W is DOUBLE PRECISION array, dimension (N)
134*>          If INFO = 0, the eigenvalues in ascending order.
135*> \endverbatim
136*>
137*> \param[out] WORK
138*> \verbatim
139*>          WORK is COMPLEX*16 array, dimension (MAX(1,LWORK))
140*>          On exit, if INFO = 0, WORK(1) returns the optimal LWORK.
141*> \endverbatim
142*>
143*> \param[in] LWORK
144*> \verbatim
145*>          LWORK is INTEGER
146*>          The length of the array WORK.
147*>          If N <= 1,                LWORK >= 1.
148*>          If JOBZ  = 'N' and N > 1, LWORK >= N + 1.
149*>          If JOBZ  = 'V' and N > 1, LWORK >= 2*N + N**2.
150*>
151*>          If LWORK = -1, then a workspace query is assumed; the routine
152*>          only calculates the optimal sizes of the WORK, RWORK and
153*>          IWORK arrays, returns these values as the first entries of
154*>          the WORK, RWORK and IWORK arrays, and no error message
155*>          related to LWORK or LRWORK or LIWORK is issued by XERBLA.
156*> \endverbatim
157*>
158*> \param[out] RWORK
159*> \verbatim
160*>          RWORK is DOUBLE PRECISION array, dimension (MAX(1,LRWORK))
161*>          On exit, if INFO = 0, RWORK(1) returns the optimal LRWORK.
162*> \endverbatim
163*>
164*> \param[in] LRWORK
165*> \verbatim
166*>          LRWORK is INTEGER
167*>          The dimension of the array RWORK.
168*>          If N <= 1,                LRWORK >= 1.
169*>          If JOBZ  = 'N' and N > 1, LRWORK >= N.
170*>          If JOBZ  = 'V' and N > 1, LRWORK >= 1 + 5*N + 2*N**2.
171*>
172*>          If LRWORK = -1, then a workspace query is assumed; the
173*>          routine only calculates the optimal sizes of the WORK, RWORK
174*>          and IWORK arrays, returns these values as the first entries
175*>          of the WORK, RWORK and IWORK arrays, and no error message
176*>          related to LWORK or LRWORK or LIWORK is issued by XERBLA.
177*> \endverbatim
178*>
179*> \param[out] IWORK
180*> \verbatim
181*>          IWORK is INTEGER array, dimension (MAX(1,LIWORK))
182*>          On exit, if INFO = 0, IWORK(1) returns the optimal LIWORK.
183*> \endverbatim
184*>
185*> \param[in] LIWORK
186*> \verbatim
187*>          LIWORK is INTEGER
188*>          The dimension of the array IWORK.
189*>          If N <= 1,                LIWORK >= 1.
190*>          If JOBZ  = 'N' and N > 1, LIWORK >= 1.
191*>          If JOBZ  = 'V' and N > 1, LIWORK >= 3 + 5*N.
192*>
193*>          If LIWORK = -1, then a workspace query is assumed; the
194*>          routine only calculates the optimal sizes of the WORK, RWORK
195*>          and IWORK arrays, returns these values as the first entries
196*>          of the WORK, RWORK and IWORK arrays, and no error message
197*>          related to LWORK or LRWORK or LIWORK is issued by XERBLA.
198*> \endverbatim
199*>
200*> \param[out] INFO
201*> \verbatim
202*>          INFO is INTEGER
203*>          = 0:  successful exit
204*>          < 0:  if INFO = -i, the i-th argument had an illegal value
205*>          > 0:  ZPOTRF or ZHEEVD returned an error code:
206*>             <= N:  if INFO = i and JOBZ = 'N', then the algorithm
207*>                    failed to converge; i off-diagonal elements of an
208*>                    intermediate tridiagonal form did not converge to
209*>                    zero;
210*>                    if INFO = i and JOBZ = 'V', then the algorithm
211*>                    failed to compute an eigenvalue while working on
212*>                    the submatrix lying in rows and columns INFO/(N+1)
213*>                    through mod(INFO,N+1);
214*>             > N:   if INFO = N + i, for 1 <= i <= N, then the leading
215*>                    minor of order i of B is not positive definite.
216*>                    The factorization of B could not be completed and
217*>                    no eigenvalues or eigenvectors were computed.
218*> \endverbatim
219*
220*  Authors:
221*  ========
222*
223*> \author Univ. of Tennessee
224*> \author Univ. of California Berkeley
225*> \author Univ. of Colorado Denver
226*> \author NAG Ltd.
227*
228*> \ingroup complex16HEeigen
229*
230*> \par Further Details:
231*  =====================
232*>
233*> \verbatim
234*>
235*>  Modified so that no backsubstitution is performed if ZHEEVD fails to
236*>  converge (NEIG in old code could be greater than N causing out of
237*>  bounds reference to A - reported by Ralf Meyer).  Also corrected the
238*>  description of INFO and the test on ITYPE. Sven, 16 Feb 05.
239*> \endverbatim
240*
241*> \par Contributors:
242*  ==================
243*>
244*>     Mark Fahey, Department of Mathematics, Univ. of Kentucky, USA
245*>
246*  =====================================================================
247      SUBROUTINE ZHEGVD( ITYPE, JOBZ, UPLO, N, A, LDA, B, LDB, W, WORK,
248     $                   LWORK, RWORK, LRWORK, IWORK, LIWORK, INFO )
249*
250*  -- LAPACK driver routine --
251*  -- LAPACK is a software package provided by Univ. of Tennessee,    --
252*  -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..--
253*
254*     .. Scalar Arguments ..
255      CHARACTER          JOBZ, UPLO
256      INTEGER            INFO, ITYPE, LDA, LDB, LIWORK, LRWORK, LWORK, N
257*     ..
258*     .. Array Arguments ..
259      INTEGER            IWORK( * )
260      DOUBLE PRECISION   RWORK( * ), W( * )
261      COMPLEX*16         A( LDA, * ), B( LDB, * ), WORK( * )
262*     ..
263*
264*  =====================================================================
265*
266*     .. Parameters ..
267      COMPLEX*16         CONE
268      PARAMETER          ( CONE = ( 1.0D+0, 0.0D+0 ) )
269*     ..
270*     .. Local Scalars ..
271      LOGICAL            LQUERY, UPPER, WANTZ
272      CHARACTER          TRANS
273      INTEGER            LIOPT, LIWMIN, LOPT, LROPT, LRWMIN, LWMIN
274*     ..
275*     .. External Functions ..
276      LOGICAL            LSAME
277      EXTERNAL           LSAME
278*     ..
279*     .. External Subroutines ..
280      EXTERNAL           XERBLA, ZHEEVD, ZHEGST, ZPOTRF, ZTRMM, ZTRSM
281*     ..
282*     .. Intrinsic Functions ..
283      INTRINSIC          DBLE, MAX
284*     ..
285*     .. Executable Statements ..
286*
287*     Test the input parameters.
288*
289      WANTZ = LSAME( JOBZ, 'V' )
290      UPPER = LSAME( UPLO, 'U' )
291      LQUERY = ( LWORK.EQ.-1 .OR. LRWORK.EQ.-1 .OR. LIWORK.EQ.-1 )
292*
293      INFO = 0
294      IF( N.LE.1 ) THEN
295         LWMIN = 1
296         LRWMIN = 1
297         LIWMIN = 1
298      ELSE IF( WANTZ ) THEN
299         LWMIN = 2*N + N*N
300         LRWMIN = 1 + 5*N + 2*N*N
301         LIWMIN = 3 + 5*N
302      ELSE
303         LWMIN = N + 1
304         LRWMIN = N
305         LIWMIN = 1
306      END IF
307      LOPT = LWMIN
308      LROPT = LRWMIN
309      LIOPT = LIWMIN
310      IF( ITYPE.LT.1 .OR. ITYPE.GT.3 ) THEN
311         INFO = -1
312      ELSE IF( .NOT.( WANTZ .OR. LSAME( JOBZ, 'N' ) ) ) THEN
313         INFO = -2
314      ELSE IF( .NOT.( UPPER .OR. LSAME( UPLO, 'L' ) ) ) THEN
315         INFO = -3
316      ELSE IF( N.LT.0 ) THEN
317         INFO = -4
318      ELSE IF( LDA.LT.MAX( 1, N ) ) THEN
319         INFO = -6
320      ELSE IF( LDB.LT.MAX( 1, N ) ) THEN
321         INFO = -8
322      END IF
323*
324      IF( INFO.EQ.0 ) THEN
325         WORK( 1 ) = LOPT
326         RWORK( 1 ) = LROPT
327         IWORK( 1 ) = LIOPT
328*
329         IF( LWORK.LT.LWMIN .AND. .NOT.LQUERY ) THEN
330            INFO = -11
331         ELSE IF( LRWORK.LT.LRWMIN .AND. .NOT.LQUERY ) THEN
332            INFO = -13
333         ELSE IF( LIWORK.LT.LIWMIN .AND. .NOT.LQUERY ) THEN
334            INFO = -15
335         END IF
336      END IF
337*
338      IF( INFO.NE.0 ) THEN
339         CALL XERBLA( 'ZHEGVD', -INFO )
340         RETURN
341      ELSE IF( LQUERY ) THEN
342         RETURN
343      END IF
344*
345*     Quick return if possible
346*
347      IF( N.EQ.0 )
348     $   RETURN
349*
350*     Form a Cholesky factorization of B.
351*
352      CALL ZPOTRF( UPLO, N, B, LDB, INFO )
353      IF( INFO.NE.0 ) THEN
354         INFO = N + INFO
355         RETURN
356      END IF
357*
358*     Transform problem to standard eigenvalue problem and solve.
359*
360      CALL ZHEGST( ITYPE, UPLO, N, A, LDA, B, LDB, INFO )
361      CALL ZHEEVD( JOBZ, UPLO, N, A, LDA, W, WORK, LWORK, RWORK, LRWORK,
362     $             IWORK, LIWORK, INFO )
363      LOPT = MAX( DBLE( LOPT ), DBLE( WORK( 1 ) ) )
364      LROPT = MAX( DBLE( LROPT ), DBLE( RWORK( 1 ) ) )
365      LIOPT = MAX( DBLE( LIOPT ), DBLE( IWORK( 1 ) ) )
366*
367      IF( WANTZ .AND. INFO.EQ.0 ) THEN
368*
369*        Backtransform eigenvectors to the original problem.
370*
371         IF( ITYPE.EQ.1 .OR. ITYPE.EQ.2 ) THEN
372*
373*           For A*x=(lambda)*B*x and A*B*x=(lambda)*x;
374*           backtransform eigenvectors: x = inv(L)**H *y or inv(U)*y
375*
376            IF( UPPER ) THEN
377               TRANS = 'N'
378            ELSE
379               TRANS = 'C'
380            END IF
381*
382            CALL ZTRSM( 'Left', UPLO, TRANS, 'Non-unit', N, N, CONE,
383     $                  B, LDB, A, LDA )
384*
385         ELSE IF( ITYPE.EQ.3 ) THEN
386*
387*           For B*A*x=(lambda)*x;
388*           backtransform eigenvectors: x = L*y or U**H *y
389*
390            IF( UPPER ) THEN
391               TRANS = 'C'
392            ELSE
393               TRANS = 'N'
394            END IF
395*
396            CALL ZTRMM( 'Left', UPLO, TRANS, 'Non-unit', N, N, CONE,
397     $                  B, LDB, A, LDA )
398         END IF
399      END IF
400*
401      WORK( 1 ) = LOPT
402      RWORK( 1 ) = LROPT
403      IWORK( 1 ) = LIOPT
404*
405      RETURN
406*
407*     End of ZHEGVD
408*
409      END
410