1 /* lapack/complex16/zgees.f -- translated by f2c (version 20090411).
2 You must link the resulting object file with libf2c:
3 on Microsoft Windows system, link with libf2c.lib;
4 on Linux or Unix systems, link with .../path/to/libf2c.a -lm
5 or, if you install libf2c.a in a standard place, with -lf2c -lm
6 -- in that order, at the end of the command line, as in
7 cc *.o -lf2c -lm
8 Source for libf2c is in /netlib/f2c/libf2c.zip, e.g.,
9
10 http://www.netlib.org/f2c/libf2c.zip
11 */
12
13 #ifdef __cplusplus
14 extern "C" {
15 #endif
16 #include "v3p_netlib.h"
17
18 /* Table of constant values */
19
20 static integer c__1 = 1;
21 static integer c__0 = 0;
22 static integer c_n1 = -1;
23
24 /*< >*/
zgees_(char * jobvs,char * sort,logical (* select)(doublecomplex *),integer * n,doublecomplex * a,integer * lda,integer * sdim,doublecomplex * w,doublecomplex * vs,integer * ldvs,doublecomplex * work,integer * lwork,doublereal * rwork,logical * bwork,integer * info,ftnlen jobvs_len,ftnlen sort_len)25 /* Subroutine */ int zgees_(char *jobvs, char *sort,
26 logical (*select)(doublecomplex*), integer *n,
27 doublecomplex *a, integer *lda, integer *sdim, doublecomplex *w,
28 doublecomplex *vs, integer *ldvs, doublecomplex *work, integer *lwork,
29 doublereal *rwork, logical *bwork, integer *info, ftnlen jobvs_len,
30 ftnlen sort_len)
31 {
32 /* System generated locals */
33 integer a_dim1, a_offset, vs_dim1, vs_offset, i__1, i__2;
34
35 /* Builtin functions */
36 double sqrt(doublereal);
37
38 /* Local variables */
39 integer i__;
40 doublereal s;
41 integer ihi, ilo;
42 doublereal dum[1], eps, sep;
43 integer ibal;
44 doublereal anrm;
45 integer ierr, itau, iwrk, icond, ieval;
46 extern logical lsame_(const char *, const char *, ftnlen, ftnlen);
47 extern /* Subroutine */ int zcopy_(integer *, doublecomplex *, integer *,
48 doublecomplex *, integer *), dlabad_(doublereal *, doublereal *);
49 logical scalea;
50 extern doublereal dlamch_(char *, ftnlen);
51 doublereal cscale;
52 extern /* Subroutine */ int zgebak_(char *, char *, integer *, integer *,
53 integer *, doublereal *, integer *, doublecomplex *, integer *,
54 integer *, ftnlen, ftnlen), zgebal_(char *, integer *,
55 doublecomplex *, integer *, integer *, integer *, doublereal *,
56 integer *, ftnlen), xerbla_(char *, integer *, ftnlen);
57 extern integer ilaenv_(integer *, char *, char *, integer *, integer *,
58 integer *, integer *, ftnlen, ftnlen);
59 extern doublereal zlange_(char *, integer *, integer *, doublecomplex *,
60 integer *, doublereal *, ftnlen);
61 doublereal bignum;
62 extern /* Subroutine */ int zgehrd_(integer *, integer *, integer *,
63 doublecomplex *, integer *, doublecomplex *, doublecomplex *,
64 integer *, integer *), zlascl_(char *, integer *, integer *,
65 doublereal *, doublereal *, integer *, integer *, doublecomplex *,
66 integer *, integer *, ftnlen), zlacpy_(char *, integer *,
67 integer *, doublecomplex *, integer *, doublecomplex *, integer *,
68 ftnlen);
69 integer minwrk, maxwrk;
70 doublereal smlnum;
71 extern /* Subroutine */ int zhseqr_(char *, char *, integer *, integer *,
72 integer *, doublecomplex *, integer *, doublecomplex *,
73 doublecomplex *, integer *, doublecomplex *, integer *, integer *,
74 ftnlen, ftnlen);
75 integer hswork;
76 extern /* Subroutine */ int zunghr_(integer *, integer *, integer *,
77 doublecomplex *, integer *, doublecomplex *, doublecomplex *,
78 integer *, integer *);
79 logical wantst, lquery, wantvs;
80 extern /* Subroutine */ int ztrsen_(char *, char *, logical *, integer *,
81 doublecomplex *, integer *, doublecomplex *, integer *,
82 doublecomplex *, integer *, doublereal *, doublereal *,
83 doublecomplex *, integer *, integer *, ftnlen, ftnlen);
84 (void)jobvs_len;
85 (void)sort_len;
86
87 /* -- LAPACK driver routine (version 3.2) -- */
88 /* -- LAPACK is a software package provided by Univ. of Tennessee, -- */
89 /* -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..-- */
90 /* November 2006 */
91
92 /* .. Scalar Arguments .. */
93 /*< CHARACTER JOBVS, SORT >*/
94 /*< INTEGER INFO, LDA, LDVS, LWORK, N, SDIM >*/
95 /* .. */
96 /* .. Array Arguments .. */
97 /*< LOGICAL BWORK( * ) >*/
98 /*< DOUBLE PRECISION RWORK( * ) >*/
99 /*< COMPLEX*16 A( LDA, * ), VS( LDVS, * ), W( * ), WORK( * ) >*/
100 /* .. */
101 /* .. Function Arguments .. */
102 /*< LOGICAL SELECT >*/
103 /*< EXTERNAL SELECT >*/
104 /* .. */
105
106 /* Purpose */
107 /* ======= */
108
109 /* ZGEES computes for an N-by-N complex nonsymmetric matrix A, the */
110 /* eigenvalues, the Schur form T, and, optionally, the matrix of Schur */
111 /* vectors Z. This gives the Schur factorization A = Z*T*(Z**H). */
112
113 /* Optionally, it also orders the eigenvalues on the diagonal of the */
114 /* Schur form so that selected eigenvalues are at the top left. */
115 /* The leading columns of Z then form an orthonormal basis for the */
116 /* invariant subspace corresponding to the selected eigenvalues. */
117
118 /* A complex matrix is in Schur form if it is upper triangular. */
119
120 /* Arguments */
121 /* ========= */
122
123 /* JOBVS (input) CHARACTER*1 */
124 /* = 'N': Schur vectors are not computed; */
125 /* = 'V': Schur vectors are computed. */
126
127 /* SORT (input) CHARACTER*1 */
128 /* Specifies whether or not to order the eigenvalues on the */
129 /* diagonal of the Schur form. */
130 /* = 'N': Eigenvalues are not ordered: */
131 /* = 'S': Eigenvalues are ordered (see SELECT). */
132
133 /* SELECT (external procedure) LOGICAL FUNCTION of one COMPLEX*16 argument */
134 /* SELECT must be declared EXTERNAL in the calling subroutine. */
135 /* If SORT = 'S', SELECT is used to select eigenvalues to order */
136 /* to the top left of the Schur form. */
137 /* IF SORT = 'N', SELECT is not referenced. */
138 /* The eigenvalue W(j) is selected if SELECT(W(j)) is true. */
139
140 /* N (input) INTEGER */
141 /* The order of the matrix A. N >= 0. */
142
143 /* A (input/output) COMPLEX*16 array, dimension (LDA,N) */
144 /* On entry, the N-by-N matrix A. */
145 /* On exit, A has been overwritten by its Schur form T. */
146
147 /* LDA (input) INTEGER */
148 /* The leading dimension of the array A. LDA >= max(1,N). */
149
150 /* SDIM (output) INTEGER */
151 /* If SORT = 'N', SDIM = 0. */
152 /* If SORT = 'S', SDIM = number of eigenvalues for which */
153 /* SELECT is true. */
154
155 /* W (output) COMPLEX*16 array, dimension (N) */
156 /* W contains the computed eigenvalues, in the same order that */
157 /* they appear on the diagonal of the output Schur form T. */
158
159 /* VS (output) COMPLEX*16 array, dimension (LDVS,N) */
160 /* If JOBVS = 'V', VS contains the unitary matrix Z of Schur */
161 /* vectors. */
162 /* If JOBVS = 'N', VS is not referenced. */
163
164 /* LDVS (input) INTEGER */
165 /* The leading dimension of the array VS. LDVS >= 1; if */
166 /* JOBVS = 'V', LDVS >= N. */
167
168 /* WORK (workspace/output) COMPLEX*16 array, dimension (MAX(1,LWORK)) */
169 /* On exit, if INFO = 0, WORK(1) returns the optimal LWORK. */
170
171 /* LWORK (input) INTEGER */
172 /* The dimension of the array WORK. LWORK >= max(1,2*N). */
173 /* For good performance, LWORK must generally be larger. */
174
175 /* If LWORK = -1, then a workspace query is assumed; the routine */
176 /* only calculates the optimal size of the WORK array, returns */
177 /* this value as the first entry of the WORK array, and no error */
178 /* message related to LWORK is issued by XERBLA. */
179
180 /* RWORK (workspace) DOUBLE PRECISION array, dimension (N) */
181
182 /* BWORK (workspace) LOGICAL array, dimension (N) */
183 /* Not referenced if SORT = 'N'. */
184
185 /* INFO (output) INTEGER */
186 /* = 0: successful exit */
187 /* < 0: if INFO = -i, the i-th argument had an illegal value. */
188 /* > 0: if INFO = i, and i is */
189 /* <= N: the QR algorithm failed to compute all the */
190 /* eigenvalues; elements 1:ILO-1 and i+1:N of W */
191 /* contain those eigenvalues which have converged; */
192 /* if JOBVS = 'V', VS contains the matrix which */
193 /* reduces A to its partially converged Schur form. */
194 /* = N+1: the eigenvalues could not be reordered because */
195 /* some eigenvalues were too close to separate (the */
196 /* problem is very ill-conditioned); */
197 /* = N+2: after reordering, roundoff changed values of */
198 /* some complex eigenvalues so that leading */
199 /* eigenvalues in the Schur form no longer satisfy */
200 /* SELECT = .TRUE.. This could also be caused by */
201 /* underflow due to scaling. */
202
203 /* ===================================================================== */
204
205 /* .. Parameters .. */
206 /*< DOUBLE PRECISION ZERO, ONE >*/
207 /*< PARAMETER ( ZERO = 0.0D0, ONE = 1.0D0 ) >*/
208 /* .. */
209 /* .. Local Scalars .. */
210 /*< LOGICAL LQUERY, SCALEA, WANTST, WANTVS >*/
211 /*< >*/
212 /*< DOUBLE PRECISION ANRM, BIGNUM, CSCALE, EPS, S, SEP, SMLNUM >*/
213 /* .. */
214 /* .. Local Arrays .. */
215 /*< DOUBLE PRECISION DUM( 1 ) >*/
216 /* .. */
217 /* .. External Subroutines .. */
218 /*< >*/
219 /* .. */
220 /* .. External Functions .. */
221 /*< LOGICAL LSAME >*/
222 /*< INTEGER ILAENV >*/
223 /*< DOUBLE PRECISION DLAMCH, ZLANGE >*/
224 /*< EXTERNAL LSAME, ILAENV, DLAMCH, ZLANGE >*/
225 /* .. */
226 /* .. Intrinsic Functions .. */
227 /*< INTRINSIC MAX, SQRT >*/
228 /* .. */
229 /* .. Executable Statements .. */
230
231 /* Test the input arguments */
232
233 /*< INFO = 0 >*/
234 /* Parameter adjustments */
235 a_dim1 = *lda;
236 a_offset = 1 + a_dim1;
237 a -= a_offset;
238 --w;
239 vs_dim1 = *ldvs;
240 vs_offset = 1 + vs_dim1;
241 vs -= vs_offset;
242 --work;
243 --rwork;
244 --bwork;
245
246 /* Function Body */
247 *info = 0;
248 /*< LQUERY = ( LWORK.EQ.-1 ) >*/
249 lquery = *lwork == -1;
250 /*< WANTVS = LSAME( JOBVS, 'V' ) >*/
251 wantvs = lsame_(jobvs, "V", (ftnlen)1, (ftnlen)1);
252 /*< WANTST = LSAME( SORT, 'S' ) >*/
253 wantst = lsame_(sort, "S", (ftnlen)1, (ftnlen)1);
254 /*< IF( ( .NOT.WANTVS ) .AND. ( .NOT.LSAME( JOBVS, 'N' ) ) ) THEN >*/
255 if (! wantvs && ! lsame_(jobvs, "N", (ftnlen)1, (ftnlen)1)) {
256 /*< INFO = -1 >*/
257 *info = -1;
258 /*< ELSE IF( ( .NOT.WANTST ) .AND. ( .NOT.LSAME( SORT, 'N' ) ) ) THEN >*/
259 } else if (! wantst && ! lsame_(sort, "N", (ftnlen)1, (ftnlen)1)) {
260 /*< INFO = -2 >*/
261 *info = -2;
262 /*< ELSE IF( N.LT.0 ) THEN >*/
263 } else if (*n < 0) {
264 /*< INFO = -4 >*/
265 *info = -4;
266 /*< ELSE IF( LDA.LT.MAX( 1, N ) ) THEN >*/
267 } else if (*lda < max(1,*n)) {
268 /*< INFO = -6 >*/
269 *info = -6;
270 /*< ELSE IF( LDVS.LT.1 .OR. ( WANTVS .AND. LDVS.LT.N ) ) THEN >*/
271 } else if (*ldvs < 1 || (wantvs && *ldvs < *n)) {
272 /*< INFO = -10 >*/
273 *info = -10;
274 /*< END IF >*/
275 }
276
277 /* Compute workspace */
278 /* (Note: Comments in the code beginning "Workspace:" describe the */
279 /* minimal amount of workspace needed at that point in the code, */
280 /* as well as the preferred amount for good performance. */
281 /* CWorkspace refers to complex workspace, and RWorkspace to real */
282 /* workspace. NB refers to the optimal block size for the */
283 /* immediately following subroutine, as returned by ILAENV. */
284 /* HSWORK refers to the workspace preferred by ZHSEQR, as */
285 /* calculated below. HSWORK is computed assuming ILO=1 and IHI=N, */
286 /* the worst case.) */
287
288 /*< IF( INFO.EQ.0 ) THEN >*/
289 if (*info == 0) {
290 /*< IF( N.EQ.0 ) THEN >*/
291 if (*n == 0) {
292 /*< MINWRK = 1 >*/
293 minwrk = 1;
294 /*< MAXWRK = 1 >*/
295 maxwrk = 1;
296 /*< ELSE >*/
297 } else {
298 /*< MAXWRK = N + N*ILAENV( 1, 'ZGEHRD', ' ', N, 1, N, 0 ) >*/
299 maxwrk = *n + *n * ilaenv_(&c__1, "ZGEHRD", " ", n, &c__1, n, &
300 c__0, (ftnlen)6, (ftnlen)1);
301 /*< MINWRK = 2*N >*/
302 minwrk = *n << 1;
303
304 /*< >*/
305 zhseqr_("S", jobvs, n, &c__1, n, &a[a_offset], lda, &w[1], &vs[
306 vs_offset], ldvs, &work[1], &c_n1, &ieval, (ftnlen)1, (
307 ftnlen)1);
308 /*< HSWORK = WORK( 1 ) >*/
309 hswork = (integer) work[1].r;
310
311 /*< IF( .NOT.WANTVS ) THEN >*/
312 if (! wantvs) {
313 /*< MAXWRK = MAX( MAXWRK, HSWORK ) >*/
314 maxwrk = max(maxwrk,hswork);
315 /*< ELSE >*/
316 } else {
317 /*< >*/
318 /* Computing MAX */
319 i__1 = maxwrk, i__2 = *n + (*n - 1) * ilaenv_(&c__1, "ZUNGHR",
320 " ", n, &c__1, n, &c_n1, (ftnlen)6, (ftnlen)1);
321 maxwrk = max(i__1,i__2);
322 /*< MAXWRK = MAX( MAXWRK, HSWORK ) >*/
323 maxwrk = max(maxwrk,hswork);
324 /*< END IF >*/
325 }
326 /*< END IF >*/
327 }
328 /*< WORK( 1 ) = MAXWRK >*/
329 work[1].r = (doublereal) maxwrk, work[1].i = 0.;
330
331 /*< IF( LWORK.LT.MINWRK .AND. .NOT.LQUERY ) THEN >*/
332 if (*lwork < minwrk && ! lquery) {
333 /*< INFO = -12 >*/
334 *info = -12;
335 /*< END IF >*/
336 }
337 /*< END IF >*/
338 }
339
340 /*< IF( INFO.NE.0 ) THEN >*/
341 if (*info != 0) {
342 /*< CALL XERBLA( 'ZGEES ', -INFO ) >*/
343 i__1 = -(*info);
344 xerbla_("ZGEES ", &i__1, (ftnlen)6);
345 /*< RETURN >*/
346 return 0;
347 /*< ELSE IF( LQUERY ) THEN >*/
348 } else if (lquery) {
349 /*< RETURN >*/
350 return 0;
351 /*< END IF >*/
352 }
353
354 /* Quick return if possible */
355
356 /*< IF( N.EQ.0 ) THEN >*/
357 if (*n == 0) {
358 /*< SDIM = 0 >*/
359 *sdim = 0;
360 /*< RETURN >*/
361 return 0;
362 /*< END IF >*/
363 }
364
365 /* Get machine constants */
366
367 /*< EPS = DLAMCH( 'P' ) >*/
368 eps = dlamch_("P", (ftnlen)1);
369 /*< SMLNUM = DLAMCH( 'S' ) >*/
370 smlnum = dlamch_("S", (ftnlen)1);
371 /*< BIGNUM = ONE / SMLNUM >*/
372 bignum = 1. / smlnum;
373 /*< CALL DLABAD( SMLNUM, BIGNUM ) >*/
374 dlabad_(&smlnum, &bignum);
375 /*< SMLNUM = SQRT( SMLNUM ) / EPS >*/
376 smlnum = sqrt(smlnum) / eps;
377 /*< BIGNUM = ONE / SMLNUM >*/
378 bignum = 1. / smlnum;
379
380 /* Scale A if max element outside range [SMLNUM,BIGNUM] */
381
382 /*< ANRM = ZLANGE( 'M', N, N, A, LDA, DUM ) >*/
383 anrm = zlange_("M", n, n, &a[a_offset], lda, dum, (ftnlen)1);
384 /*< SCALEA = .FALSE. >*/
385 scalea = FALSE_;
386 /*< IF( ANRM.GT.ZERO .AND. ANRM.LT.SMLNUM ) THEN >*/
387 if (anrm > 0. && anrm < smlnum) {
388 /*< SCALEA = .TRUE. >*/
389 scalea = TRUE_;
390 /*< CSCALE = SMLNUM >*/
391 cscale = smlnum;
392 /*< ELSE IF( ANRM.GT.BIGNUM ) THEN >*/
393 } else if (anrm > bignum) {
394 /*< SCALEA = .TRUE. >*/
395 scalea = TRUE_;
396 /*< CSCALE = BIGNUM >*/
397 cscale = bignum;
398 /*< END IF >*/
399 }
400 /*< >*/
401 if (scalea) {
402 zlascl_("G", &c__0, &c__0, &anrm, &cscale, n, n, &a[a_offset], lda, &
403 ierr, (ftnlen)1);
404 }
405
406 /* Permute the matrix to make it more nearly triangular */
407 /* (CWorkspace: none) */
408 /* (RWorkspace: need N) */
409
410 /*< IBAL = 1 >*/
411 ibal = 1;
412 /*< CALL ZGEBAL( 'P', N, A, LDA, ILO, IHI, RWORK( IBAL ), IERR ) >*/
413 zgebal_("P", n, &a[a_offset], lda, &ilo, &ihi, &rwork[ibal], &ierr, (
414 ftnlen)1);
415
416 /* Reduce to upper Hessenberg form */
417 /* (CWorkspace: need 2*N, prefer N+N*NB) */
418 /* (RWorkspace: none) */
419
420 /*< ITAU = 1 >*/
421 itau = 1;
422 /*< IWRK = N + ITAU >*/
423 iwrk = *n + itau;
424 /*< >*/
425 i__1 = *lwork - iwrk + 1;
426 zgehrd_(n, &ilo, &ihi, &a[a_offset], lda, &work[itau], &work[iwrk], &i__1,
427 &ierr);
428
429 /*< IF( WANTVS ) THEN >*/
430 if (wantvs) {
431
432 /* Copy Householder vectors to VS */
433
434 /*< CALL ZLACPY( 'L', N, N, A, LDA, VS, LDVS ) >*/
435 zlacpy_("L", n, n, &a[a_offset], lda, &vs[vs_offset], ldvs, (ftnlen)1)
436 ;
437
438 /* Generate unitary matrix in VS */
439 /* (CWorkspace: need 2*N-1, prefer N+(N-1)*NB) */
440 /* (RWorkspace: none) */
441
442 /*< >*/
443 i__1 = *lwork - iwrk + 1;
444 zunghr_(n, &ilo, &ihi, &vs[vs_offset], ldvs, &work[itau], &work[iwrk],
445 &i__1, &ierr);
446 /*< END IF >*/
447 }
448
449 /*< SDIM = 0 >*/
450 *sdim = 0;
451
452 /* Perform QR iteration, accumulating Schur vectors in VS if desired */
453 /* (CWorkspace: need 1, prefer HSWORK (see comments) ) */
454 /* (RWorkspace: none) */
455
456 /*< IWRK = ITAU >*/
457 iwrk = itau;
458 /*< >*/
459 i__1 = *lwork - iwrk + 1;
460 zhseqr_("S", jobvs, n, &ilo, &ihi, &a[a_offset], lda, &w[1], &vs[
461 vs_offset], ldvs, &work[iwrk], &i__1, &ieval, (ftnlen)1, (ftnlen)
462 1);
463 /*< >*/
464 if (ieval > 0) {
465 *info = ieval;
466 }
467
468 /* Sort eigenvalues if desired */
469
470 /*< IF( WANTST .AND. INFO.EQ.0 ) THEN >*/
471 if (wantst && *info == 0) {
472 /*< >*/
473 if (scalea) {
474 zlascl_("G", &c__0, &c__0, &cscale, &anrm, n, &c__1, &w[1], n, &
475 ierr, (ftnlen)1);
476 }
477 /*< DO 10 I = 1, N >*/
478 i__1 = *n;
479 for (i__ = 1; i__ <= i__1; ++i__) {
480 /*< BWORK( I ) = SELECT( W( I ) ) >*/
481 bwork[i__] = (*select)(&w[i__]);
482 /*< 10 CONTINUE >*/
483 /* L10: */
484 }
485
486 /* Reorder eigenvalues and transform Schur vectors */
487 /* (CWorkspace: none) */
488 /* (RWorkspace: none) */
489
490 /*< >*/
491 i__1 = *lwork - iwrk + 1;
492 ztrsen_("N", jobvs, &bwork[1], n, &a[a_offset], lda, &vs[vs_offset],
493 ldvs, &w[1], sdim, &s, &sep, &work[iwrk], &i__1, &icond, (
494 ftnlen)1, (ftnlen)1);
495 /*< END IF >*/
496 }
497
498 /*< IF( WANTVS ) THEN >*/
499 if (wantvs) {
500
501 /* Undo balancing */
502 /* (CWorkspace: none) */
503 /* (RWorkspace: need N) */
504
505 /*< >*/
506 zgebak_("P", "R", n, &ilo, &ihi, &rwork[ibal], n, &vs[vs_offset],
507 ldvs, &ierr, (ftnlen)1, (ftnlen)1);
508 /*< END IF >*/
509 }
510
511 /*< IF( SCALEA ) THEN >*/
512 if (scalea) {
513
514 /* Undo scaling for the Schur form of A */
515
516 /*< CALL ZLASCL( 'U', 0, 0, CSCALE, ANRM, N, N, A, LDA, IERR ) >*/
517 zlascl_("U", &c__0, &c__0, &cscale, &anrm, n, n, &a[a_offset], lda, &
518 ierr, (ftnlen)1);
519 /*< CALL ZCOPY( N, A, LDA+1, W, 1 ) >*/
520 i__1 = *lda + 1;
521 zcopy_(n, &a[a_offset], &i__1, &w[1], &c__1);
522 /*< END IF >*/
523 }
524
525 /*< WORK( 1 ) = MAXWRK >*/
526 work[1].r = (doublereal) maxwrk, work[1].i = 0.;
527 /*< RETURN >*/
528 return 0;
529
530 /* End of ZGEES */
531
532 /*< END >*/
533 } /* zgees_ */
534
535 #ifdef __cplusplus
536 }
537 #endif
538