1*> \brief <b> CGEES computes the eigenvalues, the Schur form, and, optionally, the matrix of Schur vectors for GE matrices</b>
2*
3*  =========== DOCUMENTATION ===========
4*
5* Online html documentation available at
6*            http://www.netlib.org/lapack/explore-html/
7*
8*> \htmlonly
9*> Download CGEES + dependencies
10*> <a href="http://www.netlib.org/cgi-bin/netlibfiles.tgz?format=tgz&filename=/lapack/lapack_routine/cgees.f">
11*> [TGZ]</a>
12*> <a href="http://www.netlib.org/cgi-bin/netlibfiles.zip?format=zip&filename=/lapack/lapack_routine/cgees.f">
13*> [ZIP]</a>
14*> <a href="http://www.netlib.org/cgi-bin/netlibfiles.txt?format=txt&filename=/lapack/lapack_routine/cgees.f">
15*> [TXT]</a>
16*> \endhtmlonly
17*
18*  Definition:
19*  ===========
20*
21*       SUBROUTINE CGEES( JOBVS, SORT, SELECT, N, A, LDA, SDIM, W, VS,
22*                         LDVS, WORK, LWORK, RWORK, BWORK, INFO )
23*
24*       .. Scalar Arguments ..
25*       CHARACTER          JOBVS, SORT
26*       INTEGER            INFO, LDA, LDVS, LWORK, N, SDIM
27*       ..
28*       .. Array Arguments ..
29*       LOGICAL            BWORK( * )
30*       REAL               RWORK( * )
31*       COMPLEX            A( LDA, * ), VS( LDVS, * ), W( * ), WORK( * )
32*       ..
33*       .. Function Arguments ..
34*       LOGICAL            SELECT
35*       EXTERNAL           SELECT
36*       ..
37*
38*
39*> \par Purpose:
40*  =============
41*>
42*> \verbatim
43*>
44*> CGEES computes for an N-by-N complex nonsymmetric matrix A, the
45*> eigenvalues, the Schur form T, and, optionally, the matrix of Schur
46*> vectors Z.  This gives the Schur factorization A = Z*T*(Z**H).
47*>
48*> Optionally, it also orders the eigenvalues on the diagonal of the
49*> Schur form so that selected eigenvalues are at the top left.
50*> The leading columns of Z then form an orthonormal basis for the
51*> invariant subspace corresponding to the selected eigenvalues.
52*>
53*> A complex matrix is in Schur form if it is upper triangular.
54*> \endverbatim
55*
56*  Arguments:
57*  ==========
58*
59*> \param[in] JOBVS
60*> \verbatim
61*>          JOBVS is CHARACTER*1
62*>          = 'N': Schur vectors are not computed;
63*>          = 'V': Schur vectors are computed.
64*> \endverbatim
65*>
66*> \param[in] SORT
67*> \verbatim
68*>          SORT is CHARACTER*1
69*>          Specifies whether or not to order the eigenvalues on the
70*>          diagonal of the Schur form.
71*>          = 'N': Eigenvalues are not ordered:
72*>          = 'S': Eigenvalues are ordered (see SELECT).
73*> \endverbatim
74*>
75*> \param[in] SELECT
76*> \verbatim
77*>          SELECT is a LOGICAL FUNCTION of one COMPLEX argument
78*>          SELECT must be declared EXTERNAL in the calling subroutine.
79*>          If SORT = 'S', SELECT is used to select eigenvalues to order
80*>          to the top left of the Schur form.
81*>          IF SORT = 'N', SELECT is not referenced.
82*>          The eigenvalue W(j) is selected if SELECT(W(j)) is true.
83*> \endverbatim
84*>
85*> \param[in] N
86*> \verbatim
87*>          N is INTEGER
88*>          The order of the matrix A. N >= 0.
89*> \endverbatim
90*>
91*> \param[in,out] A
92*> \verbatim
93*>          A is COMPLEX array, dimension (LDA,N)
94*>          On entry, the N-by-N matrix A.
95*>          On exit, A has been overwritten by its Schur form T.
96*> \endverbatim
97*>
98*> \param[in] LDA
99*> \verbatim
100*>          LDA is INTEGER
101*>          The leading dimension of the array A.  LDA >= max(1,N).
102*> \endverbatim
103*>
104*> \param[out] SDIM
105*> \verbatim
106*>          SDIM is INTEGER
107*>          If SORT = 'N', SDIM = 0.
108*>          If SORT = 'S', SDIM = number of eigenvalues for which
109*>                         SELECT is true.
110*> \endverbatim
111*>
112*> \param[out] W
113*> \verbatim
114*>          W is COMPLEX array, dimension (N)
115*>          W contains the computed eigenvalues, in the same order that
116*>          they appear on the diagonal of the output Schur form T.
117*> \endverbatim
118*>
119*> \param[out] VS
120*> \verbatim
121*>          VS is COMPLEX array, dimension (LDVS,N)
122*>          If JOBVS = 'V', VS contains the unitary matrix Z of Schur
123*>          vectors.
124*>          If JOBVS = 'N', VS is not referenced.
125*> \endverbatim
126*>
127*> \param[in] LDVS
128*> \verbatim
129*>          LDVS is INTEGER
130*>          The leading dimension of the array VS.  LDVS >= 1; if
131*>          JOBVS = 'V', LDVS >= N.
132*> \endverbatim
133*>
134*> \param[out] WORK
135*> \verbatim
136*>          WORK is COMPLEX array, dimension (MAX(1,LWORK))
137*>          On exit, if INFO = 0, WORK(1) returns the optimal LWORK.
138*> \endverbatim
139*>
140*> \param[in] LWORK
141*> \verbatim
142*>          LWORK is INTEGER
143*>          The dimension of the array WORK.  LWORK >= max(1,2*N).
144*>          For good performance, LWORK must generally be larger.
145*>
146*>          If LWORK = -1, then a workspace query is assumed; the routine
147*>          only calculates the optimal size of the WORK array, returns
148*>          this value as the first entry of the WORK array, and no error
149*>          message related to LWORK is issued by XERBLA.
150*> \endverbatim
151*>
152*> \param[out] RWORK
153*> \verbatim
154*>          RWORK is REAL array, dimension (N)
155*> \endverbatim
156*>
157*> \param[out] BWORK
158*> \verbatim
159*>          BWORK is LOGICAL array, dimension (N)
160*>          Not referenced if SORT = 'N'.
161*> \endverbatim
162*>
163*> \param[out] INFO
164*> \verbatim
165*>          INFO is INTEGER
166*>          = 0: successful exit
167*>          < 0: if INFO = -i, the i-th argument had an illegal value.
168*>          > 0: if INFO = i, and i is
169*>               <= N:  the QR algorithm failed to compute all the
170*>                      eigenvalues; elements 1:ILO-1 and i+1:N of W
171*>                      contain those eigenvalues which have converged;
172*>                      if JOBVS = 'V', VS contains the matrix which
173*>                      reduces A to its partially converged Schur form.
174*>               = N+1: the eigenvalues could not be reordered because
175*>                      some eigenvalues were too close to separate (the
176*>                      problem is very ill-conditioned);
177*>               = N+2: after reordering, roundoff changed values of
178*>                      some complex eigenvalues so that leading
179*>                      eigenvalues in the Schur form no longer satisfy
180*>                      SELECT = .TRUE..  This could also be caused by
181*>                      underflow due to scaling.
182*> \endverbatim
183*
184*  Authors:
185*  ========
186*
187*> \author Univ. of Tennessee
188*> \author Univ. of California Berkeley
189*> \author Univ. of Colorado Denver
190*> \author NAG Ltd.
191*
192*> \date December 2016
193*
194*> \ingroup complexGEeigen
195*
196*  =====================================================================
197      SUBROUTINE CGEES( JOBVS, SORT, SELECT, N, A, LDA, SDIM, W, VS,
198     $                  LDVS, WORK, LWORK, RWORK, BWORK, INFO )
199*
200*  -- LAPACK driver routine (version 3.7.0) --
201*  -- LAPACK is a software package provided by Univ. of Tennessee,    --
202*  -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..--
203*     December 2016
204*
205*     .. Scalar Arguments ..
206      CHARACTER          JOBVS, SORT
207      INTEGER            INFO, LDA, LDVS, LWORK, N, SDIM
208*     ..
209*     .. Array Arguments ..
210      LOGICAL            BWORK( * )
211      REAL               RWORK( * )
212      COMPLEX            A( LDA, * ), VS( LDVS, * ), W( * ), WORK( * )
213*     ..
214*     .. Function Arguments ..
215      LOGICAL            SELECT
216      EXTERNAL           SELECT
217*     ..
218*
219*  =====================================================================
220*
221*     .. Parameters ..
222      REAL               ZERO, ONE
223      PARAMETER          ( ZERO = 0.0E0, ONE = 1.0E0 )
224*     ..
225*     .. Local Scalars ..
226      LOGICAL            LQUERY, SCALEA, WANTST, WANTVS
227      INTEGER            HSWORK, I, IBAL, ICOND, IERR, IEVAL, IHI, ILO,
228     $                   ITAU, IWRK, MAXWRK, MINWRK
229      REAL               ANRM, BIGNUM, CSCALE, EPS, S, SEP, SMLNUM
230*     ..
231*     .. Local Arrays ..
232      REAL               DUM( 1 )
233*     ..
234*     .. External Subroutines ..
235      EXTERNAL           CCOPY, CGEBAK, CGEBAL, CGEHRD, CHSEQR, CLACPY,
236     $                   CLASCL, CTRSEN, CUNGHR, SLABAD, XERBLA
237*     ..
238*     .. External Functions ..
239      LOGICAL            LSAME
240      INTEGER            ILAENV
241      REAL               CLANGE, SLAMCH
242      EXTERNAL           LSAME, ILAENV, CLANGE, SLAMCH
243*     ..
244*     .. Intrinsic Functions ..
245      INTRINSIC          MAX, SQRT
246*     ..
247*     .. Executable Statements ..
248*
249*     Test the input arguments
250*
251      INFO = 0
252      LQUERY = ( LWORK.EQ.-1 )
253      WANTVS = LSAME( JOBVS, 'V' )
254      WANTST = LSAME( SORT, 'S' )
255      IF( ( .NOT.WANTVS ) .AND. ( .NOT.LSAME( JOBVS, 'N' ) ) ) THEN
256         INFO = -1
257      ELSE IF( ( .NOT.WANTST ) .AND. ( .NOT.LSAME( SORT, 'N' ) ) ) THEN
258         INFO = -2
259      ELSE IF( N.LT.0 ) THEN
260         INFO = -4
261      ELSE IF( LDA.LT.MAX( 1, N ) ) THEN
262         INFO = -6
263      ELSE IF( LDVS.LT.1 .OR. ( WANTVS .AND. LDVS.LT.N ) ) THEN
264         INFO = -10
265      END IF
266*
267*     Compute workspace
268*      (Note: Comments in the code beginning "Workspace:" describe the
269*       minimal amount of workspace needed at that point in the code,
270*       as well as the preferred amount for good performance.
271*       CWorkspace refers to complex workspace, and RWorkspace to real
272*       workspace. NB refers to the optimal block size for the
273*       immediately following subroutine, as returned by ILAENV.
274*       HSWORK refers to the workspace preferred by CHSEQR, as
275*       calculated below. HSWORK is computed assuming ILO=1 and IHI=N,
276*       the worst case.)
277*
278      IF( INFO.EQ.0 ) THEN
279         IF( N.EQ.0 ) THEN
280            MINWRK = 1
281            MAXWRK = 1
282         ELSE
283            MAXWRK = N + N*ILAENV( 1, 'CGEHRD', ' ', N, 1, N, 0 )
284            MINWRK = 2*N
285*
286            CALL CHSEQR( 'S', JOBVS, N, 1, N, A, LDA, W, VS, LDVS,
287     $             WORK, -1, IEVAL )
288            HSWORK = WORK( 1 )
289*
290            IF( .NOT.WANTVS ) THEN
291               MAXWRK = MAX( MAXWRK, HSWORK )
292            ELSE
293               MAXWRK = MAX( MAXWRK, N + ( N - 1 )*ILAENV( 1, 'CUNGHR',
294     $                       ' ', N, 1, N, -1 ) )
295               MAXWRK = MAX( MAXWRK, HSWORK )
296            END IF
297         END IF
298         WORK( 1 ) = MAXWRK
299*
300         IF( LWORK.LT.MINWRK .AND. .NOT.LQUERY ) THEN
301            INFO = -12
302         END IF
303      END IF
304*
305      IF( INFO.NE.0 ) THEN
306         CALL XERBLA( 'CGEES ', -INFO )
307         RETURN
308      ELSE IF( LQUERY ) THEN
309         RETURN
310      END IF
311*
312*     Quick return if possible
313*
314      IF( N.EQ.0 ) THEN
315         SDIM = 0
316         RETURN
317      END IF
318*
319*     Get machine constants
320*
321      EPS = SLAMCH( 'P' )
322      SMLNUM = SLAMCH( 'S' )
323      BIGNUM = ONE / SMLNUM
324      CALL SLABAD( SMLNUM, BIGNUM )
325      SMLNUM = SQRT( SMLNUM ) / EPS
326      BIGNUM = ONE / SMLNUM
327*
328*     Scale A if max element outside range [SMLNUM,BIGNUM]
329*
330      ANRM = CLANGE( 'M', N, N, A, LDA, DUM )
331      SCALEA = .FALSE.
332      IF( ANRM.GT.ZERO .AND. ANRM.LT.SMLNUM ) THEN
333         SCALEA = .TRUE.
334         CSCALE = SMLNUM
335      ELSE IF( ANRM.GT.BIGNUM ) THEN
336         SCALEA = .TRUE.
337         CSCALE = BIGNUM
338      END IF
339      IF( SCALEA )
340     $   CALL CLASCL( 'G', 0, 0, ANRM, CSCALE, N, N, A, LDA, IERR )
341*
342*     Permute the matrix to make it more nearly triangular
343*     (CWorkspace: none)
344*     (RWorkspace: need N)
345*
346      IBAL = 1
347      CALL CGEBAL( 'P', N, A, LDA, ILO, IHI, RWORK( IBAL ), IERR )
348*
349*     Reduce to upper Hessenberg form
350*     (CWorkspace: need 2*N, prefer N+N*NB)
351*     (RWorkspace: none)
352*
353      ITAU = 1
354      IWRK = N + ITAU
355      CALL CGEHRD( N, ILO, IHI, A, LDA, WORK( ITAU ), WORK( IWRK ),
356     $             LWORK-IWRK+1, IERR )
357*
358      IF( WANTVS ) THEN
359*
360*        Copy Householder vectors to VS
361*
362         CALL CLACPY( 'L', N, N, A, LDA, VS, LDVS )
363*
364*        Generate unitary matrix in VS
365*        (CWorkspace: need 2*N-1, prefer N+(N-1)*NB)
366*        (RWorkspace: none)
367*
368         CALL CUNGHR( N, ILO, IHI, VS, LDVS, WORK( ITAU ), WORK( IWRK ),
369     $                LWORK-IWRK+1, IERR )
370      END IF
371*
372      SDIM = 0
373*
374*     Perform QR iteration, accumulating Schur vectors in VS if desired
375*     (CWorkspace: need 1, prefer HSWORK (see comments) )
376*     (RWorkspace: none)
377*
378      IWRK = ITAU
379      CALL CHSEQR( 'S', JOBVS, N, ILO, IHI, A, LDA, W, VS, LDVS,
380     $             WORK( IWRK ), LWORK-IWRK+1, IEVAL )
381      IF( IEVAL.GT.0 )
382     $   INFO = IEVAL
383*
384*     Sort eigenvalues if desired
385*
386      IF( WANTST .AND. INFO.EQ.0 ) THEN
387         IF( SCALEA )
388     $      CALL CLASCL( 'G', 0, 0, CSCALE, ANRM, N, 1, W, N, IERR )
389         DO 10 I = 1, N
390            BWORK( I ) = SELECT( W( I ) )
391   10    CONTINUE
392*
393*        Reorder eigenvalues and transform Schur vectors
394*        (CWorkspace: none)
395*        (RWorkspace: none)
396*
397         CALL CTRSEN( 'N', JOBVS, BWORK, N, A, LDA, VS, LDVS, W, SDIM,
398     $                S, SEP, WORK( IWRK ), LWORK-IWRK+1, ICOND )
399      END IF
400*
401      IF( WANTVS ) THEN
402*
403*        Undo balancing
404*        (CWorkspace: none)
405*        (RWorkspace: need N)
406*
407         CALL CGEBAK( 'P', 'R', N, ILO, IHI, RWORK( IBAL ), N, VS, LDVS,
408     $                IERR )
409      END IF
410*
411      IF( SCALEA ) THEN
412*
413*        Undo scaling for the Schur form of A
414*
415         CALL CLASCL( 'U', 0, 0, CSCALE, ANRM, N, N, A, LDA, IERR )
416         CALL CCOPY( N, A, LDA+1, W, 1 )
417      END IF
418*
419      WORK( 1 ) = MAXWRK
420      RETURN
421*
422*     End of CGEES
423*
424      END
425