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