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