dtrsen.c 17 KB

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