dlarrd.c 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794
  1. /* dlarrd.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__1 = 1;
  15. static integer c_n1 = -1;
  16. static integer c__3 = 3;
  17. static integer c__2 = 2;
  18. static integer c__0 = 0;
  19. /* Subroutine */ int _starpu_dlarrd_(char *range, char *order, integer *n, doublereal
  20. *vl, doublereal *vu, integer *il, integer *iu, doublereal *gers,
  21. doublereal *reltol, doublereal *d__, doublereal *e, doublereal *e2,
  22. doublereal *pivmin, integer *nsplit, integer *isplit, integer *m,
  23. doublereal *w, doublereal *werr, doublereal *wl, doublereal *wu,
  24. integer *iblock, integer *indexw, doublereal *work, integer *iwork,
  25. integer *info)
  26. {
  27. /* System generated locals */
  28. integer i__1, i__2, i__3;
  29. doublereal d__1, d__2;
  30. /* Builtin functions */
  31. double log(doublereal);
  32. /* Local variables */
  33. integer i__, j, ib, ie, je, nb;
  34. doublereal gl;
  35. integer im, in;
  36. doublereal gu;
  37. integer iw, jee;
  38. doublereal eps;
  39. integer nwl;
  40. doublereal wlu, wul;
  41. integer nwu;
  42. doublereal tmp1, tmp2;
  43. integer iend, jblk, ioff, iout, itmp1, itmp2, jdisc;
  44. extern logical _starpu_lsame_(char *, char *);
  45. integer iinfo;
  46. doublereal atoli;
  47. integer iwoff, itmax;
  48. doublereal wkill, rtoli, uflow, tnorm;
  49. extern doublereal _starpu_dlamch_(char *);
  50. integer ibegin;
  51. extern /* Subroutine */ int _starpu_dlaebz_(integer *, integer *, integer *,
  52. integer *, integer *, integer *, doublereal *, doublereal *,
  53. doublereal *, doublereal *, doublereal *, doublereal *, integer *,
  54. doublereal *, doublereal *, integer *, integer *, doublereal *,
  55. integer *, integer *);
  56. integer irange, idiscl, idumma[1];
  57. extern integer _starpu_ilaenv_(integer *, char *, char *, integer *, integer *,
  58. integer *, integer *);
  59. integer idiscu;
  60. logical ncnvrg, toofew;
  61. /* -- LAPACK auxiliary routine (version 3.2.1) -- */
  62. /* -- LAPACK is a software package provided by Univ. of Tennessee, -- */
  63. /* -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..-- */
  64. /* -- April 2009 -- */
  65. /* .. Scalar Arguments .. */
  66. /* .. */
  67. /* .. Array Arguments .. */
  68. /* .. */
  69. /* Purpose */
  70. /* ======= */
  71. /* DLARRD computes the eigenvalues of a symmetric tridiagonal */
  72. /* matrix T to suitable accuracy. This is an auxiliary code to be */
  73. /* called from DSTEMR. */
  74. /* The user may ask for all eigenvalues, all eigenvalues */
  75. /* in the half-open interval (VL, VU], or the IL-th through IU-th */
  76. /* eigenvalues. */
  77. /* To avoid overflow, the matrix must be scaled so that its */
  78. /* largest element is no greater than overflow**(1/2) * */
  79. /* underflow**(1/4) in absolute value, and for greatest */
  80. /* accuracy, it should not be much smaller than that. */
  81. /* See W. Kahan "Accurate Eigenvalues of a Symmetric Tridiagonal */
  82. /* Matrix", Report CS41, Computer Science Dept., Stanford */
  83. /* University, July 21, 1966. */
  84. /* Arguments */
  85. /* ========= */
  86. /* RANGE (input) CHARACTER */
  87. /* = 'A': ("All") all eigenvalues will be found. */
  88. /* = 'V': ("Value") all eigenvalues in the half-open interval */
  89. /* (VL, VU] will be found. */
  90. /* = 'I': ("Index") the IL-th through IU-th eigenvalues (of the */
  91. /* entire matrix) will be found. */
  92. /* ORDER (input) CHARACTER */
  93. /* = 'B': ("By Block") the eigenvalues will be grouped by */
  94. /* split-off block (see IBLOCK, ISPLIT) and */
  95. /* ordered from smallest to largest within */
  96. /* the block. */
  97. /* = 'E': ("Entire matrix") */
  98. /* the eigenvalues for the entire matrix */
  99. /* will be ordered from smallest to */
  100. /* largest. */
  101. /* N (input) INTEGER */
  102. /* The order of the tridiagonal matrix T. N >= 0. */
  103. /* VL (input) DOUBLE PRECISION */
  104. /* VU (input) DOUBLE PRECISION */
  105. /* If RANGE='V', the lower and upper bounds of the interval to */
  106. /* be searched for eigenvalues. Eigenvalues less than or equal */
  107. /* to VL, or greater than VU, will not be returned. VL < VU. */
  108. /* Not referenced if RANGE = 'A' or 'I'. */
  109. /* IL (input) INTEGER */
  110. /* IU (input) INTEGER */
  111. /* If RANGE='I', the indices (in ascending order) of the */
  112. /* smallest and largest eigenvalues to be returned. */
  113. /* 1 <= IL <= IU <= N, if N > 0; IL = 1 and IU = 0 if N = 0. */
  114. /* Not referenced if RANGE = 'A' or 'V'. */
  115. /* GERS (input) DOUBLE PRECISION array, dimension (2*N) */
  116. /* The N Gerschgorin intervals (the i-th Gerschgorin interval */
  117. /* is (GERS(2*i-1), GERS(2*i)). */
  118. /* RELTOL (input) DOUBLE PRECISION */
  119. /* The minimum relative width of an interval. When an interval */
  120. /* is narrower than RELTOL times the larger (in */
  121. /* magnitude) endpoint, then it is considered to be */
  122. /* sufficiently small, i.e., converged. Note: this should */
  123. /* always be at least radix*machine epsilon. */
  124. /* D (input) DOUBLE PRECISION array, dimension (N) */
  125. /* The n diagonal elements of the tridiagonal matrix T. */
  126. /* E (input) DOUBLE PRECISION array, dimension (N-1) */
  127. /* The (n-1) off-diagonal elements of the tridiagonal matrix T. */
  128. /* E2 (input) DOUBLE PRECISION array, dimension (N-1) */
  129. /* The (n-1) squared off-diagonal elements of the tridiagonal matrix T. */
  130. /* PIVMIN (input) DOUBLE PRECISION */
  131. /* The minimum pivot allowed in the Sturm sequence for T. */
  132. /* NSPLIT (input) INTEGER */
  133. /* The number of diagonal blocks in the matrix T. */
  134. /* 1 <= NSPLIT <= N. */
  135. /* ISPLIT (input) INTEGER array, dimension (N) */
  136. /* The splitting points, at which T breaks up into submatrices. */
  137. /* The first submatrix consists of rows/columns 1 to ISPLIT(1), */
  138. /* the second of rows/columns ISPLIT(1)+1 through ISPLIT(2), */
  139. /* etc., and the NSPLIT-th consists of rows/columns */
  140. /* ISPLIT(NSPLIT-1)+1 through ISPLIT(NSPLIT)=N. */
  141. /* (Only the first NSPLIT elements will actually be used, but */
  142. /* since the user cannot know a priori what value NSPLIT will */
  143. /* have, N words must be reserved for ISPLIT.) */
  144. /* M (output) INTEGER */
  145. /* The actual number of eigenvalues found. 0 <= M <= N. */
  146. /* (See also the description of INFO=2,3.) */
  147. /* W (output) DOUBLE PRECISION array, dimension (N) */
  148. /* On exit, the first M elements of W will contain the */
  149. /* eigenvalue approximations. DLARRD computes an interval */
  150. /* I_j = (a_j, b_j] that includes eigenvalue j. The eigenvalue */
  151. /* approximation is given as the interval midpoint */
  152. /* W(j)= ( a_j + b_j)/2. The corresponding error is bounded by */
  153. /* WERR(j) = abs( a_j - b_j)/2 */
  154. /* WERR (output) DOUBLE PRECISION array, dimension (N) */
  155. /* The error bound on the corresponding eigenvalue approximation */
  156. /* in W. */
  157. /* WL (output) DOUBLE PRECISION */
  158. /* WU (output) DOUBLE PRECISION */
  159. /* The interval (WL, WU] contains all the wanted eigenvalues. */
  160. /* If RANGE='V', then WL=VL and WU=VU. */
  161. /* If RANGE='A', then WL and WU are the global Gerschgorin bounds */
  162. /* on the spectrum. */
  163. /* If RANGE='I', then WL and WU are computed by DLAEBZ from the */
  164. /* index range specified. */
  165. /* IBLOCK (output) INTEGER array, dimension (N) */
  166. /* At each row/column j where E(j) is zero or small, the */
  167. /* matrix T is considered to split into a block diagonal */
  168. /* matrix. On exit, if INFO = 0, IBLOCK(i) specifies to which */
  169. /* block (from 1 to the number of blocks) the eigenvalue W(i) */
  170. /* belongs. (DLARRD may use the remaining N-M elements as */
  171. /* workspace.) */
  172. /* INDEXW (output) INTEGER array, dimension (N) */
  173. /* The indices of the eigenvalues within each block (submatrix); */
  174. /* for example, INDEXW(i)= j and IBLOCK(i)=k imply that the */
  175. /* i-th eigenvalue W(i) is the j-th eigenvalue in block k. */
  176. /* WORK (workspace) DOUBLE PRECISION array, dimension (4*N) */
  177. /* IWORK (workspace) INTEGER array, dimension (3*N) */
  178. /* INFO (output) INTEGER */
  179. /* = 0: successful exit */
  180. /* < 0: if INFO = -i, the i-th argument had an illegal value */
  181. /* > 0: some or all of the eigenvalues failed to converge or */
  182. /* were not computed: */
  183. /* =1 or 3: Bisection failed to converge for some */
  184. /* eigenvalues; these eigenvalues are flagged by a */
  185. /* negative block number. The effect is that the */
  186. /* eigenvalues may not be as accurate as the */
  187. /* absolute and relative tolerances. This is */
  188. /* generally caused by unexpectedly inaccurate */
  189. /* arithmetic. */
  190. /* =2 or 3: RANGE='I' only: Not all of the eigenvalues */
  191. /* IL:IU were found. */
  192. /* Effect: M < IU+1-IL */
  193. /* Cause: non-monotonic arithmetic, causing the */
  194. /* Sturm sequence to be non-monotonic. */
  195. /* Cure: recalculate, using RANGE='A', and pick */
  196. /* out eigenvalues IL:IU. In some cases, */
  197. /* increasing the PARAMETER "FUDGE" may */
  198. /* make things work. */
  199. /* = 4: RANGE='I', and the Gershgorin interval */
  200. /* initially used was too small. No eigenvalues */
  201. /* were computed. */
  202. /* Probable cause: your machine has sloppy */
  203. /* floating-point arithmetic. */
  204. /* Cure: Increase the PARAMETER "FUDGE", */
  205. /* recompile, and try again. */
  206. /* Internal Parameters */
  207. /* =================== */
  208. /* FUDGE DOUBLE PRECISION, default = 2 */
  209. /* A "fudge factor" to widen the Gershgorin intervals. Ideally, */
  210. /* a value of 1 should work, but on machines with sloppy */
  211. /* arithmetic, this needs to be larger. The default for */
  212. /* publicly released versions should be large enough to handle */
  213. /* the worst machine around. Note that this has no effect */
  214. /* on accuracy of the solution. */
  215. /* Based on contributions by */
  216. /* W. Kahan, University of California, Berkeley, USA */
  217. /* Beresford Parlett, University of California, Berkeley, USA */
  218. /* Jim Demmel, University of California, Berkeley, USA */
  219. /* Inderjit Dhillon, University of Texas, Austin, USA */
  220. /* Osni Marques, LBNL/NERSC, USA */
  221. /* Christof Voemel, University of California, Berkeley, USA */
  222. /* ===================================================================== */
  223. /* .. Parameters .. */
  224. /* .. */
  225. /* .. Local Scalars .. */
  226. /* .. */
  227. /* .. Local Arrays .. */
  228. /* .. */
  229. /* .. External Functions .. */
  230. /* .. */
  231. /* .. External Subroutines .. */
  232. /* .. */
  233. /* .. Intrinsic Functions .. */
  234. /* .. */
  235. /* .. Executable Statements .. */
  236. /* Parameter adjustments */
  237. --iwork;
  238. --work;
  239. --indexw;
  240. --iblock;
  241. --werr;
  242. --w;
  243. --isplit;
  244. --e2;
  245. --e;
  246. --d__;
  247. --gers;
  248. /* Function Body */
  249. *info = 0;
  250. /* Decode RANGE */
  251. if (_starpu_lsame_(range, "A")) {
  252. irange = 1;
  253. } else if (_starpu_lsame_(range, "V")) {
  254. irange = 2;
  255. } else if (_starpu_lsame_(range, "I")) {
  256. irange = 3;
  257. } else {
  258. irange = 0;
  259. }
  260. /* Check for Errors */
  261. if (irange <= 0) {
  262. *info = -1;
  263. } else if (! (_starpu_lsame_(order, "B") || _starpu_lsame_(order,
  264. "E"))) {
  265. *info = -2;
  266. } else if (*n < 0) {
  267. *info = -3;
  268. } else if (irange == 2) {
  269. if (*vl >= *vu) {
  270. *info = -5;
  271. }
  272. } else if (irange == 3 && (*il < 1 || *il > max(1,*n))) {
  273. *info = -6;
  274. } else if (irange == 3 && (*iu < min(*n,*il) || *iu > *n)) {
  275. *info = -7;
  276. }
  277. if (*info != 0) {
  278. return 0;
  279. }
  280. /* Initialize error flags */
  281. *info = 0;
  282. ncnvrg = FALSE_;
  283. toofew = FALSE_;
  284. /* Quick return if possible */
  285. *m = 0;
  286. if (*n == 0) {
  287. return 0;
  288. }
  289. /* Simplification: */
  290. if (irange == 3 && *il == 1 && *iu == *n) {
  291. irange = 1;
  292. }
  293. /* Get machine constants */
  294. eps = _starpu_dlamch_("P");
  295. uflow = _starpu_dlamch_("U");
  296. /* Special Case when N=1 */
  297. /* Treat case of 1x1 matrix for quick return */
  298. if (*n == 1) {
  299. if (irange == 1 || irange == 2 && d__[1] > *vl && d__[1] <= *vu ||
  300. irange == 3 && *il == 1 && *iu == 1) {
  301. *m = 1;
  302. w[1] = d__[1];
  303. /* The computation error of the eigenvalue is zero */
  304. werr[1] = 0.;
  305. iblock[1] = 1;
  306. indexw[1] = 1;
  307. }
  308. return 0;
  309. }
  310. /* NB is the minimum vector length for vector bisection, or 0 */
  311. /* if only scalar is to be done. */
  312. nb = _starpu_ilaenv_(&c__1, "DSTEBZ", " ", n, &c_n1, &c_n1, &c_n1);
  313. if (nb <= 1) {
  314. nb = 0;
  315. }
  316. /* Find global spectral radius */
  317. gl = d__[1];
  318. gu = d__[1];
  319. i__1 = *n;
  320. for (i__ = 1; i__ <= i__1; ++i__) {
  321. /* Computing MIN */
  322. d__1 = gl, d__2 = gers[(i__ << 1) - 1];
  323. gl = min(d__1,d__2);
  324. /* Computing MAX */
  325. d__1 = gu, d__2 = gers[i__ * 2];
  326. gu = max(d__1,d__2);
  327. /* L5: */
  328. }
  329. /* Compute global Gerschgorin bounds and spectral diameter */
  330. /* Computing MAX */
  331. d__1 = abs(gl), d__2 = abs(gu);
  332. tnorm = max(d__1,d__2);
  333. gl = gl - tnorm * 2. * eps * *n - *pivmin * 4.;
  334. gu = gu + tnorm * 2. * eps * *n + *pivmin * 4.;
  335. /* [JAN/28/2009] remove the line below since SPDIAM variable not use */
  336. /* SPDIAM = GU - GL */
  337. /* Input arguments for DLAEBZ: */
  338. /* The relative tolerance. An interval (a,b] lies within */
  339. /* "relative tolerance" if b-a < RELTOL*max(|a|,|b|), */
  340. rtoli = *reltol;
  341. /* Set the absolute tolerance for interval convergence to zero to force */
  342. /* interval convergence based on relative size of the interval. */
  343. /* This is dangerous because intervals might not converge when RELTOL is */
  344. /* small. But at least a very small number should be selected so that for */
  345. /* strongly graded matrices, the code can get relatively accurate */
  346. /* eigenvalues. */
  347. atoli = uflow * 4. + *pivmin * 4.;
  348. if (irange == 3) {
  349. /* RANGE='I': Compute an interval containing eigenvalues */
  350. /* IL through IU. The initial interval [GL,GU] from the global */
  351. /* Gerschgorin bounds GL and GU is refined by DLAEBZ. */
  352. itmax = (integer) ((log(tnorm + *pivmin) - log(*pivmin)) / log(2.)) +
  353. 2;
  354. work[*n + 1] = gl;
  355. work[*n + 2] = gl;
  356. work[*n + 3] = gu;
  357. work[*n + 4] = gu;
  358. work[*n + 5] = gl;
  359. work[*n + 6] = gu;
  360. iwork[1] = -1;
  361. iwork[2] = -1;
  362. iwork[3] = *n + 1;
  363. iwork[4] = *n + 1;
  364. iwork[5] = *il - 1;
  365. iwork[6] = *iu;
  366. _starpu_dlaebz_(&c__3, &itmax, n, &c__2, &c__2, &nb, &atoli, &rtoli, pivmin, &
  367. d__[1], &e[1], &e2[1], &iwork[5], &work[*n + 1], &work[*n + 5]
  368. , &iout, &iwork[1], &w[1], &iblock[1], &iinfo);
  369. if (iinfo != 0) {
  370. *info = iinfo;
  371. return 0;
  372. }
  373. /* On exit, output intervals may not be ordered by ascending negcount */
  374. if (iwork[6] == *iu) {
  375. *wl = work[*n + 1];
  376. wlu = work[*n + 3];
  377. nwl = iwork[1];
  378. *wu = work[*n + 4];
  379. wul = work[*n + 2];
  380. nwu = iwork[4];
  381. } else {
  382. *wl = work[*n + 2];
  383. wlu = work[*n + 4];
  384. nwl = iwork[2];
  385. *wu = work[*n + 3];
  386. wul = work[*n + 1];
  387. nwu = iwork[3];
  388. }
  389. /* On exit, the interval [WL, WLU] contains a value with negcount NWL, */
  390. /* and [WUL, WU] contains a value with negcount NWU. */
  391. if (nwl < 0 || nwl >= *n || nwu < 1 || nwu > *n) {
  392. *info = 4;
  393. return 0;
  394. }
  395. } else if (irange == 2) {
  396. *wl = *vl;
  397. *wu = *vu;
  398. } else if (irange == 1) {
  399. *wl = gl;
  400. *wu = gu;
  401. }
  402. /* Find Eigenvalues -- Loop Over blocks and recompute NWL and NWU. */
  403. /* NWL accumulates the number of eigenvalues .le. WL, */
  404. /* NWU accumulates the number of eigenvalues .le. WU */
  405. *m = 0;
  406. iend = 0;
  407. *info = 0;
  408. nwl = 0;
  409. nwu = 0;
  410. i__1 = *nsplit;
  411. for (jblk = 1; jblk <= i__1; ++jblk) {
  412. ioff = iend;
  413. ibegin = ioff + 1;
  414. iend = isplit[jblk];
  415. in = iend - ioff;
  416. if (in == 1) {
  417. /* 1x1 block */
  418. if (*wl >= d__[ibegin] - *pivmin) {
  419. ++nwl;
  420. }
  421. if (*wu >= d__[ibegin] - *pivmin) {
  422. ++nwu;
  423. }
  424. if (irange == 1 || *wl < d__[ibegin] - *pivmin && *wu >= d__[
  425. ibegin] - *pivmin) {
  426. ++(*m);
  427. w[*m] = d__[ibegin];
  428. werr[*m] = 0.;
  429. /* The gap for a single block doesn't matter for the later */
  430. /* algorithm and is assigned an arbitrary large value */
  431. iblock[*m] = jblk;
  432. indexw[*m] = 1;
  433. }
  434. /* Disabled 2x2 case because of a failure on the following matrix */
  435. /* RANGE = 'I', IL = IU = 4 */
  436. /* Original Tridiagonal, d = [ */
  437. /* -0.150102010615740E+00 */
  438. /* -0.849897989384260E+00 */
  439. /* -0.128208148052635E-15 */
  440. /* 0.128257718286320E-15 */
  441. /* ]; */
  442. /* e = [ */
  443. /* -0.357171383266986E+00 */
  444. /* -0.180411241501588E-15 */
  445. /* -0.175152352710251E-15 */
  446. /* ]; */
  447. /* ELSE IF( IN.EQ.2 ) THEN */
  448. /* * 2x2 block */
  449. /* DISC = SQRT( (HALF*(D(IBEGIN)-D(IEND)))**2 + E(IBEGIN)**2 ) */
  450. /* TMP1 = HALF*(D(IBEGIN)+D(IEND)) */
  451. /* L1 = TMP1 - DISC */
  452. /* IF( WL.GE. L1-PIVMIN ) */
  453. /* $ NWL = NWL + 1 */
  454. /* IF( WU.GE. L1-PIVMIN ) */
  455. /* $ NWU = NWU + 1 */
  456. /* IF( IRANGE.EQ.ALLRNG .OR. ( WL.LT.L1-PIVMIN .AND. WU.GE. */
  457. /* $ L1-PIVMIN ) ) THEN */
  458. /* M = M + 1 */
  459. /* W( M ) = L1 */
  460. /* * The uncertainty of eigenvalues of a 2x2 matrix is very small */
  461. /* WERR( M ) = EPS * ABS( W( M ) ) * TWO */
  462. /* IBLOCK( M ) = JBLK */
  463. /* INDEXW( M ) = 1 */
  464. /* ENDIF */
  465. /* L2 = TMP1 + DISC */
  466. /* IF( WL.GE. L2-PIVMIN ) */
  467. /* $ NWL = NWL + 1 */
  468. /* IF( WU.GE. L2-PIVMIN ) */
  469. /* $ NWU = NWU + 1 */
  470. /* IF( IRANGE.EQ.ALLRNG .OR. ( WL.LT.L2-PIVMIN .AND. WU.GE. */
  471. /* $ L2-PIVMIN ) ) THEN */
  472. /* M = M + 1 */
  473. /* W( M ) = L2 */
  474. /* * The uncertainty of eigenvalues of a 2x2 matrix is very small */
  475. /* WERR( M ) = EPS * ABS( W( M ) ) * TWO */
  476. /* IBLOCK( M ) = JBLK */
  477. /* INDEXW( M ) = 2 */
  478. /* ENDIF */
  479. } else {
  480. /* General Case - block of size IN >= 2 */
  481. /* Compute local Gerschgorin interval and use it as the initial */
  482. /* interval for DLAEBZ */
  483. gu = d__[ibegin];
  484. gl = d__[ibegin];
  485. tmp1 = 0.;
  486. i__2 = iend;
  487. for (j = ibegin; j <= i__2; ++j) {
  488. /* Computing MIN */
  489. d__1 = gl, d__2 = gers[(j << 1) - 1];
  490. gl = min(d__1,d__2);
  491. /* Computing MAX */
  492. d__1 = gu, d__2 = gers[j * 2];
  493. gu = max(d__1,d__2);
  494. /* L40: */
  495. }
  496. /* [JAN/28/2009] */
  497. /* change SPDIAM by TNORM in lines 2 and 3 thereafter */
  498. /* line 1: remove computation of SPDIAM (not useful anymore) */
  499. /* SPDIAM = GU - GL */
  500. /* GL = GL - FUDGE*SPDIAM*EPS*IN - FUDGE*PIVMIN */
  501. /* GU = GU + FUDGE*SPDIAM*EPS*IN + FUDGE*PIVMIN */
  502. gl = gl - tnorm * 2. * eps * in - *pivmin * 2.;
  503. gu = gu + tnorm * 2. * eps * in + *pivmin * 2.;
  504. if (irange > 1) {
  505. if (gu < *wl) {
  506. /* the local block contains none of the wanted eigenvalues */
  507. nwl += in;
  508. nwu += in;
  509. goto L70;
  510. }
  511. /* refine search interval if possible, only range (WL,WU] matters */
  512. gl = max(gl,*wl);
  513. gu = min(gu,*wu);
  514. if (gl >= gu) {
  515. goto L70;
  516. }
  517. }
  518. /* Find negcount of initial interval boundaries GL and GU */
  519. work[*n + 1] = gl;
  520. work[*n + in + 1] = gu;
  521. _starpu_dlaebz_(&c__1, &c__0, &in, &in, &c__1, &nb, &atoli, &rtoli,
  522. pivmin, &d__[ibegin], &e[ibegin], &e2[ibegin], idumma, &
  523. work[*n + 1], &work[*n + (in << 1) + 1], &im, &iwork[1], &
  524. w[*m + 1], &iblock[*m + 1], &iinfo);
  525. if (iinfo != 0) {
  526. *info = iinfo;
  527. return 0;
  528. }
  529. nwl += iwork[1];
  530. nwu += iwork[in + 1];
  531. iwoff = *m - iwork[1];
  532. /* Compute Eigenvalues */
  533. itmax = (integer) ((log(gu - gl + *pivmin) - log(*pivmin)) / log(
  534. 2.)) + 2;
  535. _starpu_dlaebz_(&c__2, &itmax, &in, &in, &c__1, &nb, &atoli, &rtoli,
  536. pivmin, &d__[ibegin], &e[ibegin], &e2[ibegin], idumma, &
  537. work[*n + 1], &work[*n + (in << 1) + 1], &iout, &iwork[1],
  538. &w[*m + 1], &iblock[*m + 1], &iinfo);
  539. if (iinfo != 0) {
  540. *info = iinfo;
  541. return 0;
  542. }
  543. /* Copy eigenvalues into W and IBLOCK */
  544. /* Use -JBLK for block number for unconverged eigenvalues. */
  545. /* Loop over the number of output intervals from DLAEBZ */
  546. i__2 = iout;
  547. for (j = 1; j <= i__2; ++j) {
  548. /* eigenvalue approximation is middle point of interval */
  549. tmp1 = (work[j + *n] + work[j + in + *n]) * .5;
  550. /* semi length of error interval */
  551. tmp2 = (d__1 = work[j + *n] - work[j + in + *n], abs(d__1)) *
  552. .5;
  553. if (j > iout - iinfo) {
  554. /* Flag non-convergence. */
  555. ncnvrg = TRUE_;
  556. ib = -jblk;
  557. } else {
  558. ib = jblk;
  559. }
  560. i__3 = iwork[j + in] + iwoff;
  561. for (je = iwork[j] + 1 + iwoff; je <= i__3; ++je) {
  562. w[je] = tmp1;
  563. werr[je] = tmp2;
  564. indexw[je] = je - iwoff;
  565. iblock[je] = ib;
  566. /* L50: */
  567. }
  568. /* L60: */
  569. }
  570. *m += im;
  571. }
  572. L70:
  573. ;
  574. }
  575. /* If RANGE='I', then (WL,WU) contains eigenvalues NWL+1,...,NWU */
  576. /* If NWL+1 < IL or NWU > IU, discard extra eigenvalues. */
  577. if (irange == 3) {
  578. idiscl = *il - 1 - nwl;
  579. idiscu = nwu - *iu;
  580. if (idiscl > 0) {
  581. im = 0;
  582. i__1 = *m;
  583. for (je = 1; je <= i__1; ++je) {
  584. /* Remove some of the smallest eigenvalues from the left so that */
  585. /* at the end IDISCL =0. Move all eigenvalues up to the left. */
  586. if (w[je] <= wlu && idiscl > 0) {
  587. --idiscl;
  588. } else {
  589. ++im;
  590. w[im] = w[je];
  591. werr[im] = werr[je];
  592. indexw[im] = indexw[je];
  593. iblock[im] = iblock[je];
  594. }
  595. /* L80: */
  596. }
  597. *m = im;
  598. }
  599. if (idiscu > 0) {
  600. /* Remove some of the largest eigenvalues from the right so that */
  601. /* at the end IDISCU =0. Move all eigenvalues up to the left. */
  602. im = *m + 1;
  603. for (je = *m; je >= 1; --je) {
  604. if (w[je] >= wul && idiscu > 0) {
  605. --idiscu;
  606. } else {
  607. --im;
  608. w[im] = w[je];
  609. werr[im] = werr[je];
  610. indexw[im] = indexw[je];
  611. iblock[im] = iblock[je];
  612. }
  613. /* L81: */
  614. }
  615. jee = 0;
  616. i__1 = *m;
  617. for (je = im; je <= i__1; ++je) {
  618. ++jee;
  619. w[jee] = w[je];
  620. werr[jee] = werr[je];
  621. indexw[jee] = indexw[je];
  622. iblock[jee] = iblock[je];
  623. /* L82: */
  624. }
  625. *m = *m - im + 1;
  626. }
  627. if (idiscl > 0 || idiscu > 0) {
  628. /* Code to deal with effects of bad arithmetic. (If N(w) is */
  629. /* monotone non-decreasing, this should never happen.) */
  630. /* Some low eigenvalues to be discarded are not in (WL,WLU], */
  631. /* or high eigenvalues to be discarded are not in (WUL,WU] */
  632. /* so just kill off the smallest IDISCL/largest IDISCU */
  633. /* eigenvalues, by marking the corresponding IBLOCK = 0 */
  634. if (idiscl > 0) {
  635. wkill = *wu;
  636. i__1 = idiscl;
  637. for (jdisc = 1; jdisc <= i__1; ++jdisc) {
  638. iw = 0;
  639. i__2 = *m;
  640. for (je = 1; je <= i__2; ++je) {
  641. if (iblock[je] != 0 && (w[je] < wkill || iw == 0)) {
  642. iw = je;
  643. wkill = w[je];
  644. }
  645. /* L90: */
  646. }
  647. iblock[iw] = 0;
  648. /* L100: */
  649. }
  650. }
  651. if (idiscu > 0) {
  652. wkill = *wl;
  653. i__1 = idiscu;
  654. for (jdisc = 1; jdisc <= i__1; ++jdisc) {
  655. iw = 0;
  656. i__2 = *m;
  657. for (je = 1; je <= i__2; ++je) {
  658. if (iblock[je] != 0 && (w[je] >= wkill || iw == 0)) {
  659. iw = je;
  660. wkill = w[je];
  661. }
  662. /* L110: */
  663. }
  664. iblock[iw] = 0;
  665. /* L120: */
  666. }
  667. }
  668. /* Now erase all eigenvalues with IBLOCK set to zero */
  669. im = 0;
  670. i__1 = *m;
  671. for (je = 1; je <= i__1; ++je) {
  672. if (iblock[je] != 0) {
  673. ++im;
  674. w[im] = w[je];
  675. werr[im] = werr[je];
  676. indexw[im] = indexw[je];
  677. iblock[im] = iblock[je];
  678. }
  679. /* L130: */
  680. }
  681. *m = im;
  682. }
  683. if (idiscl < 0 || idiscu < 0) {
  684. toofew = TRUE_;
  685. }
  686. }
  687. if (irange == 1 && *m != *n || irange == 3 && *m != *iu - *il + 1) {
  688. toofew = TRUE_;
  689. }
  690. /* If ORDER='B', do nothing the eigenvalues are already sorted by */
  691. /* block. */
  692. /* If ORDER='E', sort the eigenvalues from smallest to largest */
  693. if (_starpu_lsame_(order, "E") && *nsplit > 1) {
  694. i__1 = *m - 1;
  695. for (je = 1; je <= i__1; ++je) {
  696. ie = 0;
  697. tmp1 = w[je];
  698. i__2 = *m;
  699. for (j = je + 1; j <= i__2; ++j) {
  700. if (w[j] < tmp1) {
  701. ie = j;
  702. tmp1 = w[j];
  703. }
  704. /* L140: */
  705. }
  706. if (ie != 0) {
  707. tmp2 = werr[ie];
  708. itmp1 = iblock[ie];
  709. itmp2 = indexw[ie];
  710. w[ie] = w[je];
  711. werr[ie] = werr[je];
  712. iblock[ie] = iblock[je];
  713. indexw[ie] = indexw[je];
  714. w[je] = tmp1;
  715. werr[je] = tmp2;
  716. iblock[je] = itmp1;
  717. indexw[je] = itmp2;
  718. }
  719. /* L150: */
  720. }
  721. }
  722. *info = 0;
  723. if (ncnvrg) {
  724. ++(*info);
  725. }
  726. if (toofew) {
  727. *info += 2;
  728. }
  729. return 0;
  730. /* End of DLARRD */
  731. } /* _starpu_dlarrd_ */