dsteqr.c 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622
  1. /* dsteqr.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 doublereal c_b9 = 0.;
  15. static doublereal c_b10 = 1.;
  16. static integer c__0 = 0;
  17. static integer c__1 = 1;
  18. static integer c__2 = 2;
  19. /* Subroutine */ int _starpu_dsteqr_(char *compz, integer *n, doublereal *d__,
  20. doublereal *e, doublereal *z__, integer *ldz, doublereal *work,
  21. integer *info)
  22. {
  23. /* System generated locals */
  24. integer z_dim1, z_offset, i__1, i__2;
  25. doublereal d__1, d__2;
  26. /* Builtin functions */
  27. double sqrt(doublereal), d_sign(doublereal *, doublereal *);
  28. /* Local variables */
  29. doublereal b, c__, f, g;
  30. integer i__, j, k, l, m;
  31. doublereal p, r__, s;
  32. integer l1, ii, mm, lm1, mm1, nm1;
  33. doublereal rt1, rt2, eps;
  34. integer lsv;
  35. doublereal tst, eps2;
  36. integer lend, jtot;
  37. extern /* Subroutine */ int _starpu_dlae2_(doublereal *, doublereal *, doublereal
  38. *, doublereal *, doublereal *);
  39. extern logical _starpu_lsame_(char *, char *);
  40. extern /* Subroutine */ int _starpu_dlasr_(char *, char *, char *, integer *,
  41. integer *, doublereal *, doublereal *, doublereal *, integer *);
  42. doublereal anorm;
  43. extern /* Subroutine */ int _starpu_dswap_(integer *, doublereal *, integer *,
  44. doublereal *, integer *), _starpu_dlaev2_(doublereal *, doublereal *,
  45. doublereal *, doublereal *, doublereal *, doublereal *,
  46. doublereal *);
  47. integer lendm1, lendp1;
  48. extern doublereal _starpu_dlapy2_(doublereal *, doublereal *), _starpu_dlamch_(char *);
  49. integer iscale;
  50. extern /* Subroutine */ int _starpu_dlascl_(char *, integer *, integer *,
  51. doublereal *, doublereal *, integer *, integer *, doublereal *,
  52. integer *, integer *), _starpu_dlaset_(char *, integer *, integer
  53. *, doublereal *, doublereal *, doublereal *, integer *);
  54. doublereal safmin;
  55. extern /* Subroutine */ int _starpu_dlartg_(doublereal *, doublereal *,
  56. doublereal *, doublereal *, doublereal *);
  57. doublereal safmax;
  58. extern /* Subroutine */ int _starpu_xerbla_(char *, integer *);
  59. extern doublereal _starpu_dlanst_(char *, integer *, doublereal *, doublereal *);
  60. extern /* Subroutine */ int _starpu_dlasrt_(char *, integer *, doublereal *,
  61. integer *);
  62. integer lendsv;
  63. doublereal ssfmin;
  64. integer nmaxit, icompz;
  65. doublereal ssfmax;
  66. /* -- LAPACK routine (version 3.2) -- */
  67. /* Univ. of Tennessee, Univ. of California Berkeley and NAG Ltd.. */
  68. /* November 2006 */
  69. /* .. Scalar Arguments .. */
  70. /* .. */
  71. /* .. Array Arguments .. */
  72. /* .. */
  73. /* Purpose */
  74. /* ======= */
  75. /* DSTEQR computes all eigenvalues and, optionally, eigenvectors of a */
  76. /* symmetric tridiagonal matrix using the implicit QL or QR method. */
  77. /* The eigenvectors of a full or band symmetric matrix can also be found */
  78. /* if DSYTRD or DSPTRD or DSBTRD has been used to reduce this matrix to */
  79. /* tridiagonal form. */
  80. /* Arguments */
  81. /* ========= */
  82. /* COMPZ (input) CHARACTER*1 */
  83. /* = 'N': Compute eigenvalues only. */
  84. /* = 'V': Compute eigenvalues and eigenvectors of the original */
  85. /* symmetric matrix. On entry, Z must contain the */
  86. /* orthogonal matrix used to reduce the original matrix */
  87. /* to tridiagonal form. */
  88. /* = 'I': Compute eigenvalues and eigenvectors of the */
  89. /* tridiagonal matrix. Z is initialized to the identity */
  90. /* matrix. */
  91. /* N (input) INTEGER */
  92. /* The order of the matrix. N >= 0. */
  93. /* D (input/output) DOUBLE PRECISION array, dimension (N) */
  94. /* On entry, the diagonal elements of the tridiagonal matrix. */
  95. /* On exit, if INFO = 0, the eigenvalues in ascending order. */
  96. /* E (input/output) DOUBLE PRECISION array, dimension (N-1) */
  97. /* On entry, the (n-1) subdiagonal elements of the tridiagonal */
  98. /* matrix. */
  99. /* On exit, E has been destroyed. */
  100. /* Z (input/output) DOUBLE PRECISION array, dimension (LDZ, N) */
  101. /* On entry, if COMPZ = 'V', then Z contains the orthogonal */
  102. /* matrix used in the reduction to tridiagonal form. */
  103. /* On exit, if INFO = 0, then if COMPZ = 'V', Z contains the */
  104. /* orthonormal eigenvectors of the original symmetric matrix, */
  105. /* and if COMPZ = 'I', Z contains the orthonormal eigenvectors */
  106. /* of the symmetric tridiagonal matrix. */
  107. /* If COMPZ = 'N', then Z is not referenced. */
  108. /* LDZ (input) INTEGER */
  109. /* The leading dimension of the array Z. LDZ >= 1, and if */
  110. /* eigenvectors are desired, then LDZ >= max(1,N). */
  111. /* WORK (workspace) DOUBLE PRECISION array, dimension (max(1,2*N-2)) */
  112. /* If COMPZ = 'N', then WORK is not referenced. */
  113. /* INFO (output) INTEGER */
  114. /* = 0: successful exit */
  115. /* < 0: if INFO = -i, the i-th argument had an illegal value */
  116. /* > 0: the algorithm has failed to find all the eigenvalues in */
  117. /* a total of 30*N iterations; if INFO = i, then i */
  118. /* elements of E have not converged to zero; on exit, D */
  119. /* and E contain the elements of a symmetric tridiagonal */
  120. /* matrix which is orthogonally similar to the original */
  121. /* matrix. */
  122. /* ===================================================================== */
  123. /* .. Parameters .. */
  124. /* .. */
  125. /* .. Local Scalars .. */
  126. /* .. */
  127. /* .. External Functions .. */
  128. /* .. */
  129. /* .. External Subroutines .. */
  130. /* .. */
  131. /* .. Intrinsic Functions .. */
  132. /* .. */
  133. /* .. Executable Statements .. */
  134. /* Test the input parameters. */
  135. /* Parameter adjustments */
  136. --d__;
  137. --e;
  138. z_dim1 = *ldz;
  139. z_offset = 1 + z_dim1;
  140. z__ -= z_offset;
  141. --work;
  142. /* Function Body */
  143. *info = 0;
  144. if (_starpu_lsame_(compz, "N")) {
  145. icompz = 0;
  146. } else if (_starpu_lsame_(compz, "V")) {
  147. icompz = 1;
  148. } else if (_starpu_lsame_(compz, "I")) {
  149. icompz = 2;
  150. } else {
  151. icompz = -1;
  152. }
  153. if (icompz < 0) {
  154. *info = -1;
  155. } else if (*n < 0) {
  156. *info = -2;
  157. } else if (*ldz < 1 || icompz > 0 && *ldz < max(1,*n)) {
  158. *info = -6;
  159. }
  160. if (*info != 0) {
  161. i__1 = -(*info);
  162. _starpu_xerbla_("DSTEQR", &i__1);
  163. return 0;
  164. }
  165. /* Quick return if possible */
  166. if (*n == 0) {
  167. return 0;
  168. }
  169. if (*n == 1) {
  170. if (icompz == 2) {
  171. z__[z_dim1 + 1] = 1.;
  172. }
  173. return 0;
  174. }
  175. /* Determine the unit roundoff and over/underflow thresholds. */
  176. eps = _starpu_dlamch_("E");
  177. /* Computing 2nd power */
  178. d__1 = eps;
  179. eps2 = d__1 * d__1;
  180. safmin = _starpu_dlamch_("S");
  181. safmax = 1. / safmin;
  182. ssfmax = sqrt(safmax) / 3.;
  183. ssfmin = sqrt(safmin) / eps2;
  184. /* Compute the eigenvalues and eigenvectors of the tridiagonal */
  185. /* matrix. */
  186. if (icompz == 2) {
  187. _starpu_dlaset_("Full", n, n, &c_b9, &c_b10, &z__[z_offset], ldz);
  188. }
  189. nmaxit = *n * 30;
  190. jtot = 0;
  191. /* Determine where the matrix splits and choose QL or QR iteration */
  192. /* for each block, according to whether top or bottom diagonal */
  193. /* element is smaller. */
  194. l1 = 1;
  195. nm1 = *n - 1;
  196. L10:
  197. if (l1 > *n) {
  198. goto L160;
  199. }
  200. if (l1 > 1) {
  201. e[l1 - 1] = 0.;
  202. }
  203. if (l1 <= nm1) {
  204. i__1 = nm1;
  205. for (m = l1; m <= i__1; ++m) {
  206. tst = (d__1 = e[m], abs(d__1));
  207. if (tst == 0.) {
  208. goto L30;
  209. }
  210. if (tst <= sqrt((d__1 = d__[m], abs(d__1))) * sqrt((d__2 = d__[m
  211. + 1], abs(d__2))) * eps) {
  212. e[m] = 0.;
  213. goto L30;
  214. }
  215. /* L20: */
  216. }
  217. }
  218. m = *n;
  219. L30:
  220. l = l1;
  221. lsv = l;
  222. lend = m;
  223. lendsv = lend;
  224. l1 = m + 1;
  225. if (lend == l) {
  226. goto L10;
  227. }
  228. /* Scale submatrix in rows and columns L to LEND */
  229. i__1 = lend - l + 1;
  230. anorm = _starpu_dlanst_("I", &i__1, &d__[l], &e[l]);
  231. iscale = 0;
  232. if (anorm == 0.) {
  233. goto L10;
  234. }
  235. if (anorm > ssfmax) {
  236. iscale = 1;
  237. i__1 = lend - l + 1;
  238. _starpu_dlascl_("G", &c__0, &c__0, &anorm, &ssfmax, &i__1, &c__1, &d__[l], n,
  239. info);
  240. i__1 = lend - l;
  241. _starpu_dlascl_("G", &c__0, &c__0, &anorm, &ssfmax, &i__1, &c__1, &e[l], n,
  242. info);
  243. } else if (anorm < ssfmin) {
  244. iscale = 2;
  245. i__1 = lend - l + 1;
  246. _starpu_dlascl_("G", &c__0, &c__0, &anorm, &ssfmin, &i__1, &c__1, &d__[l], n,
  247. info);
  248. i__1 = lend - l;
  249. _starpu_dlascl_("G", &c__0, &c__0, &anorm, &ssfmin, &i__1, &c__1, &e[l], n,
  250. info);
  251. }
  252. /* Choose between QL and QR iteration */
  253. if ((d__1 = d__[lend], abs(d__1)) < (d__2 = d__[l], abs(d__2))) {
  254. lend = lsv;
  255. l = lendsv;
  256. }
  257. if (lend > l) {
  258. /* QL Iteration */
  259. /* Look for small subdiagonal element. */
  260. L40:
  261. if (l != lend) {
  262. lendm1 = lend - 1;
  263. i__1 = lendm1;
  264. for (m = l; m <= i__1; ++m) {
  265. /* Computing 2nd power */
  266. d__2 = (d__1 = e[m], abs(d__1));
  267. tst = d__2 * d__2;
  268. if (tst <= eps2 * (d__1 = d__[m], abs(d__1)) * (d__2 = d__[m
  269. + 1], abs(d__2)) + safmin) {
  270. goto L60;
  271. }
  272. /* L50: */
  273. }
  274. }
  275. m = lend;
  276. L60:
  277. if (m < lend) {
  278. e[m] = 0.;
  279. }
  280. p = d__[l];
  281. if (m == l) {
  282. goto L80;
  283. }
  284. /* If remaining matrix is 2-by-2, use DLAE2 or SLAEV2 */
  285. /* to compute its eigensystem. */
  286. if (m == l + 1) {
  287. if (icompz > 0) {
  288. _starpu_dlaev2_(&d__[l], &e[l], &d__[l + 1], &rt1, &rt2, &c__, &s);
  289. work[l] = c__;
  290. work[*n - 1 + l] = s;
  291. _starpu_dlasr_("R", "V", "B", n, &c__2, &work[l], &work[*n - 1 + l], &
  292. z__[l * z_dim1 + 1], ldz);
  293. } else {
  294. _starpu_dlae2_(&d__[l], &e[l], &d__[l + 1], &rt1, &rt2);
  295. }
  296. d__[l] = rt1;
  297. d__[l + 1] = rt2;
  298. e[l] = 0.;
  299. l += 2;
  300. if (l <= lend) {
  301. goto L40;
  302. }
  303. goto L140;
  304. }
  305. if (jtot == nmaxit) {
  306. goto L140;
  307. }
  308. ++jtot;
  309. /* Form shift. */
  310. g = (d__[l + 1] - p) / (e[l] * 2.);
  311. r__ = _starpu_dlapy2_(&g, &c_b10);
  312. g = d__[m] - p + e[l] / (g + d_sign(&r__, &g));
  313. s = 1.;
  314. c__ = 1.;
  315. p = 0.;
  316. /* Inner loop */
  317. mm1 = m - 1;
  318. i__1 = l;
  319. for (i__ = mm1; i__ >= i__1; --i__) {
  320. f = s * e[i__];
  321. b = c__ * e[i__];
  322. _starpu_dlartg_(&g, &f, &c__, &s, &r__);
  323. if (i__ != m - 1) {
  324. e[i__ + 1] = r__;
  325. }
  326. g = d__[i__ + 1] - p;
  327. r__ = (d__[i__] - g) * s + c__ * 2. * b;
  328. p = s * r__;
  329. d__[i__ + 1] = g + p;
  330. g = c__ * r__ - b;
  331. /* If eigenvectors are desired, then save rotations. */
  332. if (icompz > 0) {
  333. work[i__] = c__;
  334. work[*n - 1 + i__] = -s;
  335. }
  336. /* L70: */
  337. }
  338. /* If eigenvectors are desired, then apply saved rotations. */
  339. if (icompz > 0) {
  340. mm = m - l + 1;
  341. _starpu_dlasr_("R", "V", "B", n, &mm, &work[l], &work[*n - 1 + l], &z__[l
  342. * z_dim1 + 1], ldz);
  343. }
  344. d__[l] -= p;
  345. e[l] = g;
  346. goto L40;
  347. /* Eigenvalue found. */
  348. L80:
  349. d__[l] = p;
  350. ++l;
  351. if (l <= lend) {
  352. goto L40;
  353. }
  354. goto L140;
  355. } else {
  356. /* QR Iteration */
  357. /* Look for small superdiagonal element. */
  358. L90:
  359. if (l != lend) {
  360. lendp1 = lend + 1;
  361. i__1 = lendp1;
  362. for (m = l; m >= i__1; --m) {
  363. /* Computing 2nd power */
  364. d__2 = (d__1 = e[m - 1], abs(d__1));
  365. tst = d__2 * d__2;
  366. if (tst <= eps2 * (d__1 = d__[m], abs(d__1)) * (d__2 = d__[m
  367. - 1], abs(d__2)) + safmin) {
  368. goto L110;
  369. }
  370. /* L100: */
  371. }
  372. }
  373. m = lend;
  374. L110:
  375. if (m > lend) {
  376. e[m - 1] = 0.;
  377. }
  378. p = d__[l];
  379. if (m == l) {
  380. goto L130;
  381. }
  382. /* If remaining matrix is 2-by-2, use DLAE2 or SLAEV2 */
  383. /* to compute its eigensystem. */
  384. if (m == l - 1) {
  385. if (icompz > 0) {
  386. _starpu_dlaev2_(&d__[l - 1], &e[l - 1], &d__[l], &rt1, &rt2, &c__, &s)
  387. ;
  388. work[m] = c__;
  389. work[*n - 1 + m] = s;
  390. _starpu_dlasr_("R", "V", "F", n, &c__2, &work[m], &work[*n - 1 + m], &
  391. z__[(l - 1) * z_dim1 + 1], ldz);
  392. } else {
  393. _starpu_dlae2_(&d__[l - 1], &e[l - 1], &d__[l], &rt1, &rt2);
  394. }
  395. d__[l - 1] = rt1;
  396. d__[l] = rt2;
  397. e[l - 1] = 0.;
  398. l += -2;
  399. if (l >= lend) {
  400. goto L90;
  401. }
  402. goto L140;
  403. }
  404. if (jtot == nmaxit) {
  405. goto L140;
  406. }
  407. ++jtot;
  408. /* Form shift. */
  409. g = (d__[l - 1] - p) / (e[l - 1] * 2.);
  410. r__ = _starpu_dlapy2_(&g, &c_b10);
  411. g = d__[m] - p + e[l - 1] / (g + d_sign(&r__, &g));
  412. s = 1.;
  413. c__ = 1.;
  414. p = 0.;
  415. /* Inner loop */
  416. lm1 = l - 1;
  417. i__1 = lm1;
  418. for (i__ = m; i__ <= i__1; ++i__) {
  419. f = s * e[i__];
  420. b = c__ * e[i__];
  421. _starpu_dlartg_(&g, &f, &c__, &s, &r__);
  422. if (i__ != m) {
  423. e[i__ - 1] = r__;
  424. }
  425. g = d__[i__] - p;
  426. r__ = (d__[i__ + 1] - g) * s + c__ * 2. * b;
  427. p = s * r__;
  428. d__[i__] = g + p;
  429. g = c__ * r__ - b;
  430. /* If eigenvectors are desired, then save rotations. */
  431. if (icompz > 0) {
  432. work[i__] = c__;
  433. work[*n - 1 + i__] = s;
  434. }
  435. /* L120: */
  436. }
  437. /* If eigenvectors are desired, then apply saved rotations. */
  438. if (icompz > 0) {
  439. mm = l - m + 1;
  440. _starpu_dlasr_("R", "V", "F", n, &mm, &work[m], &work[*n - 1 + m], &z__[m
  441. * z_dim1 + 1], ldz);
  442. }
  443. d__[l] -= p;
  444. e[lm1] = g;
  445. goto L90;
  446. /* Eigenvalue found. */
  447. L130:
  448. d__[l] = p;
  449. --l;
  450. if (l >= lend) {
  451. goto L90;
  452. }
  453. goto L140;
  454. }
  455. /* Undo scaling if necessary */
  456. L140:
  457. if (iscale == 1) {
  458. i__1 = lendsv - lsv + 1;
  459. _starpu_dlascl_("G", &c__0, &c__0, &ssfmax, &anorm, &i__1, &c__1, &d__[lsv],
  460. n, info);
  461. i__1 = lendsv - lsv;
  462. _starpu_dlascl_("G", &c__0, &c__0, &ssfmax, &anorm, &i__1, &c__1, &e[lsv], n,
  463. info);
  464. } else if (iscale == 2) {
  465. i__1 = lendsv - lsv + 1;
  466. _starpu_dlascl_("G", &c__0, &c__0, &ssfmin, &anorm, &i__1, &c__1, &d__[lsv],
  467. n, info);
  468. i__1 = lendsv - lsv;
  469. _starpu_dlascl_("G", &c__0, &c__0, &ssfmin, &anorm, &i__1, &c__1, &e[lsv], n,
  470. info);
  471. }
  472. /* Check for no convergence to an eigenvalue after a total */
  473. /* of N*MAXIT iterations. */
  474. if (jtot < nmaxit) {
  475. goto L10;
  476. }
  477. i__1 = *n - 1;
  478. for (i__ = 1; i__ <= i__1; ++i__) {
  479. if (e[i__] != 0.) {
  480. ++(*info);
  481. }
  482. /* L150: */
  483. }
  484. goto L190;
  485. /* Order eigenvalues and eigenvectors. */
  486. L160:
  487. if (icompz == 0) {
  488. /* Use Quick Sort */
  489. _starpu_dlasrt_("I", n, &d__[1], info);
  490. } else {
  491. /* Use Selection Sort to minimize swaps of eigenvectors */
  492. i__1 = *n;
  493. for (ii = 2; ii <= i__1; ++ii) {
  494. i__ = ii - 1;
  495. k = i__;
  496. p = d__[i__];
  497. i__2 = *n;
  498. for (j = ii; j <= i__2; ++j) {
  499. if (d__[j] < p) {
  500. k = j;
  501. p = d__[j];
  502. }
  503. /* L170: */
  504. }
  505. if (k != i__) {
  506. d__[k] = d__[i__];
  507. d__[i__] = p;
  508. _starpu_dswap_(n, &z__[i__ * z_dim1 + 1], &c__1, &z__[k * z_dim1 + 1],
  509. &c__1);
  510. }
  511. /* L180: */
  512. }
  513. }
  514. L190:
  515. return 0;
  516. /* End of DSTEQR */
  517. } /* _starpu_dsteqr_ */