00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013 #include "f2c.h"
00014 #include "blaswrap.h"
00015
00016
00017
00018 static integer c__1 = 1;
00019 static integer c__2 = 2;
00020
00021 int dlarre_(char *range, integer *n, doublereal *vl,
00022 doublereal *vu, integer *il, integer *iu, doublereal *d__, doublereal
00023 *e, doublereal *e2, doublereal *rtol1, doublereal *rtol2, doublereal *
00024 spltol, integer *nsplit, integer *isplit, integer *m, doublereal *w,
00025 doublereal *werr, doublereal *wgap, integer *iblock, integer *indexw,
00026 doublereal *gers, doublereal *pivmin, doublereal *work, integer *
00027 iwork, integer *info)
00028 {
00029
00030 integer i__1, i__2;
00031 doublereal d__1, d__2, d__3;
00032
00033
00034 double sqrt(doublereal), log(doublereal);
00035
00036
00037 integer i__, j;
00038 doublereal s1, s2;
00039 integer mb;
00040 doublereal gl;
00041 integer in, mm;
00042 doublereal gu;
00043 integer cnt;
00044 doublereal eps, tau, tmp, rtl;
00045 integer cnt1, cnt2;
00046 doublereal tmp1, eabs;
00047 integer iend, jblk;
00048 doublereal eold;
00049 integer indl;
00050 doublereal dmax__, emax;
00051 integer wend, idum, indu;
00052 doublereal rtol;
00053 integer iseed[4];
00054 doublereal avgap, sigma;
00055 extern logical lsame_(char *, char *);
00056 integer iinfo;
00057 extern int dcopy_(integer *, doublereal *, integer *,
00058 doublereal *, integer *);
00059 logical norep;
00060 extern int dlasq2_(integer *, doublereal *, integer *);
00061 extern doublereal dlamch_(char *);
00062 integer ibegin;
00063 logical forceb;
00064 integer irange;
00065 doublereal sgndef;
00066 extern int dlarra_(integer *, doublereal *, doublereal *,
00067 doublereal *, doublereal *, doublereal *, integer *, integer *,
00068 integer *), dlarrb_(integer *, doublereal *, doublereal *,
00069 integer *, integer *, doublereal *, doublereal *, integer *,
00070 doublereal *, doublereal *, doublereal *, doublereal *, integer *,
00071 doublereal *, doublereal *, integer *, integer *), dlarrc_(char *
00072 , integer *, doublereal *, doublereal *, doublereal *, doublereal
00073 *, doublereal *, integer *, integer *, integer *, integer *);
00074 integer wbegin;
00075 extern int dlarrd_(char *, char *, integer *, doublereal
00076 *, doublereal *, integer *, integer *, doublereal *, doublereal *,
00077 doublereal *, doublereal *, doublereal *, doublereal *, integer *
00078 , integer *, integer *, doublereal *, doublereal *, doublereal *,
00079 doublereal *, integer *, integer *, doublereal *, integer *,
00080 integer *);
00081 doublereal safmin, spdiam;
00082 extern int dlarrk_(integer *, integer *, doublereal *,
00083 doublereal *, doublereal *, doublereal *, doublereal *,
00084 doublereal *, doublereal *, doublereal *, integer *);
00085 logical usedqd;
00086 doublereal clwdth, isleft;
00087 extern int dlarnv_(integer *, integer *, integer *,
00088 doublereal *);
00089 doublereal isrght, bsrtol, dpivot;
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103
00104
00105
00106
00107
00108
00109
00110
00111
00112
00113
00114
00115
00116
00117
00118
00119
00120
00121
00122
00123
00124
00125
00126
00127
00128
00129
00130
00131
00132
00133
00134
00135
00136
00137
00138
00139
00140
00141
00142
00143
00144
00145
00146
00147
00148
00149
00150
00151
00152
00153
00154
00155
00156
00157
00158
00159
00160
00161
00162
00163
00164
00165
00166
00167
00168
00169
00170
00171
00172
00173
00174
00175
00176
00177
00178
00179
00180
00181
00182
00183
00184
00185
00186
00187
00188
00189
00190
00191
00192
00193
00194
00195
00196
00197
00198
00199
00200
00201
00202
00203
00204
00205
00206
00207
00208
00209
00210
00211
00212
00213
00214
00215
00216
00217
00218
00219
00220
00221
00222
00223
00224
00225
00226
00227
00228
00229
00230
00231
00232
00233
00234
00235
00236
00237
00238
00239
00240
00241
00242
00243
00244
00245
00246
00247
00248
00249
00250
00251
00252
00253
00254
00255
00256
00257
00258
00259
00260
00261
00262
00263
00264
00265
00266
00267
00268
00269
00270
00271
00272
00273
00274 --iwork;
00275 --work;
00276 --gers;
00277 --indexw;
00278 --iblock;
00279 --wgap;
00280 --werr;
00281 --w;
00282 --isplit;
00283 --e2;
00284 --e;
00285 --d__;
00286
00287
00288 *info = 0;
00289
00290
00291
00292 if (lsame_(range, "A")) {
00293 irange = 1;
00294 } else if (lsame_(range, "V")) {
00295 irange = 3;
00296 } else if (lsame_(range, "I")) {
00297 irange = 2;
00298 }
00299 *m = 0;
00300
00301 safmin = dlamch_("S");
00302 eps = dlamch_("P");
00303
00304 rtl = sqrt(eps);
00305 bsrtol = sqrt(eps);
00306
00307 if (*n == 1) {
00308 if (irange == 1 || irange == 3 && d__[1] > *vl && d__[1] <= *vu ||
00309 irange == 2 && *il == 1 && *iu == 1) {
00310 *m = 1;
00311 w[1] = d__[1];
00312
00313 werr[1] = 0.;
00314 wgap[1] = 0.;
00315 iblock[1] = 1;
00316 indexw[1] = 1;
00317 gers[1] = d__[1];
00318 gers[2] = d__[1];
00319 }
00320
00321 e[1] = 0.;
00322 return 0;
00323 }
00324
00325
00326
00327
00328 gl = d__[1];
00329 gu = d__[1];
00330 eold = 0.;
00331 emax = 0.;
00332 e[*n] = 0.;
00333 i__1 = *n;
00334 for (i__ = 1; i__ <= i__1; ++i__) {
00335 werr[i__] = 0.;
00336 wgap[i__] = 0.;
00337 eabs = (d__1 = e[i__], abs(d__1));
00338 if (eabs >= emax) {
00339 emax = eabs;
00340 }
00341 tmp1 = eabs + eold;
00342 gers[(i__ << 1) - 1] = d__[i__] - tmp1;
00343
00344 d__1 = gl, d__2 = gers[(i__ << 1) - 1];
00345 gl = min(d__1,d__2);
00346 gers[i__ * 2] = d__[i__] + tmp1;
00347
00348 d__1 = gu, d__2 = gers[i__ * 2];
00349 gu = max(d__1,d__2);
00350 eold = eabs;
00351
00352 }
00353
00354
00355
00356 d__3 = emax;
00357 d__1 = 1., d__2 = d__3 * d__3;
00358 *pivmin = safmin * max(d__1,d__2);
00359
00360
00361 spdiam = gu - gl;
00362
00363 dlarra_(n, &d__[1], &e[1], &e2[1], spltol, &spdiam, nsplit, &isplit[1], &
00364 iinfo);
00365
00366
00367 forceb = FALSE_;
00368
00369
00370 usedqd = irange == 1 && ! forceb;
00371 if (irange == 1 && ! forceb) {
00372
00373 *vl = gl;
00374 *vu = gu;
00375 } else {
00376
00377
00378
00379
00380
00381
00382 dlarrd_(range, "B", n, vl, vu, il, iu, &gers[1], &bsrtol, &d__[1], &e[
00383 1], &e2[1], pivmin, nsplit, &isplit[1], &mm, &w[1], &werr[1],
00384 vl, vu, &iblock[1], &indexw[1], &work[1], &iwork[1], &iinfo);
00385 if (iinfo != 0) {
00386 *info = -1;
00387 return 0;
00388 }
00389
00390 i__1 = *n;
00391 for (i__ = mm + 1; i__ <= i__1; ++i__) {
00392 w[i__] = 0.;
00393 werr[i__] = 0.;
00394 iblock[i__] = 0;
00395 indexw[i__] = 0;
00396
00397 }
00398 }
00399
00400
00401 ibegin = 1;
00402 wbegin = 1;
00403 i__1 = *nsplit;
00404 for (jblk = 1; jblk <= i__1; ++jblk) {
00405 iend = isplit[jblk];
00406 in = iend - ibegin + 1;
00407
00408 if (in == 1) {
00409 if (irange == 1 || irange == 3 && d__[ibegin] > *vl && d__[ibegin]
00410 <= *vu || irange == 2 && iblock[wbegin] == jblk) {
00411 ++(*m);
00412 w[*m] = d__[ibegin];
00413 werr[*m] = 0.;
00414
00415
00416 wgap[*m] = 0.;
00417 iblock[*m] = jblk;
00418 indexw[*m] = 1;
00419 ++wbegin;
00420 }
00421
00422 e[iend] = 0.;
00423 ibegin = iend + 1;
00424 goto L170;
00425 }
00426
00427
00428
00429
00430 e[iend] = 0.;
00431
00432
00433 gl = d__[ibegin];
00434 gu = d__[ibegin];
00435 i__2 = iend;
00436 for (i__ = ibegin; i__ <= i__2; ++i__) {
00437
00438 d__1 = gers[(i__ << 1) - 1];
00439 gl = min(d__1,gl);
00440
00441 d__1 = gers[i__ * 2];
00442 gu = max(d__1,gu);
00443
00444 }
00445 spdiam = gu - gl;
00446 if (! (irange == 1 && ! forceb)) {
00447
00448 mb = 0;
00449 i__2 = mm;
00450 for (i__ = wbegin; i__ <= i__2; ++i__) {
00451 if (iblock[i__] == jblk) {
00452 ++mb;
00453 } else {
00454 goto L21;
00455 }
00456
00457 }
00458 L21:
00459 if (mb == 0) {
00460
00461
00462 e[iend] = 0.;
00463 ibegin = iend + 1;
00464 goto L170;
00465 } else {
00466
00467 usedqd = (doublereal) mb > in * .5 && ! forceb;
00468 wend = wbegin + mb - 1;
00469
00470
00471
00472 sigma = 0.;
00473 i__2 = wend - 1;
00474 for (i__ = wbegin; i__ <= i__2; ++i__) {
00475
00476 d__1 = 0., d__2 = w[i__ + 1] - werr[i__ + 1] - (w[i__] +
00477 werr[i__]);
00478 wgap[i__] = max(d__1,d__2);
00479
00480 }
00481
00482 d__1 = 0., d__2 = *vu - sigma - (w[wend] + werr[wend]);
00483 wgap[wend] = max(d__1,d__2);
00484
00485 indl = indexw[wbegin];
00486 indu = indexw[wend];
00487 }
00488 }
00489 if (irange == 1 && ! forceb || usedqd) {
00490
00491
00492 dlarrk_(&in, &c__1, &gl, &gu, &d__[ibegin], &e2[ibegin], pivmin, &
00493 rtl, &tmp, &tmp1, &iinfo);
00494 if (iinfo != 0) {
00495 *info = -1;
00496 return 0;
00497 }
00498
00499 d__2 = gl, d__3 = tmp - tmp1 - eps * 100. * (d__1 = tmp - tmp1,
00500 abs(d__1));
00501 isleft = max(d__2,d__3);
00502 dlarrk_(&in, &in, &gl, &gu, &d__[ibegin], &e2[ibegin], pivmin, &
00503 rtl, &tmp, &tmp1, &iinfo);
00504 if (iinfo != 0) {
00505 *info = -1;
00506 return 0;
00507 }
00508
00509 d__2 = gu, d__3 = tmp + tmp1 + eps * 100. * (d__1 = tmp + tmp1,
00510 abs(d__1));
00511 isrght = min(d__2,d__3);
00512
00513 spdiam = isrght - isleft;
00514 } else {
00515
00516
00517
00518 d__2 = gl, d__3 = w[wbegin] - werr[wbegin] - eps * 100. * (d__1 =
00519 w[wbegin] - werr[wbegin], abs(d__1));
00520 isleft = max(d__2,d__3);
00521
00522 d__2 = gu, d__3 = w[wend] + werr[wend] + eps * 100. * (d__1 = w[
00523 wend] + werr[wend], abs(d__1));
00524 isrght = min(d__2,d__3);
00525 }
00526
00527
00528
00529
00530
00531
00532
00533
00534 if (irange == 1 && ! forceb) {
00535
00536 usedqd = TRUE_;
00537
00538 indl = 1;
00539 indu = in;
00540
00541 mb = in;
00542 wend = wbegin + mb - 1;
00543
00544 s1 = isleft + spdiam * .25;
00545 s2 = isrght - spdiam * .25;
00546 } else {
00547
00548
00549
00550 if (usedqd) {
00551 s1 = isleft + spdiam * .25;
00552 s2 = isrght - spdiam * .25;
00553 } else {
00554 tmp = min(isrght,*vu) - max(isleft,*vl);
00555 s1 = max(isleft,*vl) + tmp * .25;
00556 s2 = min(isrght,*vu) - tmp * .25;
00557 }
00558 }
00559
00560 if (mb > 1) {
00561 dlarrc_("T", &in, &s1, &s2, &d__[ibegin], &e[ibegin], pivmin, &
00562 cnt, &cnt1, &cnt2, &iinfo);
00563 }
00564 if (mb == 1) {
00565 sigma = gl;
00566 sgndef = 1.;
00567 } else if (cnt1 - indl >= indu - cnt2) {
00568 if (irange == 1 && ! forceb) {
00569 sigma = max(isleft,gl);
00570 } else if (usedqd) {
00571
00572
00573 sigma = isleft;
00574 } else {
00575
00576
00577 sigma = max(isleft,*vl);
00578 }
00579 sgndef = 1.;
00580 } else {
00581 if (irange == 1 && ! forceb) {
00582 sigma = min(isrght,gu);
00583 } else if (usedqd) {
00584
00585
00586 sigma = isrght;
00587 } else {
00588
00589
00590 sigma = min(isrght,*vu);
00591 }
00592 sgndef = -1.;
00593 }
00594
00595
00596
00597
00598
00599 if (usedqd) {
00600
00601
00602 tau = spdiam * eps * *n + *pivmin * 2.;
00603 } else {
00604 if (mb > 1) {
00605 clwdth = w[wend] + werr[wend] - w[wbegin] - werr[wbegin];
00606 avgap = (d__1 = clwdth / (doublereal) (wend - wbegin), abs(
00607 d__1));
00608 if (sgndef == 1.) {
00609
00610 d__1 = wgap[wbegin];
00611 tau = max(d__1,avgap) * .5;
00612
00613 d__1 = tau, d__2 = werr[wbegin];
00614 tau = max(d__1,d__2);
00615 } else {
00616
00617 d__1 = wgap[wend - 1];
00618 tau = max(d__1,avgap) * .5;
00619
00620 d__1 = tau, d__2 = werr[wend];
00621 tau = max(d__1,d__2);
00622 }
00623 } else {
00624 tau = werr[wbegin];
00625 }
00626 }
00627
00628 for (idum = 1; idum <= 6; ++idum) {
00629
00630
00631
00632 dpivot = d__[ibegin] - sigma;
00633 work[1] = dpivot;
00634 dmax__ = abs(work[1]);
00635 j = ibegin;
00636 i__2 = in - 1;
00637 for (i__ = 1; i__ <= i__2; ++i__) {
00638 work[(in << 1) + i__] = 1. / work[i__];
00639 tmp = e[j] * work[(in << 1) + i__];
00640 work[in + i__] = tmp;
00641 dpivot = d__[j + 1] - sigma - tmp * e[j];
00642 work[i__ + 1] = dpivot;
00643
00644 d__1 = dmax__, d__2 = abs(dpivot);
00645 dmax__ = max(d__1,d__2);
00646 ++j;
00647
00648 }
00649
00650 if (dmax__ > spdiam * 64.) {
00651 norep = TRUE_;
00652 } else {
00653 norep = FALSE_;
00654 }
00655 if (usedqd && ! norep) {
00656
00657
00658 i__2 = in;
00659 for (i__ = 1; i__ <= i__2; ++i__) {
00660 tmp = sgndef * work[i__];
00661 if (tmp < 0.) {
00662 norep = TRUE_;
00663 }
00664
00665 }
00666 }
00667 if (norep) {
00668
00669
00670
00671 if (idum == 5) {
00672 if (sgndef == 1.) {
00673
00674 sigma = gl - spdiam * 2. * eps * *n - *pivmin * 4.;
00675 } else {
00676 sigma = gu + spdiam * 2. * eps * *n + *pivmin * 4.;
00677 }
00678 } else {
00679 sigma -= sgndef * tau;
00680 tau *= 2.;
00681 }
00682 } else {
00683
00684 goto L83;
00685 }
00686
00687 }
00688
00689
00690 *info = 2;
00691 return 0;
00692 L83:
00693
00694
00695
00696 e[iend] = sigma;
00697
00698 dcopy_(&in, &work[1], &c__1, &d__[ibegin], &c__1);
00699 i__2 = in - 1;
00700 dcopy_(&i__2, &work[in + 1], &c__1, &e[ibegin], &c__1);
00701 if (mb > 1) {
00702
00703
00704
00705
00706
00707 for (i__ = 1; i__ <= 4; ++i__) {
00708 iseed[i__ - 1] = 1;
00709
00710 }
00711 i__2 = (in << 1) - 1;
00712 dlarnv_(&c__2, iseed, &i__2, &work[1]);
00713 i__2 = in - 1;
00714 for (i__ = 1; i__ <= i__2; ++i__) {
00715 d__[ibegin + i__ - 1] *= eps * 8. * work[i__] + 1.;
00716 e[ibegin + i__ - 1] *= eps * 8. * work[in + i__] + 1.;
00717
00718 }
00719 d__[iend] *= eps * 4. * work[in] + 1.;
00720
00721 }
00722
00723
00724
00725
00726
00727
00728 if (! usedqd) {
00729
00730
00731
00732
00733
00734 i__2 = wend;
00735 for (j = wbegin; j <= i__2; ++j) {
00736 w[j] -= sigma;
00737 werr[j] += (d__1 = w[j], abs(d__1)) * eps;
00738
00739 }
00740
00741
00742 i__2 = iend - 1;
00743 for (i__ = ibegin; i__ <= i__2; ++i__) {
00744
00745 d__1 = e[i__];
00746 work[i__] = d__[i__] * (d__1 * d__1);
00747
00748 }
00749
00750 i__2 = indl - 1;
00751 dlarrb_(&in, &d__[ibegin], &work[ibegin], &indl, &indu, rtol1,
00752 rtol2, &i__2, &w[wbegin], &wgap[wbegin], &werr[wbegin], &
00753 work[(*n << 1) + 1], &iwork[1], pivmin, &spdiam, &in, &
00754 iinfo);
00755 if (iinfo != 0) {
00756 *info = -4;
00757 return 0;
00758 }
00759
00760
00761
00762 d__1 = 0., d__2 = *vu - sigma - (w[wend] + werr[wend]);
00763 wgap[wend] = max(d__1,d__2);
00764 i__2 = indu;
00765 for (i__ = indl; i__ <= i__2; ++i__) {
00766 ++(*m);
00767 iblock[*m] = jblk;
00768 indexw[*m] = i__;
00769
00770 }
00771 } else {
00772
00773
00774
00775
00776
00777
00778
00779
00780
00781
00782
00783 rtol = log((doublereal) in) * 4. * eps;
00784 j = ibegin;
00785 i__2 = in - 1;
00786 for (i__ = 1; i__ <= i__2; ++i__) {
00787 work[(i__ << 1) - 1] = (d__1 = d__[j], abs(d__1));
00788 work[i__ * 2] = e[j] * e[j] * work[(i__ << 1) - 1];
00789 ++j;
00790
00791 }
00792 work[(in << 1) - 1] = (d__1 = d__[iend], abs(d__1));
00793 work[in * 2] = 0.;
00794 dlasq2_(&in, &work[1], &iinfo);
00795 if (iinfo != 0) {
00796
00797
00798
00799 *info = -5;
00800 return 0;
00801 } else {
00802
00803 i__2 = in;
00804 for (i__ = 1; i__ <= i__2; ++i__) {
00805 if (work[i__] < 0.) {
00806 *info = -6;
00807 return 0;
00808 }
00809
00810 }
00811 }
00812 if (sgndef > 0.) {
00813 i__2 = indu;
00814 for (i__ = indl; i__ <= i__2; ++i__) {
00815 ++(*m);
00816 w[*m] = work[in - i__ + 1];
00817 iblock[*m] = jblk;
00818 indexw[*m] = i__;
00819
00820 }
00821 } else {
00822 i__2 = indu;
00823 for (i__ = indl; i__ <= i__2; ++i__) {
00824 ++(*m);
00825 w[*m] = -work[i__];
00826 iblock[*m] = jblk;
00827 indexw[*m] = i__;
00828
00829 }
00830 }
00831 i__2 = *m;
00832 for (i__ = *m - mb + 1; i__ <= i__2; ++i__) {
00833
00834 werr[i__] = rtol * (d__1 = w[i__], abs(d__1));
00835
00836 }
00837 i__2 = *m - 1;
00838 for (i__ = *m - mb + 1; i__ <= i__2; ++i__) {
00839
00840
00841 d__1 = 0., d__2 = w[i__ + 1] - werr[i__ + 1] - (w[i__] + werr[
00842 i__]);
00843 wgap[i__] = max(d__1,d__2);
00844
00845 }
00846
00847 d__1 = 0., d__2 = *vu - sigma - (w[*m] + werr[*m]);
00848 wgap[*m] = max(d__1,d__2);
00849 }
00850
00851 ibegin = iend + 1;
00852 wbegin = wend + 1;
00853 L170:
00854 ;
00855 }
00856
00857 return 0;
00858
00859
00860
00861 }