1 /* ztrsen.f -- translated by f2c (version 20061008).
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 #include "f2c.h"
14 #include "blaswrap.h"
15 
16 /* Table of constant values */
17 
18 static integer c_n1 = -1;
19 
ztrsen_(char * job,char * compq,logical * select,integer * n,doublecomplex * t,integer * ldt,doublecomplex * q,integer * ldq,doublecomplex * w,integer * m,doublereal * s,doublereal * sep,doublecomplex * work,integer * lwork,integer * info)20 /* Subroutine */ int ztrsen_(char *job, char *compq, logical *select, integer
21 	*n, doublecomplex *t, integer *ldt, doublecomplex *q, integer *ldq,
22 	doublecomplex *w, integer *m, doublereal *s, doublereal *sep,
23 	doublecomplex *work, integer *lwork, integer *info)
24 {
25     /* System generated locals */
26     integer q_dim1, q_offset, t_dim1, t_offset, i__1, i__2, i__3;
27 
28     /* Builtin functions */
29     double sqrt(doublereal);
30 
31     /* Local variables */
32     integer k, n1, n2, nn, ks;
33     doublereal est;
34     integer kase, ierr;
35     doublereal scale;
36     extern logical lsame_(char *, char *);
37     integer isave[3], lwmin;
38     logical wantq, wants;
39     doublereal rnorm, rwork[1];
40     extern /* Subroutine */ int zlacn2_(integer *, doublecomplex *,
41 	    doublecomplex *, doublereal *, integer *, integer *), xerbla_(
42 	    char *, integer *);
43     extern doublereal zlange_(char *, integer *, integer *, doublecomplex *,
44 	    integer *, doublereal *);
45     logical wantbh;
46     extern /* Subroutine */ int zlacpy_(char *, integer *, integer *,
47 	    doublecomplex *, integer *, doublecomplex *, integer *);
48     logical wantsp;
49     extern /* Subroutine */ int ztrexc_(char *, integer *, doublecomplex *,
50 	    integer *, doublecomplex *, integer *, integer *, integer *,
51 	    integer *);
52     logical lquery;
53     extern /* Subroutine */ int ztrsyl_(char *, char *, integer *, integer *,
54 	    integer *, doublecomplex *, integer *, doublecomplex *, integer *,
55 	     doublecomplex *, integer *, doublereal *, integer *);
56 
57 
58 /*  -- LAPACK routine (version 3.2) -- */
59 /*     Univ. of Tennessee, Univ. of California Berkeley and NAG Ltd.. */
60 /*     November 2006 */
61 
62 /*     Modified to call ZLACN2 in place of ZLACON, 10 Feb 03, SJH. */
63 
64 /*     .. Scalar Arguments .. */
65 /*     .. */
66 /*     .. Array Arguments .. */
67 /*     .. */
68 
69 /*  Purpose */
70 /*  ======= */
71 
72 /*  ZTRSEN reorders the Schur factorization of a complex matrix */
73 /*  A = Q*T*Q**H, so that a selected cluster of eigenvalues appears in */
74 /*  the leading positions on the diagonal of the upper triangular matrix */
75 /*  T, and the leading columns of Q form an orthonormal basis of the */
76 /*  corresponding right invariant subspace. */
77 
78 /*  Optionally the routine computes the reciprocal condition numbers of */
79 /*  the cluster of eigenvalues and/or the invariant subspace. */
80 
81 /*  Arguments */
82 /*  ========= */
83 
84 /*  JOB     (input) CHARACTER*1 */
85 /*          Specifies whether condition numbers are required for the */
86 /*          cluster of eigenvalues (S) or the invariant subspace (SEP): */
87 /*          = 'N': none; */
88 /*          = 'E': for eigenvalues only (S); */
89 /*          = 'V': for invariant subspace only (SEP); */
90 /*          = 'B': for both eigenvalues and invariant subspace (S and */
91 /*                 SEP). */
92 
93 /*  COMPQ   (input) CHARACTER*1 */
94 /*          = 'V': update the matrix Q of Schur vectors; */
95 /*          = 'N': do not update Q. */
96 
97 /*  SELECT  (input) LOGICAL array, dimension (N) */
98 /*          SELECT specifies the eigenvalues in the selected cluster. To */
99 /*          select the j-th eigenvalue, SELECT(j) must be set to .TRUE.. */
100 
101 /*  N       (input) INTEGER */
102 /*          The order of the matrix T. N >= 0. */
103 
104 /*  T       (input/output) COMPLEX*16 array, dimension (LDT,N) */
105 /*          On entry, the upper triangular matrix T. */
106 /*          On exit, T is overwritten by the reordered matrix T, with the */
107 /*          selected eigenvalues as the leading diagonal elements. */
108 
109 /*  LDT     (input) INTEGER */
110 /*          The leading dimension of the array T. LDT >= max(1,N). */
111 
112 /*  Q       (input/output) COMPLEX*16 array, dimension (LDQ,N) */
113 /*          On entry, if COMPQ = 'V', the matrix Q of Schur vectors. */
114 /*          On exit, if COMPQ = 'V', Q has been postmultiplied by the */
115 /*          unitary transformation matrix which reorders T; the leading M */
116 /*          columns of Q form an orthonormal basis for the specified */
117 /*          invariant subspace. */
118 /*          If COMPQ = 'N', Q is not referenced. */
119 
120 /*  LDQ     (input) INTEGER */
121 /*          The leading dimension of the array Q. */
122 /*          LDQ >= 1; and if COMPQ = 'V', LDQ >= N. */
123 
124 /*  W       (output) COMPLEX*16 array, dimension (N) */
125 /*          The reordered eigenvalues of T, in the same order as they */
126 /*          appear on the diagonal of T. */
127 
128 /*  M       (output) INTEGER */
129 /*          The dimension of the specified invariant subspace. */
130 /*          0 <= M <= N. */
131 
132 /*  S       (output) DOUBLE PRECISION */
133 /*          If JOB = 'E' or 'B', S is a lower bound on the reciprocal */
134 /*          condition number for the selected cluster of eigenvalues. */
135 /*          S cannot underestimate the true reciprocal condition number */
136 /*          by more than a factor of sqrt(N). If M = 0 or N, S = 1. */
137 /*          If JOB = 'N' or 'V', S is not referenced. */
138 
139 /*  SEP     (output) DOUBLE PRECISION */
140 /*          If JOB = 'V' or 'B', SEP is the estimated reciprocal */
141 /*          condition number of the specified invariant subspace. If */
142 /*          M = 0 or N, SEP = norm(T). */
143 /*          If JOB = 'N' or 'E', SEP is not referenced. */
144 
145 /*  WORK    (workspace/output) COMPLEX*16 array, dimension (MAX(1,LWORK)) */
146 /*          On exit, if INFO = 0, WORK(1) returns the optimal LWORK. */
147 
148 /*  LWORK   (input) INTEGER */
149 /*          The dimension of the array WORK. */
150 /*          If JOB = 'N', LWORK >= 1; */
151 /*          if JOB = 'E', LWORK = max(1,M*(N-M)); */
152 /*          if JOB = 'V' or 'B', LWORK >= max(1,2*M*(N-M)). */
153 
154 /*          If LWORK = -1, then a workspace query is assumed; the routine */
155 /*          only calculates the optimal size of the WORK array, returns */
156 /*          this value as the first entry of the WORK array, and no error */
157 /*          message related to LWORK is issued by XERBLA. */
158 
159 /*  INFO    (output) INTEGER */
160 /*          = 0:  successful exit */
161 /*          < 0:  if INFO = -i, the i-th argument had an illegal value */
162 
163 /*  Further Details */
164 /*  =============== */
165 
166 /*  ZTRSEN first collects the selected eigenvalues by computing a unitary */
167 /*  transformation Z to move them to the top left corner of T. In other */
168 /*  words, the selected eigenvalues are the eigenvalues of T11 in: */
169 
170 /*                Z'*T*Z = ( T11 T12 ) n1 */
171 /*                         (  0  T22 ) n2 */
172 /*                            n1  n2 */
173 
174 /*  where N = n1+n2 and Z' means the conjugate transpose of Z. The first */
175 /*  n1 columns of Z span the specified invariant subspace of T. */
176 
177 /*  If T has been obtained from the Schur factorization of a matrix */
178 /*  A = Q*T*Q', then the reordered Schur factorization of A is given by */
179 /*  A = (Q*Z)*(Z'*T*Z)*(Q*Z)', and the first n1 columns of Q*Z span the */
180 /*  corresponding invariant subspace of A. */
181 
182 /*  The reciprocal condition number of the average of the eigenvalues of */
183 /*  T11 may be returned in S. S lies between 0 (very badly conditioned) */
184 /*  and 1 (very well conditioned). It is computed as follows. First we */
185 /*  compute R so that */
186 
187 /*                         P = ( I  R ) n1 */
188 /*                             ( 0  0 ) n2 */
189 /*                               n1 n2 */
190 
191 /*  is the projector on the invariant subspace associated with T11. */
192 /*  R is the solution of the Sylvester equation: */
193 
194 /*                        T11*R - R*T22 = T12. */
195 
196 /*  Let F-norm(M) denote the Frobenius-norm of M and 2-norm(M) denote */
197 /*  the two-norm of M. Then S is computed as the lower bound */
198 
199 /*                      (1 + F-norm(R)**2)**(-1/2) */
200 
201 /*  on the reciprocal of 2-norm(P), the true reciprocal condition number. */
202 /*  S cannot underestimate 1 / 2-norm(P) by more than a factor of */
203 /*  sqrt(N). */
204 
205 /*  An approximate error bound for the computed average of the */
206 /*  eigenvalues of T11 is */
207 
208 /*                         EPS * norm(T) / S */
209 
210 /*  where EPS is the machine precision. */
211 
212 /*  The reciprocal condition number of the right invariant subspace */
213 /*  spanned by the first n1 columns of Z (or of Q*Z) is returned in SEP. */
214 /*  SEP is defined as the separation of T11 and T22: */
215 
216 /*                     sep( T11, T22 ) = sigma-min( C ) */
217 
218 /*  where sigma-min(C) is the smallest singular value of the */
219 /*  n1*n2-by-n1*n2 matrix */
220 
221 /*     C  = kprod( I(n2), T11 ) - kprod( transpose(T22), I(n1) ) */
222 
223 /*  I(m) is an m by m identity matrix, and kprod denotes the Kronecker */
224 /*  product. We estimate sigma-min(C) by the reciprocal of an estimate of */
225 /*  the 1-norm of inverse(C). The true reciprocal 1-norm of inverse(C) */
226 /*  cannot differ from sigma-min(C) by more than a factor of sqrt(n1*n2). */
227 
228 /*  When SEP is small, small changes in T can cause large changes in */
229 /*  the invariant subspace. An approximate bound on the maximum angular */
230 /*  error in the computed right invariant subspace is */
231 
232 /*                      EPS * norm(T) / SEP */
233 
234 /*  ===================================================================== */
235 
236 /*     .. Parameters .. */
237 /*     .. */
238 /*     .. Local Scalars .. */
239 /*     .. */
240 /*     .. Local Arrays .. */
241 /*     .. */
242 /*     .. External Functions .. */
243 /*     .. */
244 /*     .. External Subroutines .. */
245 /*     .. */
246 /*     .. Intrinsic Functions .. */
247 /*     .. */
248 /*     .. Executable Statements .. */
249 
250 /*     Decode and test the input parameters. */
251 
252     /* Parameter adjustments */
253     --select;
254     t_dim1 = *ldt;
255     t_offset = 1 + t_dim1;
256     t -= t_offset;
257     q_dim1 = *ldq;
258     q_offset = 1 + q_dim1;
259     q -= q_offset;
260     --w;
261     --work;
262 
263     /* Function Body */
264     wantbh = lsame_(job, "B");
265     wants = lsame_(job, "E") || wantbh;
266     wantsp = lsame_(job, "V") || wantbh;
267     wantq = lsame_(compq, "V");
268 
269 /*     Set M to the number of selected eigenvalues. */
270 
271     *m = 0;
272     i__1 = *n;
273     for (k = 1; k <= i__1; ++k) {
274 	if (select[k]) {
275 	    ++(*m);
276 	}
277 /* L10: */
278     }
279 
280     n1 = *m;
281     n2 = *n - *m;
282     nn = n1 * n2;
283 
284     *info = 0;
285     lquery = *lwork == -1;
286 
287     if (wantsp) {
288 /* Computing MAX */
289 	i__1 = 1, i__2 = nn << 1;
290 	lwmin = max(i__1,i__2);
291     } else if (lsame_(job, "N")) {
292 	lwmin = 1;
293     } else if (lsame_(job, "E")) {
294 	lwmin = max(1,nn);
295     }
296 
297     if (! lsame_(job, "N") && ! wants && ! wantsp) {
298 	*info = -1;
299     } else if (! lsame_(compq, "N") && ! wantq) {
300 	*info = -2;
301     } else if (*n < 0) {
302 	*info = -4;
303     } else if (*ldt < max(1,*n)) {
304 	*info = -6;
305     } else if (*ldq < 1 || wantq && *ldq < *n) {
306 	*info = -8;
307     } else if (*lwork < lwmin && ! lquery) {
308 	*info = -14;
309     }
310 
311     if (*info == 0) {
312 	work[1].r = (doublereal) lwmin, work[1].i = 0.;
313     }
314 
315     if (*info != 0) {
316 	i__1 = -(*info);
317 	xerbla_("ZTRSEN", &i__1);
318 	return 0;
319     } else if (lquery) {
320 	return 0;
321     }
322 
323 /*     Quick return if possible */
324 
325     if (*m == *n || *m == 0) {
326 	if (wants) {
327 	    *s = 1.;
328 	}
329 	if (wantsp) {
330 	    *sep = zlange_("1", n, n, &t[t_offset], ldt, rwork);
331 	}
332 	goto L40;
333     }
334 
335 /*     Collect the selected eigenvalues at the top left corner of T. */
336 
337     ks = 0;
338     i__1 = *n;
339     for (k = 1; k <= i__1; ++k) {
340 	if (select[k]) {
341 	    ++ks;
342 
343 /*           Swap the K-th eigenvalue to position KS. */
344 
345 	    if (k != ks) {
346 		ztrexc_(compq, n, &t[t_offset], ldt, &q[q_offset], ldq, &k, &
347 			ks, &ierr);
348 	    }
349 	}
350 /* L20: */
351     }
352 
353     if (wants) {
354 
355 /*        Solve the Sylvester equation for R: */
356 
357 /*           T11*R - R*T22 = scale*T12 */
358 
359 	zlacpy_("F", &n1, &n2, &t[(n1 + 1) * t_dim1 + 1], ldt, &work[1], &n1);
360 	ztrsyl_("N", "N", &c_n1, &n1, &n2, &t[t_offset], ldt, &t[n1 + 1 + (n1
361 		+ 1) * t_dim1], ldt, &work[1], &n1, &scale, &ierr);
362 
363 /*        Estimate the reciprocal of the condition number of the cluster */
364 /*        of eigenvalues. */
365 
366 	rnorm = zlange_("F", &n1, &n2, &work[1], &n1, rwork);
367 	if (rnorm == 0.) {
368 	    *s = 1.;
369 	} else {
370 	    *s = scale / (sqrt(scale * scale / rnorm + rnorm) * sqrt(rnorm));
371 	}
372     }
373 
374     if (wantsp) {
375 
376 /*        Estimate sep(T11,T22). */
377 
378 	est = 0.;
379 	kase = 0;
380 L30:
381 	zlacn2_(&nn, &work[nn + 1], &work[1], &est, &kase, isave);
382 	if (kase != 0) {
383 	    if (kase == 1) {
384 
385 /*              Solve T11*R - R*T22 = scale*X. */
386 
387 		ztrsyl_("N", "N", &c_n1, &n1, &n2, &t[t_offset], ldt, &t[n1 +
388 			1 + (n1 + 1) * t_dim1], ldt, &work[1], &n1, &scale, &
389 			ierr);
390 	    } else {
391 
392 /*              Solve T11'*R - R*T22' = scale*X. */
393 
394 		ztrsyl_("C", "C", &c_n1, &n1, &n2, &t[t_offset], ldt, &t[n1 +
395 			1 + (n1 + 1) * t_dim1], ldt, &work[1], &n1, &scale, &
396 			ierr);
397 	    }
398 	    goto L30;
399 	}
400 
401 	*sep = scale / est;
402     }
403 
404 L40:
405 
406 /*     Copy reordered eigenvalues to W. */
407 
408     i__1 = *n;
409     for (k = 1; k <= i__1; ++k) {
410 	i__2 = k;
411 	i__3 = k + k * t_dim1;
412 	w[i__2].r = t[i__3].r, w[i__2].i = t[i__3].i;
413 /* L50: */
414     }
415 
416     work[1].r = (doublereal) lwmin, work[1].i = 0.;
417 
418     return 0;
419 
420 /*     End of ZTRSEN */
421 
422 } /* ztrsen_ */
423