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