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