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_n1 = -1;
00020
00021 int cheevx_(char *jobz, char *range, char *uplo, integer *n,
00022 complex *a, integer *lda, real *vl, real *vu, integer *il, integer *
00023 iu, real *abstol, integer *m, real *w, complex *z__, integer *ldz,
00024 complex *work, integer *lwork, real *rwork, integer *iwork, integer *
00025 ifail, integer *info)
00026 {
00027
00028 integer a_dim1, a_offset, z_dim1, z_offset, i__1, i__2;
00029 real r__1, r__2;
00030
00031
00032 double sqrt(doublereal);
00033
00034
00035 integer i__, j, nb, jj;
00036 real eps, vll, vuu, tmp1;
00037 integer indd, inde;
00038 real anrm;
00039 integer imax;
00040 real rmin, rmax;
00041 logical test;
00042 integer itmp1, indee;
00043 real sigma;
00044 extern logical lsame_(char *, char *);
00045 integer iinfo;
00046 extern int sscal_(integer *, real *, real *, integer *);
00047 char order[1];
00048 extern int cswap_(integer *, complex *, integer *,
00049 complex *, integer *);
00050 logical lower;
00051 extern int scopy_(integer *, real *, integer *, real *,
00052 integer *);
00053 logical wantz;
00054 extern doublereal clanhe_(char *, char *, integer *, complex *, integer *,
00055 real *);
00056 logical alleig, indeig;
00057 integer iscale, indibl;
00058 logical valeig;
00059 extern doublereal slamch_(char *);
00060 extern int chetrd_(char *, integer *, complex *, integer
00061 *, real *, real *, complex *, complex *, integer *, integer *), csscal_(integer *, real *, complex *, integer *),
00062 clacpy_(char *, integer *, integer *, complex *, integer *,
00063 complex *, integer *);
00064 real safmin;
00065 extern integer ilaenv_(integer *, char *, char *, integer *, integer *,
00066 integer *, integer *);
00067 extern int xerbla_(char *, integer *);
00068 real abstll, bignum;
00069 integer indiwk, indisp, indtau;
00070 extern int cstein_(integer *, real *, real *, integer *,
00071 real *, integer *, integer *, complex *, integer *, real *,
00072 integer *, integer *, integer *);
00073 integer indrwk, indwrk, lwkmin;
00074 extern int csteqr_(char *, integer *, real *, real *,
00075 complex *, integer *, real *, integer *), cungtr_(char *,
00076 integer *, complex *, integer *, complex *, complex *, integer *,
00077 integer *), ssterf_(integer *, real *, real *, integer *),
00078 cunmtr_(char *, char *, char *, integer *, integer *, complex *,
00079 integer *, complex *, complex *, integer *, complex *, integer *,
00080 integer *);
00081 integer nsplit, llwork;
00082 real smlnum;
00083 extern int sstebz_(char *, char *, integer *, real *,
00084 real *, integer *, integer *, real *, real *, real *, integer *,
00085 integer *, real *, integer *, integer *, real *, integer *,
00086 integer *);
00087 integer lwkopt;
00088 logical lquery;
00089
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 a_dim1 = *lda;
00251 a_offset = 1 + a_dim1;
00252 a -= a_offset;
00253 --w;
00254 z_dim1 = *ldz;
00255 z_offset = 1 + z_dim1;
00256 z__ -= z_offset;
00257 --work;
00258 --rwork;
00259 --iwork;
00260 --ifail;
00261
00262
00263 lower = lsame_(uplo, "L");
00264 wantz = lsame_(jobz, "V");
00265 alleig = lsame_(range, "A");
00266 valeig = lsame_(range, "V");
00267 indeig = lsame_(range, "I");
00268 lquery = *lwork == -1;
00269
00270 *info = 0;
00271 if (! (wantz || lsame_(jobz, "N"))) {
00272 *info = -1;
00273 } else if (! (alleig || valeig || indeig)) {
00274 *info = -2;
00275 } else if (! (lower || lsame_(uplo, "U"))) {
00276 *info = -3;
00277 } else if (*n < 0) {
00278 *info = -4;
00279 } else if (*lda < max(1,*n)) {
00280 *info = -6;
00281 } else {
00282 if (valeig) {
00283 if (*n > 0 && *vu <= *vl) {
00284 *info = -8;
00285 }
00286 } else if (indeig) {
00287 if (*il < 1 || *il > max(1,*n)) {
00288 *info = -9;
00289 } else if (*iu < min(*n,*il) || *iu > *n) {
00290 *info = -10;
00291 }
00292 }
00293 }
00294 if (*info == 0) {
00295 if (*ldz < 1 || wantz && *ldz < *n) {
00296 *info = -15;
00297 }
00298 }
00299
00300 if (*info == 0) {
00301 if (*n <= 1) {
00302 lwkmin = 1;
00303 work[1].r = (real) lwkmin, work[1].i = 0.f;
00304 } else {
00305 lwkmin = *n << 1;
00306 nb = ilaenv_(&c__1, "CHETRD", uplo, n, &c_n1, &c_n1, &c_n1);
00307
00308 i__1 = nb, i__2 = ilaenv_(&c__1, "CUNMTR", uplo, n, &c_n1, &c_n1,
00309 &c_n1);
00310 nb = max(i__1,i__2);
00311
00312 i__1 = 1, i__2 = (nb + 1) * *n;
00313 lwkopt = max(i__1,i__2);
00314 work[1].r = (real) lwkopt, work[1].i = 0.f;
00315 }
00316
00317 if (*lwork < lwkmin && ! lquery) {
00318 *info = -17;
00319 }
00320 }
00321
00322 if (*info != 0) {
00323 i__1 = -(*info);
00324 xerbla_("CHEEVX", &i__1);
00325 return 0;
00326 } else if (lquery) {
00327 return 0;
00328 }
00329
00330
00331
00332 *m = 0;
00333 if (*n == 0) {
00334 return 0;
00335 }
00336
00337 if (*n == 1) {
00338 if (alleig || indeig) {
00339 *m = 1;
00340 i__1 = a_dim1 + 1;
00341 w[1] = a[i__1].r;
00342 } else if (valeig) {
00343 i__1 = a_dim1 + 1;
00344 i__2 = a_dim1 + 1;
00345 if (*vl < a[i__1].r && *vu >= a[i__2].r) {
00346 *m = 1;
00347 i__1 = a_dim1 + 1;
00348 w[1] = a[i__1].r;
00349 }
00350 }
00351 if (wantz) {
00352 i__1 = z_dim1 + 1;
00353 z__[i__1].r = 1.f, z__[i__1].i = 0.f;
00354 }
00355 return 0;
00356 }
00357
00358
00359
00360 safmin = slamch_("Safe minimum");
00361 eps = slamch_("Precision");
00362 smlnum = safmin / eps;
00363 bignum = 1.f / smlnum;
00364 rmin = sqrt(smlnum);
00365
00366 r__1 = sqrt(bignum), r__2 = 1.f / sqrt(sqrt(safmin));
00367 rmax = dmin(r__1,r__2);
00368
00369
00370
00371 iscale = 0;
00372 abstll = *abstol;
00373 if (valeig) {
00374 vll = *vl;
00375 vuu = *vu;
00376 }
00377 anrm = clanhe_("M", uplo, n, &a[a_offset], lda, &rwork[1]);
00378 if (anrm > 0.f && anrm < rmin) {
00379 iscale = 1;
00380 sigma = rmin / anrm;
00381 } else if (anrm > rmax) {
00382 iscale = 1;
00383 sigma = rmax / anrm;
00384 }
00385 if (iscale == 1) {
00386 if (lower) {
00387 i__1 = *n;
00388 for (j = 1; j <= i__1; ++j) {
00389 i__2 = *n - j + 1;
00390 csscal_(&i__2, &sigma, &a[j + j * a_dim1], &c__1);
00391
00392 }
00393 } else {
00394 i__1 = *n;
00395 for (j = 1; j <= i__1; ++j) {
00396 csscal_(&j, &sigma, &a[j * a_dim1 + 1], &c__1);
00397
00398 }
00399 }
00400 if (*abstol > 0.f) {
00401 abstll = *abstol * sigma;
00402 }
00403 if (valeig) {
00404 vll = *vl * sigma;
00405 vuu = *vu * sigma;
00406 }
00407 }
00408
00409
00410
00411 indd = 1;
00412 inde = indd + *n;
00413 indrwk = inde + *n;
00414 indtau = 1;
00415 indwrk = indtau + *n;
00416 llwork = *lwork - indwrk + 1;
00417 chetrd_(uplo, n, &a[a_offset], lda, &rwork[indd], &rwork[inde], &work[
00418 indtau], &work[indwrk], &llwork, &iinfo);
00419
00420
00421
00422
00423
00424 test = FALSE_;
00425 if (indeig) {
00426 if (*il == 1 && *iu == *n) {
00427 test = TRUE_;
00428 }
00429 }
00430 if ((alleig || test) && *abstol <= 0.f) {
00431 scopy_(n, &rwork[indd], &c__1, &w[1], &c__1);
00432 indee = indrwk + (*n << 1);
00433 if (! wantz) {
00434 i__1 = *n - 1;
00435 scopy_(&i__1, &rwork[inde], &c__1, &rwork[indee], &c__1);
00436 ssterf_(n, &w[1], &rwork[indee], info);
00437 } else {
00438 clacpy_("A", n, n, &a[a_offset], lda, &z__[z_offset], ldz);
00439 cungtr_(uplo, n, &z__[z_offset], ldz, &work[indtau], &work[indwrk]
00440 , &llwork, &iinfo);
00441 i__1 = *n - 1;
00442 scopy_(&i__1, &rwork[inde], &c__1, &rwork[indee], &c__1);
00443 csteqr_(jobz, n, &w[1], &rwork[indee], &z__[z_offset], ldz, &
00444 rwork[indrwk], info);
00445 if (*info == 0) {
00446 i__1 = *n;
00447 for (i__ = 1; i__ <= i__1; ++i__) {
00448 ifail[i__] = 0;
00449
00450 }
00451 }
00452 }
00453 if (*info == 0) {
00454 *m = *n;
00455 goto L40;
00456 }
00457 *info = 0;
00458 }
00459
00460
00461
00462 if (wantz) {
00463 *(unsigned char *)order = 'B';
00464 } else {
00465 *(unsigned char *)order = 'E';
00466 }
00467 indibl = 1;
00468 indisp = indibl + *n;
00469 indiwk = indisp + *n;
00470 sstebz_(range, order, n, &vll, &vuu, il, iu, &abstll, &rwork[indd], &
00471 rwork[inde], m, &nsplit, &w[1], &iwork[indibl], &iwork[indisp], &
00472 rwork[indrwk], &iwork[indiwk], info);
00473
00474 if (wantz) {
00475 cstein_(n, &rwork[indd], &rwork[inde], m, &w[1], &iwork[indibl], &
00476 iwork[indisp], &z__[z_offset], ldz, &rwork[indrwk], &iwork[
00477 indiwk], &ifail[1], info);
00478
00479
00480
00481
00482 cunmtr_("L", uplo, "N", n, m, &a[a_offset], lda, &work[indtau], &z__[
00483 z_offset], ldz, &work[indwrk], &llwork, &iinfo);
00484 }
00485
00486
00487
00488 L40:
00489 if (iscale == 1) {
00490 if (*info == 0) {
00491 imax = *m;
00492 } else {
00493 imax = *info - 1;
00494 }
00495 r__1 = 1.f / sigma;
00496 sscal_(&imax, &r__1, &w[1], &c__1);
00497 }
00498
00499
00500
00501
00502 if (wantz) {
00503 i__1 = *m - 1;
00504 for (j = 1; j <= i__1; ++j) {
00505 i__ = 0;
00506 tmp1 = w[j];
00507 i__2 = *m;
00508 for (jj = j + 1; jj <= i__2; ++jj) {
00509 if (w[jj] < tmp1) {
00510 i__ = jj;
00511 tmp1 = w[jj];
00512 }
00513
00514 }
00515
00516 if (i__ != 0) {
00517 itmp1 = iwork[indibl + i__ - 1];
00518 w[i__] = w[j];
00519 iwork[indibl + i__ - 1] = iwork[indibl + j - 1];
00520 w[j] = tmp1;
00521 iwork[indibl + j - 1] = itmp1;
00522 cswap_(n, &z__[i__ * z_dim1 + 1], &c__1, &z__[j * z_dim1 + 1],
00523 &c__1);
00524 if (*info != 0) {
00525 itmp1 = ifail[i__];
00526 ifail[i__] = ifail[j];
00527 ifail[j] = itmp1;
00528 }
00529 }
00530
00531 }
00532 }
00533
00534
00535
00536 work[1].r = (real) lwkopt, work[1].i = 0.f;
00537
00538 return 0;
00539
00540
00541
00542 }