dlarrv.c 37 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989
  1. /* dlarrv.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_b5 = 0.;
  15. static integer c__1 = 1;
  16. static integer c__2 = 2;
  17. /* Subroutine */ int _starpu_dlarrv_(integer *n, doublereal *vl, doublereal *vu,
  18. doublereal *d__, doublereal *l, doublereal *pivmin, integer *isplit,
  19. integer *m, integer *dol, integer *dou, doublereal *minrgp,
  20. doublereal *rtol1, doublereal *rtol2, doublereal *w, doublereal *werr,
  21. doublereal *wgap, integer *iblock, integer *indexw, doublereal *gers,
  22. doublereal *z__, integer *ldz, integer *isuppz, doublereal *work,
  23. integer *iwork, integer *info)
  24. {
  25. /* System generated locals */
  26. integer z_dim1, z_offset, i__1, i__2, i__3, i__4, i__5;
  27. doublereal d__1, d__2;
  28. logical L__1;
  29. /* Builtin functions */
  30. double log(doublereal);
  31. /* Local variables */
  32. integer minwsize, i__, j, k, p, q, miniwsize, ii;
  33. doublereal gl;
  34. integer im, in;
  35. doublereal gu, gap, eps, tau, tol, tmp;
  36. integer zto;
  37. doublereal ztz;
  38. integer iend, jblk;
  39. doublereal lgap;
  40. integer done;
  41. doublereal rgap, left;
  42. integer wend, iter;
  43. doublereal bstw;
  44. integer itmp1;
  45. extern /* Subroutine */ int _starpu_dscal_(integer *, doublereal *, doublereal *,
  46. integer *);
  47. integer indld;
  48. doublereal fudge;
  49. integer idone;
  50. doublereal sigma;
  51. integer iinfo, iindr;
  52. doublereal resid;
  53. logical eskip;
  54. doublereal right;
  55. extern /* Subroutine */ int _starpu_dcopy_(integer *, doublereal *, integer *,
  56. doublereal *, integer *);
  57. integer nclus, zfrom;
  58. doublereal rqtol;
  59. integer iindc1, iindc2;
  60. extern /* Subroutine */ int _starpu_dlar1v_(integer *, integer *, integer *,
  61. doublereal *, doublereal *, doublereal *, doublereal *,
  62. doublereal *, doublereal *, doublereal *, doublereal *, logical *,
  63. integer *, doublereal *, doublereal *, integer *, integer *,
  64. doublereal *, doublereal *, doublereal *, doublereal *);
  65. logical stp2ii;
  66. doublereal lambda;
  67. extern doublereal _starpu_dlamch_(char *);
  68. integer ibegin, indeig;
  69. logical needbs;
  70. integer indlld;
  71. doublereal sgndef, mingma;
  72. extern /* Subroutine */ int _starpu_dlarrb_(integer *, doublereal *, doublereal *,
  73. integer *, integer *, doublereal *, doublereal *, integer *,
  74. doublereal *, doublereal *, doublereal *, doublereal *, integer *,
  75. doublereal *, doublereal *, integer *, integer *);
  76. integer oldien, oldncl, wbegin;
  77. doublereal spdiam;
  78. integer negcnt;
  79. extern /* Subroutine */ int _starpu_dlarrf_(integer *, doublereal *, doublereal *,
  80. doublereal *, integer *, integer *, doublereal *, doublereal *,
  81. doublereal *, doublereal *, doublereal *, doublereal *,
  82. doublereal *, doublereal *, doublereal *, doublereal *,
  83. doublereal *, integer *);
  84. integer oldcls;
  85. doublereal savgap;
  86. integer ndepth;
  87. doublereal ssigma;
  88. extern /* Subroutine */ int _starpu_dlaset_(char *, integer *, integer *,
  89. doublereal *, doublereal *, doublereal *, integer *);
  90. logical usedbs;
  91. integer iindwk, offset;
  92. doublereal gaptol;
  93. integer newcls, oldfst, indwrk, windex, oldlst;
  94. logical usedrq;
  95. integer newfst, newftt, parity, windmn, windpl, isupmn, newlst, zusedl;
  96. doublereal bstres;
  97. integer newsiz, zusedu, zusedw;
  98. doublereal nrminv, rqcorr;
  99. logical tryrqc;
  100. integer isupmx;
  101. /* -- LAPACK auxiliary routine (version 3.2) -- */
  102. /* Univ. of Tennessee, Univ. of California Berkeley and NAG Ltd.. */
  103. /* November 2006 */
  104. /* .. Scalar Arguments .. */
  105. /* .. */
  106. /* .. Array Arguments .. */
  107. /* .. */
  108. /* Purpose */
  109. /* ======= */
  110. /* DLARRV computes the eigenvectors of the tridiagonal matrix */
  111. /* T = L D L^T given L, D and APPROXIMATIONS to the eigenvalues of L D L^T. */
  112. /* The input eigenvalues should have been computed by DLARRE. */
  113. /* Arguments */
  114. /* ========= */
  115. /* N (input) INTEGER */
  116. /* The order of the matrix. N >= 0. */
  117. /* VL (input) DOUBLE PRECISION */
  118. /* VU (input) DOUBLE PRECISION */
  119. /* Lower and upper bounds of the interval that contains the desired */
  120. /* eigenvalues. VL < VU. Needed to compute gaps on the left or right */
  121. /* end of the extremal eigenvalues in the desired RANGE. */
  122. /* D (input/output) DOUBLE PRECISION array, dimension (N) */
  123. /* On entry, the N diagonal elements of the diagonal matrix D. */
  124. /* On exit, D may be overwritten. */
  125. /* L (input/output) DOUBLE PRECISION array, dimension (N) */
  126. /* On entry, the (N-1) subdiagonal elements of the unit */
  127. /* bidiagonal matrix L are in elements 1 to N-1 of L */
  128. /* (if the matrix is not splitted.) At the end of each block */
  129. /* is stored the corresponding shift as given by DLARRE. */
  130. /* On exit, L is overwritten. */
  131. /* PIVMIN (in) DOUBLE PRECISION */
  132. /* The minimum pivot allowed in the Sturm sequence. */
  133. /* ISPLIT (input) INTEGER array, dimension (N) */
  134. /* The splitting points, at which T breaks up into blocks. */
  135. /* The first block consists of rows/columns 1 to */
  136. /* ISPLIT( 1 ), the second of rows/columns ISPLIT( 1 )+1 */
  137. /* through ISPLIT( 2 ), etc. */
  138. /* M (input) INTEGER */
  139. /* The total number of input eigenvalues. 0 <= M <= N. */
  140. /* DOL (input) INTEGER */
  141. /* DOU (input) INTEGER */
  142. /* If the user wants to compute only selected eigenvectors from all */
  143. /* the eigenvalues supplied, he can specify an index range DOL:DOU. */
  144. /* Or else the setting DOL=1, DOU=M should be applied. */
  145. /* Note that DOL and DOU refer to the order in which the eigenvalues */
  146. /* are stored in W. */
  147. /* If the user wants to compute only selected eigenpairs, then */
  148. /* the columns DOL-1 to DOU+1 of the eigenvector space Z contain the */
  149. /* computed eigenvectors. All other columns of Z are set to zero. */
  150. /* MINRGP (input) DOUBLE PRECISION */
  151. /* RTOL1 (input) DOUBLE PRECISION */
  152. /* RTOL2 (input) DOUBLE PRECISION */
  153. /* Parameters for bisection. */
  154. /* An interval [LEFT,RIGHT] has converged if */
  155. /* RIGHT-LEFT.LT.MAX( RTOL1*GAP, RTOL2*MAX(|LEFT|,|RIGHT|) ) */
  156. /* W (input/output) DOUBLE PRECISION array, dimension (N) */
  157. /* The first M elements of W contain the APPROXIMATE eigenvalues for */
  158. /* which eigenvectors are to be computed. The eigenvalues */
  159. /* should be grouped by split-off block and ordered from */
  160. /* smallest to largest within the block ( The output array */
  161. /* W from DLARRE is expected here ). Furthermore, they are with */
  162. /* respect to the shift of the corresponding root representation */
  163. /* for their block. On exit, W holds the eigenvalues of the */
  164. /* UNshifted matrix. */
  165. /* WERR (input/output) DOUBLE PRECISION array, dimension (N) */
  166. /* The first M elements contain the semiwidth of the uncertainty */
  167. /* interval of the corresponding eigenvalue in W */
  168. /* WGAP (input/output) DOUBLE PRECISION array, dimension (N) */
  169. /* The separation from the right neighbor eigenvalue in W. */
  170. /* IBLOCK (input) INTEGER array, dimension (N) */
  171. /* The indices of the blocks (submatrices) associated with the */
  172. /* corresponding eigenvalues in W; IBLOCK(i)=1 if eigenvalue */
  173. /* W(i) belongs to the first block from the top, =2 if W(i) */
  174. /* belongs to the second block, etc. */
  175. /* INDEXW (input) INTEGER array, dimension (N) */
  176. /* The indices of the eigenvalues within each block (submatrix); */
  177. /* for example, INDEXW(i)= 10 and IBLOCK(i)=2 imply that the */
  178. /* i-th eigenvalue W(i) is the 10-th eigenvalue in the second block. */
  179. /* GERS (input) DOUBLE PRECISION array, dimension (2*N) */
  180. /* The N Gerschgorin intervals (the i-th Gerschgorin interval */
  181. /* is (GERS(2*i-1), GERS(2*i)). The Gerschgorin intervals should */
  182. /* be computed from the original UNshifted matrix. */
  183. /* Z (output) DOUBLE PRECISION array, dimension (LDZ, max(1,M) ) */
  184. /* If INFO = 0, the first M columns of Z contain the */
  185. /* orthonormal eigenvectors of the matrix T */
  186. /* corresponding to the input eigenvalues, with the i-th */
  187. /* column of Z holding the eigenvector associated with W(i). */
  188. /* Note: the user must ensure that at least max(1,M) columns are */
  189. /* supplied in the array Z. */
  190. /* LDZ (input) INTEGER */
  191. /* The leading dimension of the array Z. LDZ >= 1, and if */
  192. /* JOBZ = 'V', LDZ >= max(1,N). */
  193. /* ISUPPZ (output) INTEGER array, dimension ( 2*max(1,M) ) */
  194. /* The support of the eigenvectors in Z, i.e., the indices */
  195. /* indicating the nonzero elements in Z. The I-th eigenvector */
  196. /* is nonzero only in elements ISUPPZ( 2*I-1 ) through */
  197. /* ISUPPZ( 2*I ). */
  198. /* WORK (workspace) DOUBLE PRECISION array, dimension (12*N) */
  199. /* IWORK (workspace) INTEGER array, dimension (7*N) */
  200. /* INFO (output) INTEGER */
  201. /* = 0: successful exit */
  202. /* > 0: A problem occured in DLARRV. */
  203. /* < 0: One of the called subroutines signaled an internal problem. */
  204. /* Needs inspection of the corresponding parameter IINFO */
  205. /* for further information. */
  206. /* =-1: Problem in DLARRB when refining a child's eigenvalues. */
  207. /* =-2: Problem in DLARRF when computing the RRR of a child. */
  208. /* When a child is inside a tight cluster, it can be difficult */
  209. /* to find an RRR. A partial remedy from the user's point of */
  210. /* view is to make the parameter MINRGP smaller and recompile. */
  211. /* However, as the orthogonality of the computed vectors is */
  212. /* proportional to 1/MINRGP, the user should be aware that */
  213. /* he might be trading in precision when he decreases MINRGP. */
  214. /* =-3: Problem in DLARRB when refining a single eigenvalue */
  215. /* after the Rayleigh correction was rejected. */
  216. /* = 5: The Rayleigh Quotient Iteration failed to converge to */
  217. /* full accuracy in MAXITR steps. */
  218. /* Further Details */
  219. /* =============== */
  220. /* Based on contributions by */
  221. /* Beresford Parlett, University of California, Berkeley, USA */
  222. /* Jim Demmel, University of California, Berkeley, USA */
  223. /* Inderjit Dhillon, University of Texas, Austin, USA */
  224. /* Osni Marques, LBNL/NERSC, USA */
  225. /* Christof Voemel, University of California, Berkeley, USA */
  226. /* ===================================================================== */
  227. /* .. Parameters .. */
  228. /* .. */
  229. /* .. Local Scalars .. */
  230. /* .. */
  231. /* .. External Functions .. */
  232. /* .. */
  233. /* .. External Subroutines .. */
  234. /* .. */
  235. /* .. Intrinsic Functions .. */
  236. /* .. */
  237. /* .. Executable Statements .. */
  238. /* .. */
  239. /* The first N entries of WORK are reserved for the eigenvalues */
  240. /* Parameter adjustments */
  241. --d__;
  242. --l;
  243. --isplit;
  244. --w;
  245. --werr;
  246. --wgap;
  247. --iblock;
  248. --indexw;
  249. --gers;
  250. z_dim1 = *ldz;
  251. z_offset = 1 + z_dim1;
  252. z__ -= z_offset;
  253. --isuppz;
  254. --work;
  255. --iwork;
  256. /* Function Body */
  257. indld = *n + 1;
  258. indlld = (*n << 1) + 1;
  259. indwrk = *n * 3 + 1;
  260. minwsize = *n * 12;
  261. i__1 = minwsize;
  262. for (i__ = 1; i__ <= i__1; ++i__) {
  263. work[i__] = 0.;
  264. /* L5: */
  265. }
  266. /* IWORK(IINDR+1:IINDR+N) hold the twist indices R for the */
  267. /* factorization used to compute the FP vector */
  268. iindr = 0;
  269. /* IWORK(IINDC1+1:IINC2+N) are used to store the clusters of the current */
  270. /* layer and the one above. */
  271. iindc1 = *n;
  272. iindc2 = *n << 1;
  273. iindwk = *n * 3 + 1;
  274. miniwsize = *n * 7;
  275. i__1 = miniwsize;
  276. for (i__ = 1; i__ <= i__1; ++i__) {
  277. iwork[i__] = 0;
  278. /* L10: */
  279. }
  280. zusedl = 1;
  281. if (*dol > 1) {
  282. /* Set lower bound for use of Z */
  283. zusedl = *dol - 1;
  284. }
  285. zusedu = *m;
  286. if (*dou < *m) {
  287. /* Set lower bound for use of Z */
  288. zusedu = *dou + 1;
  289. }
  290. /* The width of the part of Z that is used */
  291. zusedw = zusedu - zusedl + 1;
  292. _starpu_dlaset_("Full", n, &zusedw, &c_b5, &c_b5, &z__[zusedl * z_dim1 + 1], ldz);
  293. eps = _starpu_dlamch_("Precision");
  294. rqtol = eps * 2.;
  295. /* Set expert flags for standard code. */
  296. tryrqc = TRUE_;
  297. if (*dol == 1 && *dou == *m) {
  298. } else {
  299. /* Only selected eigenpairs are computed. Since the other evalues */
  300. /* are not refined by RQ iteration, bisection has to compute to full */
  301. /* accuracy. */
  302. *rtol1 = eps * 4.;
  303. *rtol2 = eps * 4.;
  304. }
  305. /* The entries WBEGIN:WEND in W, WERR, WGAP correspond to the */
  306. /* desired eigenvalues. The support of the nonzero eigenvector */
  307. /* entries is contained in the interval IBEGIN:IEND. */
  308. /* Remark that if k eigenpairs are desired, then the eigenvectors */
  309. /* are stored in k contiguous columns of Z. */
  310. /* DONE is the number of eigenvectors already computed */
  311. done = 0;
  312. ibegin = 1;
  313. wbegin = 1;
  314. i__1 = iblock[*m];
  315. for (jblk = 1; jblk <= i__1; ++jblk) {
  316. iend = isplit[jblk];
  317. sigma = l[iend];
  318. /* Find the eigenvectors of the submatrix indexed IBEGIN */
  319. /* through IEND. */
  320. wend = wbegin - 1;
  321. L15:
  322. if (wend < *m) {
  323. if (iblock[wend + 1] == jblk) {
  324. ++wend;
  325. goto L15;
  326. }
  327. }
  328. if (wend < wbegin) {
  329. ibegin = iend + 1;
  330. goto L170;
  331. } else if (wend < *dol || wbegin > *dou) {
  332. ibegin = iend + 1;
  333. wbegin = wend + 1;
  334. goto L170;
  335. }
  336. /* Find local spectral diameter of the block */
  337. gl = gers[(ibegin << 1) - 1];
  338. gu = gers[ibegin * 2];
  339. i__2 = iend;
  340. for (i__ = ibegin + 1; i__ <= i__2; ++i__) {
  341. /* Computing MIN */
  342. d__1 = gers[(i__ << 1) - 1];
  343. gl = min(d__1,gl);
  344. /* Computing MAX */
  345. d__1 = gers[i__ * 2];
  346. gu = max(d__1,gu);
  347. /* L20: */
  348. }
  349. spdiam = gu - gl;
  350. /* OLDIEN is the last index of the previous block */
  351. oldien = ibegin - 1;
  352. /* Calculate the size of the current block */
  353. in = iend - ibegin + 1;
  354. /* The number of eigenvalues in the current block */
  355. im = wend - wbegin + 1;
  356. /* This is for a 1x1 block */
  357. if (ibegin == iend) {
  358. ++done;
  359. z__[ibegin + wbegin * z_dim1] = 1.;
  360. isuppz[(wbegin << 1) - 1] = ibegin;
  361. isuppz[wbegin * 2] = ibegin;
  362. w[wbegin] += sigma;
  363. work[wbegin] = w[wbegin];
  364. ibegin = iend + 1;
  365. ++wbegin;
  366. goto L170;
  367. }
  368. /* The desired (shifted) eigenvalues are stored in W(WBEGIN:WEND) */
  369. /* Note that these can be approximations, in this case, the corresp. */
  370. /* entries of WERR give the size of the uncertainty interval. */
  371. /* The eigenvalue approximations will be refined when necessary as */
  372. /* high relative accuracy is required for the computation of the */
  373. /* corresponding eigenvectors. */
  374. _starpu_dcopy_(&im, &w[wbegin], &c__1, &work[wbegin], &c__1);
  375. /* We store in W the eigenvalue approximations w.r.t. the original */
  376. /* matrix T. */
  377. i__2 = im;
  378. for (i__ = 1; i__ <= i__2; ++i__) {
  379. w[wbegin + i__ - 1] += sigma;
  380. /* L30: */
  381. }
  382. /* NDEPTH is the current depth of the representation tree */
  383. ndepth = 0;
  384. /* PARITY is either 1 or 0 */
  385. parity = 1;
  386. /* NCLUS is the number of clusters for the next level of the */
  387. /* representation tree, we start with NCLUS = 1 for the root */
  388. nclus = 1;
  389. iwork[iindc1 + 1] = 1;
  390. iwork[iindc1 + 2] = im;
  391. /* IDONE is the number of eigenvectors already computed in the current */
  392. /* block */
  393. idone = 0;
  394. /* loop while( IDONE.LT.IM ) */
  395. /* generate the representation tree for the current block and */
  396. /* compute the eigenvectors */
  397. L40:
  398. if (idone < im) {
  399. /* This is a crude protection against infinitely deep trees */
  400. if (ndepth > *m) {
  401. *info = -2;
  402. return 0;
  403. }
  404. /* breadth first processing of the current level of the representation */
  405. /* tree: OLDNCL = number of clusters on current level */
  406. oldncl = nclus;
  407. /* reset NCLUS to count the number of child clusters */
  408. nclus = 0;
  409. parity = 1 - parity;
  410. if (parity == 0) {
  411. oldcls = iindc1;
  412. newcls = iindc2;
  413. } else {
  414. oldcls = iindc2;
  415. newcls = iindc1;
  416. }
  417. /* Process the clusters on the current level */
  418. i__2 = oldncl;
  419. for (i__ = 1; i__ <= i__2; ++i__) {
  420. j = oldcls + (i__ << 1);
  421. /* OLDFST, OLDLST = first, last index of current cluster. */
  422. /* cluster indices start with 1 and are relative */
  423. /* to WBEGIN when accessing W, WGAP, WERR, Z */
  424. oldfst = iwork[j - 1];
  425. oldlst = iwork[j];
  426. if (ndepth > 0) {
  427. /* Retrieve relatively robust representation (RRR) of cluster */
  428. /* that has been computed at the previous level */
  429. /* The RRR is stored in Z and overwritten once the eigenvectors */
  430. /* have been computed or when the cluster is refined */
  431. if (*dol == 1 && *dou == *m) {
  432. /* Get representation from location of the leftmost evalue */
  433. /* of the cluster */
  434. j = wbegin + oldfst - 1;
  435. } else {
  436. if (wbegin + oldfst - 1 < *dol) {
  437. /* Get representation from the left end of Z array */
  438. j = *dol - 1;
  439. } else if (wbegin + oldfst - 1 > *dou) {
  440. /* Get representation from the right end of Z array */
  441. j = *dou;
  442. } else {
  443. j = wbegin + oldfst - 1;
  444. }
  445. }
  446. _starpu_dcopy_(&in, &z__[ibegin + j * z_dim1], &c__1, &d__[ibegin]
  447. , &c__1);
  448. i__3 = in - 1;
  449. _starpu_dcopy_(&i__3, &z__[ibegin + (j + 1) * z_dim1], &c__1, &l[
  450. ibegin], &c__1);
  451. sigma = z__[iend + (j + 1) * z_dim1];
  452. /* Set the corresponding entries in Z to zero */
  453. _starpu_dlaset_("Full", &in, &c__2, &c_b5, &c_b5, &z__[ibegin + j
  454. * z_dim1], ldz);
  455. }
  456. /* Compute DL and DLL of current RRR */
  457. i__3 = iend - 1;
  458. for (j = ibegin; j <= i__3; ++j) {
  459. tmp = d__[j] * l[j];
  460. work[indld - 1 + j] = tmp;
  461. work[indlld - 1 + j] = tmp * l[j];
  462. /* L50: */
  463. }
  464. if (ndepth > 0) {
  465. /* P and Q are index of the first and last eigenvalue to compute */
  466. /* within the current block */
  467. p = indexw[wbegin - 1 + oldfst];
  468. q = indexw[wbegin - 1 + oldlst];
  469. /* Offset for the arrays WORK, WGAP and WERR, i.e., th P-OFFSET */
  470. /* thru' Q-OFFSET elements of these arrays are to be used. */
  471. /* OFFSET = P-OLDFST */
  472. offset = indexw[wbegin] - 1;
  473. /* perform limited bisection (if necessary) to get approximate */
  474. /* eigenvalues to the precision needed. */
  475. _starpu_dlarrb_(&in, &d__[ibegin], &work[indlld + ibegin - 1], &p,
  476. &q, rtol1, rtol2, &offset, &work[wbegin], &wgap[
  477. wbegin], &werr[wbegin], &work[indwrk], &iwork[
  478. iindwk], pivmin, &spdiam, &in, &iinfo);
  479. if (iinfo != 0) {
  480. *info = -1;
  481. return 0;
  482. }
  483. /* We also recompute the extremal gaps. W holds all eigenvalues */
  484. /* of the unshifted matrix and must be used for computation */
  485. /* of WGAP, the entries of WORK might stem from RRRs with */
  486. /* different shifts. The gaps from WBEGIN-1+OLDFST to */
  487. /* WBEGIN-1+OLDLST are correctly computed in DLARRB. */
  488. /* However, we only allow the gaps to become greater since */
  489. /* this is what should happen when we decrease WERR */
  490. if (oldfst > 1) {
  491. /* Computing MAX */
  492. d__1 = wgap[wbegin + oldfst - 2], d__2 = w[wbegin +
  493. oldfst - 1] - werr[wbegin + oldfst - 1] - w[
  494. wbegin + oldfst - 2] - werr[wbegin + oldfst -
  495. 2];
  496. wgap[wbegin + oldfst - 2] = max(d__1,d__2);
  497. }
  498. if (wbegin + oldlst - 1 < wend) {
  499. /* Computing MAX */
  500. d__1 = wgap[wbegin + oldlst - 1], d__2 = w[wbegin +
  501. oldlst] - werr[wbegin + oldlst] - w[wbegin +
  502. oldlst - 1] - werr[wbegin + oldlst - 1];
  503. wgap[wbegin + oldlst - 1] = max(d__1,d__2);
  504. }
  505. /* Each time the eigenvalues in WORK get refined, we store */
  506. /* the newly found approximation with all shifts applied in W */
  507. i__3 = oldlst;
  508. for (j = oldfst; j <= i__3; ++j) {
  509. w[wbegin + j - 1] = work[wbegin + j - 1] + sigma;
  510. /* L53: */
  511. }
  512. }
  513. /* Process the current node. */
  514. newfst = oldfst;
  515. i__3 = oldlst;
  516. for (j = oldfst; j <= i__3; ++j) {
  517. if (j == oldlst) {
  518. /* we are at the right end of the cluster, this is also the */
  519. /* boundary of the child cluster */
  520. newlst = j;
  521. } else if (wgap[wbegin + j - 1] >= *minrgp * (d__1 = work[
  522. wbegin + j - 1], abs(d__1))) {
  523. /* the right relative gap is big enough, the child cluster */
  524. /* (NEWFST,..,NEWLST) is well separated from the following */
  525. newlst = j;
  526. } else {
  527. /* inside a child cluster, the relative gap is not */
  528. /* big enough. */
  529. goto L140;
  530. }
  531. /* Compute size of child cluster found */
  532. newsiz = newlst - newfst + 1;
  533. /* NEWFTT is the place in Z where the new RRR or the computed */
  534. /* eigenvector is to be stored */
  535. if (*dol == 1 && *dou == *m) {
  536. /* Store representation at location of the leftmost evalue */
  537. /* of the cluster */
  538. newftt = wbegin + newfst - 1;
  539. } else {
  540. if (wbegin + newfst - 1 < *dol) {
  541. /* Store representation at the left end of Z array */
  542. newftt = *dol - 1;
  543. } else if (wbegin + newfst - 1 > *dou) {
  544. /* Store representation at the right end of Z array */
  545. newftt = *dou;
  546. } else {
  547. newftt = wbegin + newfst - 1;
  548. }
  549. }
  550. if (newsiz > 1) {
  551. /* Current child is not a singleton but a cluster. */
  552. /* Compute and store new representation of child. */
  553. /* Compute left and right cluster gap. */
  554. /* LGAP and RGAP are not computed from WORK because */
  555. /* the eigenvalue approximations may stem from RRRs */
  556. /* different shifts. However, W hold all eigenvalues */
  557. /* of the unshifted matrix. Still, the entries in WGAP */
  558. /* have to be computed from WORK since the entries */
  559. /* in W might be of the same order so that gaps are not */
  560. /* exhibited correctly for very close eigenvalues. */
  561. if (newfst == 1) {
  562. /* Computing MAX */
  563. d__1 = 0., d__2 = w[wbegin] - werr[wbegin] - *vl;
  564. lgap = max(d__1,d__2);
  565. } else {
  566. lgap = wgap[wbegin + newfst - 2];
  567. }
  568. rgap = wgap[wbegin + newlst - 1];
  569. /* Compute left- and rightmost eigenvalue of child */
  570. /* to high precision in order to shift as close */
  571. /* as possible and obtain as large relative gaps */
  572. /* as possible */
  573. for (k = 1; k <= 2; ++k) {
  574. if (k == 1) {
  575. p = indexw[wbegin - 1 + newfst];
  576. } else {
  577. p = indexw[wbegin - 1 + newlst];
  578. }
  579. offset = indexw[wbegin] - 1;
  580. _starpu_dlarrb_(&in, &d__[ibegin], &work[indlld + ibegin
  581. - 1], &p, &p, &rqtol, &rqtol, &offset, &
  582. work[wbegin], &wgap[wbegin], &werr[wbegin]
  583. , &work[indwrk], &iwork[iindwk], pivmin, &
  584. spdiam, &in, &iinfo);
  585. /* L55: */
  586. }
  587. if (wbegin + newlst - 1 < *dol || wbegin + newfst - 1
  588. > *dou) {
  589. /* if the cluster contains no desired eigenvalues */
  590. /* skip the computation of that branch of the rep. tree */
  591. /* We could skip before the refinement of the extremal */
  592. /* eigenvalues of the child, but then the representation */
  593. /* tree could be different from the one when nothing is */
  594. /* skipped. For this reason we skip at this place. */
  595. idone = idone + newlst - newfst + 1;
  596. goto L139;
  597. }
  598. /* Compute RRR of child cluster. */
  599. /* Note that the new RRR is stored in Z */
  600. /* DLARRF needs LWORK = 2*N */
  601. _starpu_dlarrf_(&in, &d__[ibegin], &l[ibegin], &work[indld +
  602. ibegin - 1], &newfst, &newlst, &work[wbegin],
  603. &wgap[wbegin], &werr[wbegin], &spdiam, &lgap,
  604. &rgap, pivmin, &tau, &z__[ibegin + newftt *
  605. z_dim1], &z__[ibegin + (newftt + 1) * z_dim1],
  606. &work[indwrk], &iinfo);
  607. if (iinfo == 0) {
  608. /* a new RRR for the cluster was found by DLARRF */
  609. /* update shift and store it */
  610. ssigma = sigma + tau;
  611. z__[iend + (newftt + 1) * z_dim1] = ssigma;
  612. /* WORK() are the midpoints and WERR() the semi-width */
  613. /* Note that the entries in W are unchanged. */
  614. i__4 = newlst;
  615. for (k = newfst; k <= i__4; ++k) {
  616. fudge = eps * 3. * (d__1 = work[wbegin + k -
  617. 1], abs(d__1));
  618. work[wbegin + k - 1] -= tau;
  619. fudge += eps * 4. * (d__1 = work[wbegin + k -
  620. 1], abs(d__1));
  621. /* Fudge errors */
  622. werr[wbegin + k - 1] += fudge;
  623. /* Gaps are not fudged. Provided that WERR is small */
  624. /* when eigenvalues are close, a zero gap indicates */
  625. /* that a new representation is needed for resolving */
  626. /* the cluster. A fudge could lead to a wrong decision */
  627. /* of judging eigenvalues 'separated' which in */
  628. /* reality are not. This could have a negative impact */
  629. /* on the orthogonality of the computed eigenvectors. */
  630. /* L116: */
  631. }
  632. ++nclus;
  633. k = newcls + (nclus << 1);
  634. iwork[k - 1] = newfst;
  635. iwork[k] = newlst;
  636. } else {
  637. *info = -2;
  638. return 0;
  639. }
  640. } else {
  641. /* Compute eigenvector of singleton */
  642. iter = 0;
  643. tol = log((doublereal) in) * 4. * eps;
  644. k = newfst;
  645. windex = wbegin + k - 1;
  646. /* Computing MAX */
  647. i__4 = windex - 1;
  648. windmn = max(i__4,1);
  649. /* Computing MIN */
  650. i__4 = windex + 1;
  651. windpl = min(i__4,*m);
  652. lambda = work[windex];
  653. ++done;
  654. /* Check if eigenvector computation is to be skipped */
  655. if (windex < *dol || windex > *dou) {
  656. eskip = TRUE_;
  657. goto L125;
  658. } else {
  659. eskip = FALSE_;
  660. }
  661. left = work[windex] - werr[windex];
  662. right = work[windex] + werr[windex];
  663. indeig = indexw[windex];
  664. /* Note that since we compute the eigenpairs for a child, */
  665. /* all eigenvalue approximations are w.r.t the same shift. */
  666. /* In this case, the entries in WORK should be used for */
  667. /* computing the gaps since they exhibit even very small */
  668. /* differences in the eigenvalues, as opposed to the */
  669. /* entries in W which might "look" the same. */
  670. if (k == 1) {
  671. /* In the case RANGE='I' and with not much initial */
  672. /* accuracy in LAMBDA and VL, the formula */
  673. /* LGAP = MAX( ZERO, (SIGMA - VL) + LAMBDA ) */
  674. /* can lead to an overestimation of the left gap and */
  675. /* thus to inadequately early RQI 'convergence'. */
  676. /* Prevent this by forcing a small left gap. */
  677. /* Computing MAX */
  678. d__1 = abs(left), d__2 = abs(right);
  679. lgap = eps * max(d__1,d__2);
  680. } else {
  681. lgap = wgap[windmn];
  682. }
  683. if (k == im) {
  684. /* In the case RANGE='I' and with not much initial */
  685. /* accuracy in LAMBDA and VU, the formula */
  686. /* can lead to an overestimation of the right gap and */
  687. /* thus to inadequately early RQI 'convergence'. */
  688. /* Prevent this by forcing a small right gap. */
  689. /* Computing MAX */
  690. d__1 = abs(left), d__2 = abs(right);
  691. rgap = eps * max(d__1,d__2);
  692. } else {
  693. rgap = wgap[windex];
  694. }
  695. gap = min(lgap,rgap);
  696. if (k == 1 || k == im) {
  697. /* The eigenvector support can become wrong */
  698. /* because significant entries could be cut off due to a */
  699. /* large GAPTOL parameter in LAR1V. Prevent this. */
  700. gaptol = 0.;
  701. } else {
  702. gaptol = gap * eps;
  703. }
  704. isupmn = in;
  705. isupmx = 1;
  706. /* Update WGAP so that it holds the minimum gap */
  707. /* to the left or the right. This is crucial in the */
  708. /* case where bisection is used to ensure that the */
  709. /* eigenvalue is refined up to the required precision. */
  710. /* The correct value is restored afterwards. */
  711. savgap = wgap[windex];
  712. wgap[windex] = gap;
  713. /* We want to use the Rayleigh Quotient Correction */
  714. /* as often as possible since it converges quadratically */
  715. /* when we are close enough to the desired eigenvalue. */
  716. /* However, the Rayleigh Quotient can have the wrong sign */
  717. /* and lead us away from the desired eigenvalue. In this */
  718. /* case, the best we can do is to use bisection. */
  719. usedbs = FALSE_;
  720. usedrq = FALSE_;
  721. /* Bisection is initially turned off unless it is forced */
  722. needbs = ! tryrqc;
  723. L120:
  724. /* Check if bisection should be used to refine eigenvalue */
  725. if (needbs) {
  726. /* Take the bisection as new iterate */
  727. usedbs = TRUE_;
  728. itmp1 = iwork[iindr + windex];
  729. offset = indexw[wbegin] - 1;
  730. d__1 = eps * 2.;
  731. _starpu_dlarrb_(&in, &d__[ibegin], &work[indlld + ibegin
  732. - 1], &indeig, &indeig, &c_b5, &d__1, &
  733. offset, &work[wbegin], &wgap[wbegin], &
  734. werr[wbegin], &work[indwrk], &iwork[
  735. iindwk], pivmin, &spdiam, &itmp1, &iinfo);
  736. if (iinfo != 0) {
  737. *info = -3;
  738. return 0;
  739. }
  740. lambda = work[windex];
  741. /* Reset twist index from inaccurate LAMBDA to */
  742. /* force computation of true MINGMA */
  743. iwork[iindr + windex] = 0;
  744. }
  745. /* Given LAMBDA, compute the eigenvector. */
  746. L__1 = ! usedbs;
  747. _starpu_dlar1v_(&in, &c__1, &in, &lambda, &d__[ibegin], &l[
  748. ibegin], &work[indld + ibegin - 1], &work[
  749. indlld + ibegin - 1], pivmin, &gaptol, &z__[
  750. ibegin + windex * z_dim1], &L__1, &negcnt, &
  751. ztz, &mingma, &iwork[iindr + windex], &isuppz[
  752. (windex << 1) - 1], &nrminv, &resid, &rqcorr,
  753. &work[indwrk]);
  754. if (iter == 0) {
  755. bstres = resid;
  756. bstw = lambda;
  757. } else if (resid < bstres) {
  758. bstres = resid;
  759. bstw = lambda;
  760. }
  761. /* Computing MIN */
  762. i__4 = isupmn, i__5 = isuppz[(windex << 1) - 1];
  763. isupmn = min(i__4,i__5);
  764. /* Computing MAX */
  765. i__4 = isupmx, i__5 = isuppz[windex * 2];
  766. isupmx = max(i__4,i__5);
  767. ++iter;
  768. /* sin alpha <= |resid|/gap */
  769. /* Note that both the residual and the gap are */
  770. /* proportional to the matrix, so ||T|| doesn't play */
  771. /* a role in the quotient */
  772. /* Convergence test for Rayleigh-Quotient iteration */
  773. /* (omitted when Bisection has been used) */
  774. if (resid > tol * gap && abs(rqcorr) > rqtol * abs(
  775. lambda) && ! usedbs) {
  776. /* We need to check that the RQCORR update doesn't */
  777. /* move the eigenvalue away from the desired one and */
  778. /* towards a neighbor. -> protection with bisection */
  779. if (indeig <= negcnt) {
  780. /* The wanted eigenvalue lies to the left */
  781. sgndef = -1.;
  782. } else {
  783. /* The wanted eigenvalue lies to the right */
  784. sgndef = 1.;
  785. }
  786. /* We only use the RQCORR if it improves the */
  787. /* the iterate reasonably. */
  788. if (rqcorr * sgndef >= 0. && lambda + rqcorr <=
  789. right && lambda + rqcorr >= left) {
  790. usedrq = TRUE_;
  791. /* Store new midpoint of bisection interval in WORK */
  792. if (sgndef == 1.) {
  793. /* The current LAMBDA is on the left of the true */
  794. /* eigenvalue */
  795. left = lambda;
  796. /* We prefer to assume that the error estimate */
  797. /* is correct. We could make the interval not */
  798. /* as a bracket but to be modified if the RQCORR */
  799. /* chooses to. In this case, the RIGHT side should */
  800. /* be modified as follows: */
  801. /* RIGHT = MAX(RIGHT, LAMBDA + RQCORR) */
  802. } else {
  803. /* The current LAMBDA is on the right of the true */
  804. /* eigenvalue */
  805. right = lambda;
  806. /* See comment about assuming the error estimate is */
  807. /* correct above. */
  808. /* LEFT = MIN(LEFT, LAMBDA + RQCORR) */
  809. }
  810. work[windex] = (right + left) * .5;
  811. /* Take RQCORR since it has the correct sign and */
  812. /* improves the iterate reasonably */
  813. lambda += rqcorr;
  814. /* Update width of error interval */
  815. werr[windex] = (right - left) * .5;
  816. } else {
  817. needbs = TRUE_;
  818. }
  819. if (right - left < rqtol * abs(lambda)) {
  820. /* The eigenvalue is computed to bisection accuracy */
  821. /* compute eigenvector and stop */
  822. usedbs = TRUE_;
  823. goto L120;
  824. } else if (iter < 10) {
  825. goto L120;
  826. } else if (iter == 10) {
  827. needbs = TRUE_;
  828. goto L120;
  829. } else {
  830. *info = 5;
  831. return 0;
  832. }
  833. } else {
  834. stp2ii = FALSE_;
  835. if (usedrq && usedbs && bstres <= resid) {
  836. lambda = bstw;
  837. stp2ii = TRUE_;
  838. }
  839. if (stp2ii) {
  840. /* improve error angle by second step */
  841. L__1 = ! usedbs;
  842. _starpu_dlar1v_(&in, &c__1, &in, &lambda, &d__[ibegin]
  843. , &l[ibegin], &work[indld + ibegin -
  844. 1], &work[indlld + ibegin - 1],
  845. pivmin, &gaptol, &z__[ibegin + windex
  846. * z_dim1], &L__1, &negcnt, &ztz, &
  847. mingma, &iwork[iindr + windex], &
  848. isuppz[(windex << 1) - 1], &nrminv, &
  849. resid, &rqcorr, &work[indwrk]);
  850. }
  851. work[windex] = lambda;
  852. }
  853. /* Compute FP-vector support w.r.t. whole matrix */
  854. isuppz[(windex << 1) - 1] += oldien;
  855. isuppz[windex * 2] += oldien;
  856. zfrom = isuppz[(windex << 1) - 1];
  857. zto = isuppz[windex * 2];
  858. isupmn += oldien;
  859. isupmx += oldien;
  860. /* Ensure vector is ok if support in the RQI has changed */
  861. if (isupmn < zfrom) {
  862. i__4 = zfrom - 1;
  863. for (ii = isupmn; ii <= i__4; ++ii) {
  864. z__[ii + windex * z_dim1] = 0.;
  865. /* L122: */
  866. }
  867. }
  868. if (isupmx > zto) {
  869. i__4 = isupmx;
  870. for (ii = zto + 1; ii <= i__4; ++ii) {
  871. z__[ii + windex * z_dim1] = 0.;
  872. /* L123: */
  873. }
  874. }
  875. i__4 = zto - zfrom + 1;
  876. _starpu_dscal_(&i__4, &nrminv, &z__[zfrom + windex * z_dim1],
  877. &c__1);
  878. L125:
  879. /* Update W */
  880. w[windex] = lambda + sigma;
  881. /* Recompute the gaps on the left and right */
  882. /* But only allow them to become larger and not */
  883. /* smaller (which can only happen through "bad" */
  884. /* cancellation and doesn't reflect the theory */
  885. /* where the initial gaps are underestimated due */
  886. /* to WERR being too crude.) */
  887. if (! eskip) {
  888. if (k > 1) {
  889. /* Computing MAX */
  890. d__1 = wgap[windmn], d__2 = w[windex] - werr[
  891. windex] - w[windmn] - werr[windmn];
  892. wgap[windmn] = max(d__1,d__2);
  893. }
  894. if (windex < wend) {
  895. /* Computing MAX */
  896. d__1 = savgap, d__2 = w[windpl] - werr[windpl]
  897. - w[windex] - werr[windex];
  898. wgap[windex] = max(d__1,d__2);
  899. }
  900. }
  901. ++idone;
  902. }
  903. /* here ends the code for the current child */
  904. L139:
  905. /* Proceed to any remaining child nodes */
  906. newfst = j + 1;
  907. L140:
  908. ;
  909. }
  910. /* L150: */
  911. }
  912. ++ndepth;
  913. goto L40;
  914. }
  915. ibegin = iend + 1;
  916. wbegin = wend + 1;
  917. L170:
  918. ;
  919. }
  920. return 0;
  921. /* End of DLARRV */
  922. } /* _starpu_dlarrv_ */