sstemr.c
Go to the documentation of this file.
00001 /* sstemr.f -- translated by f2c (version 20061008).
00002    You must link the resulting object file with libf2c:
00003         on Microsoft Windows system, link with libf2c.lib;
00004         on Linux or Unix systems, link with .../path/to/libf2c.a -lm
00005         or, if you install libf2c.a in a standard place, with -lf2c -lm
00006         -- in that order, at the end of the command line, as in
00007                 cc *.o -lf2c -lm
00008         Source for libf2c is in /netlib/f2c/libf2c.zip, e.g.,
00009 
00010                 http://www.netlib.org/f2c/libf2c.zip
00011 */
00012 
00013 #include "f2c.h"
00014 #include "blaswrap.h"
00015 
00016 /* Table of constant values */
00017 
00018 static integer c__1 = 1;
00019 static real c_b18 = .003f;
00020 
00021 /* Subroutine */ int sstemr_(char *jobz, char *range, integer *n, real *d__, 
00022         real *e, real *vl, real *vu, integer *il, integer *iu, integer *m, 
00023         real *w, real *z__, integer *ldz, integer *nzc, integer *isuppz, 
00024         logical *tryrac, real *work, integer *lwork, integer *iwork, integer *
00025         liwork, integer *info)
00026 {
00027     /* System generated locals */
00028     integer z_dim1, z_offset, i__1, i__2;
00029     real r__1, r__2;
00030 
00031     /* Builtin functions */
00032     double sqrt(doublereal);
00033 
00034     /* Local variables */
00035     integer i__, j;
00036     real r1, r2;
00037     integer jj;
00038     real cs;
00039     integer in;
00040     real sn, wl, wu;
00041     integer iil, iiu;
00042     real eps, tmp;
00043     integer indd, iend, jblk, wend;
00044     real rmin, rmax;
00045     integer itmp;
00046     real tnrm;
00047     integer inde2;
00048     extern /* Subroutine */ int slae2_(real *, real *, real *, real *, real *)
00049             ;
00050     integer itmp2;
00051     real rtol1, rtol2, scale;
00052     integer indgp;
00053     extern logical lsame_(char *, char *);
00054     integer iinfo;
00055     extern /* Subroutine */ int sscal_(integer *, real *, real *, integer *);
00056     integer iindw, ilast, lwmin;
00057     extern /* Subroutine */ int scopy_(integer *, real *, integer *, real *, 
00058             integer *), sswap_(integer *, real *, integer *, real *, integer *
00059 );
00060     logical wantz;
00061     extern /* Subroutine */ int slaev2_(real *, real *, real *, real *, real *
00062 , real *, real *);
00063     logical alleig;
00064     integer ibegin;
00065     logical indeig;
00066     integer iindbl;
00067     logical valeig;
00068     extern doublereal slamch_(char *);
00069     integer wbegin;
00070     real safmin;
00071     extern /* Subroutine */ int xerbla_(char *, integer *);
00072     real bignum;
00073     integer inderr, iindwk, indgrs, offset;
00074     extern /* Subroutine */ int slarrc_(char *, integer *, real *, real *, 
00075             real *, real *, real *, integer *, integer *, integer *, integer *
00076 ), slarre_(char *, integer *, real *, real *, integer *, 
00077             integer *, real *, real *, real *, real *, real *, real *, 
00078             integer *, integer *, integer *, real *, real *, real *, integer *
00079 , integer *, real *, real *, real *, integer *, integer *)
00080             ;
00081     real thresh;
00082     integer iinspl, indwrk, ifirst, liwmin, nzcmin;
00083     real pivmin;
00084     extern doublereal slanst_(char *, integer *, real *, real *);
00085     extern /* Subroutine */ int slarrj_(integer *, real *, real *, integer *, 
00086             integer *, real *, integer *, real *, real *, real *, integer *, 
00087             real *, real *, integer *), slarrr_(integer *, real *, real *, 
00088             integer *);
00089     integer nsplit;
00090     extern /* Subroutine */ int slarrv_(integer *, real *, real *, real *, 
00091             real *, real *, integer *, integer *, integer *, integer *, real *
00092 , real *, real *, real *, real *, real *, integer *, integer *, 
00093             real *, real *, integer *, integer *, real *, integer *, integer *
00094 );
00095     real smlnum;
00096     extern /* Subroutine */ int slasrt_(char *, integer *, real *, integer *);
00097     logical lquery, zquery;
00098 
00099 
00100 /*  -- LAPACK computational routine (version 3.2) -- */
00101 /*     Univ. of Tennessee, Univ. of California Berkeley and NAG Ltd.. */
00102 /*     November 2006 */
00103 
00104 /*     .. Scalar Arguments .. */
00105 /*     .. */
00106 /*     .. Array Arguments .. */
00107 /*     .. */
00108 
00109 /*  Purpose */
00110 /*  ======= */
00111 
00112 /*  SSTEMR computes selected eigenvalues and, optionally, eigenvectors */
00113 /*  of a real symmetric tridiagonal matrix T. Any such unreduced matrix has */
00114 /*  a well defined set of pairwise different real eigenvalues, the corresponding */
00115 /*  real eigenvectors are pairwise orthogonal. */
00116 
00117 /*  The spectrum may be computed either completely or partially by specifying */
00118 /*  either an interval (VL,VU] or a range of indices IL:IU for the desired */
00119 /*  eigenvalues. */
00120 
00121 /*  Depending on the number of desired eigenvalues, these are computed either */
00122 /*  by bisection or the dqds algorithm. Numerically orthogonal eigenvectors are */
00123 /*  computed by the use of various suitable L D L^T factorizations near clusters */
00124 /*  of close eigenvalues (referred to as RRRs, Relatively Robust */
00125 /*  Representations). An informal sketch of the algorithm follows. */
00126 
00127 /*  For each unreduced block (submatrix) of T, */
00128 /*     (a) Compute T - sigma I  = L D L^T, so that L and D */
00129 /*         define all the wanted eigenvalues to high relative accuracy. */
00130 /*         This means that small relative changes in the entries of D and L */
00131 /*         cause only small relative changes in the eigenvalues and */
00132 /*         eigenvectors. The standard (unfactored) representation of the */
00133 /*         tridiagonal matrix T does not have this property in general. */
00134 /*     (b) Compute the eigenvalues to suitable accuracy. */
00135 /*         If the eigenvectors are desired, the algorithm attains full */
00136 /*         accuracy of the computed eigenvalues only right before */
00137 /*         the corresponding vectors have to be computed, see steps c) and d). */
00138 /*     (c) For each cluster of close eigenvalues, select a new */
00139 /*         shift close to the cluster, find a new factorization, and refine */
00140 /*         the shifted eigenvalues to suitable accuracy. */
00141 /*     (d) For each eigenvalue with a large enough relative separation compute */
00142 /*         the corresponding eigenvector by forming a rank revealing twisted */
00143 /*         factorization. Go back to (c) for any clusters that remain. */
00144 
00145 /*  For more details, see: */
00146 /*  - Inderjit S. Dhillon and Beresford N. Parlett: "Multiple representations */
00147 /*    to compute orthogonal eigenvectors of symmetric tridiagonal matrices," */
00148 /*    Linear Algebra and its Applications, 387(1), pp. 1-28, August 2004. */
00149 /*  - Inderjit Dhillon and Beresford Parlett: "Orthogonal Eigenvectors and */
00150 /*    Relative Gaps," SIAM Journal on Matrix Analysis and Applications, Vol. 25, */
00151 /*    2004.  Also LAPACK Working Note 154. */
00152 /*  - Inderjit Dhillon: "A new O(n^2) algorithm for the symmetric */
00153 /*    tridiagonal eigenvalue/eigenvector problem", */
00154 /*    Computer Science Division Technical Report No. UCB/CSD-97-971, */
00155 /*    UC Berkeley, May 1997. */
00156 
00157 /*  Notes: */
00158 /*  1.SSTEMR works only on machines which follow IEEE-754 */
00159 /*  floating-point standard in their handling of infinities and NaNs. */
00160 /*  This permits the use of efficient inner loops avoiding a check for */
00161 /*  zero divisors. */
00162 
00163 /*  Arguments */
00164 /*  ========= */
00165 
00166 /*  JOBZ    (input) CHARACTER*1 */
00167 /*          = 'N':  Compute eigenvalues only; */
00168 /*          = 'V':  Compute eigenvalues and eigenvectors. */
00169 
00170 /*  RANGE   (input) CHARACTER*1 */
00171 /*          = 'A': all eigenvalues will be found. */
00172 /*          = 'V': all eigenvalues in the half-open interval (VL,VU] */
00173 /*                 will be found. */
00174 /*          = 'I': the IL-th through IU-th eigenvalues will be found. */
00175 
00176 /*  N       (input) INTEGER */
00177 /*          The order of the matrix.  N >= 0. */
00178 
00179 /*  D       (input/output) REAL array, dimension (N) */
00180 /*          On entry, the N diagonal elements of the tridiagonal matrix */
00181 /*          T. On exit, D is overwritten. */
00182 
00183 /*  E       (input/output) REAL array, dimension (N) */
00184 /*          On entry, the (N-1) subdiagonal elements of the tridiagonal */
00185 /*          matrix T in elements 1 to N-1 of E. E(N) need not be set on */
00186 /*          input, but is used internally as workspace. */
00187 /*          On exit, E is overwritten. */
00188 
00189 /*  VL      (input) REAL */
00190 /*  VU      (input) REAL */
00191 /*          If RANGE='V', the lower and upper bounds of the interval to */
00192 /*          be searched for eigenvalues. VL < VU. */
00193 /*          Not referenced if RANGE = 'A' or 'I'. */
00194 
00195 /*  IL      (input) INTEGER */
00196 /*  IU      (input) INTEGER */
00197 /*          If RANGE='I', the indices (in ascending order) of the */
00198 /*          smallest and largest eigenvalues to be returned. */
00199 /*          1 <= IL <= IU <= N, if N > 0. */
00200 /*          Not referenced if RANGE = 'A' or 'V'. */
00201 
00202 /*  M       (output) INTEGER */
00203 /*          The total number of eigenvalues found.  0 <= M <= N. */
00204 /*          If RANGE = 'A', M = N, and if RANGE = 'I', M = IU-IL+1. */
00205 
00206 /*  W       (output) REAL array, dimension (N) */
00207 /*          The first M elements contain the selected eigenvalues in */
00208 /*          ascending order. */
00209 
00210 /*  Z       (output) REAL array, dimension (LDZ, max(1,M) ) */
00211 /*          If JOBZ = 'V', and if INFO = 0, then the first M columns of Z */
00212 /*          contain the orthonormal eigenvectors of the matrix T */
00213 /*          corresponding to the selected eigenvalues, with the i-th */
00214 /*          column of Z holding the eigenvector associated with W(i). */
00215 /*          If JOBZ = 'N', then Z is not referenced. */
00216 /*          Note: the user must ensure that at least max(1,M) columns are */
00217 /*          supplied in the array Z; if RANGE = 'V', the exact value of M */
00218 /*          is not known in advance and can be computed with a workspace */
00219 /*          query by setting NZC = -1, see below. */
00220 
00221 /*  LDZ     (input) INTEGER */
00222 /*          The leading dimension of the array Z.  LDZ >= 1, and if */
00223 /*          JOBZ = 'V', then LDZ >= max(1,N). */
00224 
00225 /*  NZC     (input) INTEGER */
00226 /*          The number of eigenvectors to be held in the array Z. */
00227 /*          If RANGE = 'A', then NZC >= max(1,N). */
00228 /*          If RANGE = 'V', then NZC >= the number of eigenvalues in (VL,VU]. */
00229 /*          If RANGE = 'I', then NZC >= IU-IL+1. */
00230 /*          If NZC = -1, then a workspace query is assumed; the */
00231 /*          routine calculates the number of columns of the array Z that */
00232 /*          are needed to hold the eigenvectors. */
00233 /*          This value is returned as the first entry of the Z array, and */
00234 /*          no error message related to NZC is issued by XERBLA. */
00235 
00236 /*  ISUPPZ  (output) INTEGER ARRAY, dimension ( 2*max(1,M) ) */
00237 /*          The support of the eigenvectors in Z, i.e., the indices */
00238 /*          indicating the nonzero elements in Z. The i-th computed eigenvector */
00239 /*          is nonzero only in elements ISUPPZ( 2*i-1 ) through */
00240 /*          ISUPPZ( 2*i ). This is relevant in the case when the matrix */
00241 /*          is split. ISUPPZ is only accessed when JOBZ is 'V' and N > 0. */
00242 
00243 /*  TRYRAC  (input/output) LOGICAL */
00244 /*          If TRYRAC.EQ..TRUE., indicates that the code should check whether */
00245 /*          the tridiagonal matrix defines its eigenvalues to high relative */
00246 /*          accuracy.  If so, the code uses relative-accuracy preserving */
00247 /*          algorithms that might be (a bit) slower depending on the matrix. */
00248 /*          If the matrix does not define its eigenvalues to high relative */
00249 /*          accuracy, the code can uses possibly faster algorithms. */
00250 /*          If TRYRAC.EQ..FALSE., the code is not required to guarantee */
00251 /*          relatively accurate eigenvalues and can use the fastest possible */
00252 /*          techniques. */
00253 /*          On exit, a .TRUE. TRYRAC will be set to .FALSE. if the matrix */
00254 /*          does not define its eigenvalues to high relative accuracy. */
00255 
00256 /*  WORK    (workspace/output) REAL array, dimension (LWORK) */
00257 /*          On exit, if INFO = 0, WORK(1) returns the optimal */
00258 /*          (and minimal) LWORK. */
00259 
00260 /*  LWORK   (input) INTEGER */
00261 /*          The dimension of the array WORK. LWORK >= max(1,18*N) */
00262 /*          if JOBZ = 'V', and LWORK >= max(1,12*N) if JOBZ = 'N'. */
00263 /*          If LWORK = -1, then a workspace query is assumed; the routine */
00264 /*          only calculates the optimal size of the WORK array, returns */
00265 /*          this value as the first entry of the WORK array, and no error */
00266 /*          message related to LWORK is issued by XERBLA. */
00267 
00268 /*  IWORK   (workspace/output) INTEGER array, dimension (LIWORK) */
00269 /*          On exit, if INFO = 0, IWORK(1) returns the optimal LIWORK. */
00270 
00271 /*  LIWORK  (input) INTEGER */
00272 /*          The dimension of the array IWORK.  LIWORK >= max(1,10*N) */
00273 /*          if the eigenvectors are desired, and LIWORK >= max(1,8*N) */
00274 /*          if only the eigenvalues are to be computed. */
00275 /*          If LIWORK = -1, then a workspace query is assumed; the */
00276 /*          routine only calculates the optimal size of the IWORK array, */
00277 /*          returns this value as the first entry of the IWORK array, and */
00278 /*          no error message related to LIWORK is issued by XERBLA. */
00279 
00280 /*  INFO    (output) INTEGER */
00281 /*          On exit, INFO */
00282 /*          = 0:  successful exit */
00283 /*          < 0:  if INFO = -i, the i-th argument had an illegal value */
00284 /*          > 0:  if INFO = 1X, internal error in SLARRE, */
00285 /*                if INFO = 2X, internal error in SLARRV. */
00286 /*                Here, the digit X = ABS( IINFO ) < 10, where IINFO is */
00287 /*                the nonzero error code returned by SLARRE or */
00288 /*                SLARRV, respectively. */
00289 
00290 
00291 /*  Further Details */
00292 /*  =============== */
00293 
00294 /*  Based on contributions by */
00295 /*     Beresford Parlett, University of California, Berkeley, USA */
00296 /*     Jim Demmel, University of California, Berkeley, USA */
00297 /*     Inderjit Dhillon, University of Texas, Austin, USA */
00298 /*     Osni Marques, LBNL/NERSC, USA */
00299 /*     Christof Voemel, University of California, Berkeley, USA */
00300 
00301 /*  ===================================================================== */
00302 
00303 /*     .. Parameters .. */
00304 /*     .. */
00305 /*     .. Local Scalars .. */
00306 /*     .. */
00307 /*     .. */
00308 /*     .. External Functions .. */
00309 /*     .. */
00310 /*     .. External Subroutines .. */
00311 /*     .. */
00312 /*     .. Intrinsic Functions .. */
00313 /*     .. */
00314 /*     .. Executable Statements .. */
00315 
00316 /*     Test the input parameters. */
00317 
00318     /* Parameter adjustments */
00319     --d__;
00320     --e;
00321     --w;
00322     z_dim1 = *ldz;
00323     z_offset = 1 + z_dim1;
00324     z__ -= z_offset;
00325     --isuppz;
00326     --work;
00327     --iwork;
00328 
00329     /* Function Body */
00330     wantz = lsame_(jobz, "V");
00331     alleig = lsame_(range, "A");
00332     valeig = lsame_(range, "V");
00333     indeig = lsame_(range, "I");
00334 
00335     lquery = *lwork == -1 || *liwork == -1;
00336     zquery = *nzc == -1;
00337 /*     SSTEMR needs WORK of size 6*N, IWORK of size 3*N. */
00338 /*     In addition, SLARRE needs WORK of size 6*N, IWORK of size 5*N. */
00339 /*     Furthermore, SLARRV needs WORK of size 12*N, IWORK of size 7*N. */
00340     if (wantz) {
00341         lwmin = *n * 18;
00342         liwmin = *n * 10;
00343     } else {
00344 /*        need less workspace if only the eigenvalues are wanted */
00345         lwmin = *n * 12;
00346         liwmin = *n << 3;
00347     }
00348     wl = 0.f;
00349     wu = 0.f;
00350     iil = 0;
00351     iiu = 0;
00352     if (valeig) {
00353 /*        We do not reference VL, VU in the cases RANGE = 'I','A' */
00354 /*        The interval (WL, WU] contains all the wanted eigenvalues. */
00355 /*        It is either given by the user or computed in SLARRE. */
00356         wl = *vl;
00357         wu = *vu;
00358     } else if (indeig) {
00359 /*        We do not reference IL, IU in the cases RANGE = 'V','A' */
00360         iil = *il;
00361         iiu = *iu;
00362     }
00363 
00364     *info = 0;
00365     if (! (wantz || lsame_(jobz, "N"))) {
00366         *info = -1;
00367     } else if (! (alleig || valeig || indeig)) {
00368         *info = -2;
00369     } else if (*n < 0) {
00370         *info = -3;
00371     } else if (valeig && *n > 0 && wu <= wl) {
00372         *info = -7;
00373     } else if (indeig && (iil < 1 || iil > *n)) {
00374         *info = -8;
00375     } else if (indeig && (iiu < iil || iiu > *n)) {
00376         *info = -9;
00377     } else if (*ldz < 1 || wantz && *ldz < *n) {
00378         *info = -13;
00379     } else if (*lwork < lwmin && ! lquery) {
00380         *info = -17;
00381     } else if (*liwork < liwmin && ! lquery) {
00382         *info = -19;
00383     }
00384 
00385 /*     Get machine constants. */
00386 
00387     safmin = slamch_("Safe minimum");
00388     eps = slamch_("Precision");
00389     smlnum = safmin / eps;
00390     bignum = 1.f / smlnum;
00391     rmin = sqrt(smlnum);
00392 /* Computing MIN */
00393     r__1 = sqrt(bignum), r__2 = 1.f / sqrt(sqrt(safmin));
00394     rmax = dmin(r__1,r__2);
00395 
00396     if (*info == 0) {
00397         work[1] = (real) lwmin;
00398         iwork[1] = liwmin;
00399 
00400         if (wantz && alleig) {
00401             nzcmin = *n;
00402         } else if (wantz && valeig) {
00403             slarrc_("T", n, vl, vu, &d__[1], &e[1], &safmin, &nzcmin, &itmp, &
00404                     itmp2, info);
00405         } else if (wantz && indeig) {
00406             nzcmin = iiu - iil + 1;
00407         } else {
00408 /*           WANTZ .EQ. FALSE. */
00409             nzcmin = 0;
00410         }
00411         if (zquery && *info == 0) {
00412             z__[z_dim1 + 1] = (real) nzcmin;
00413         } else if (*nzc < nzcmin && ! zquery) {
00414             *info = -14;
00415         }
00416     }
00417     if (*info != 0) {
00418 
00419         i__1 = -(*info);
00420         xerbla_("SSTEMR", &i__1);
00421 
00422         return 0;
00423     } else if (lquery || zquery) {
00424         return 0;
00425     }
00426 
00427 /*     Handle N = 0, 1, and 2 cases immediately */
00428 
00429     *m = 0;
00430     if (*n == 0) {
00431         return 0;
00432     }
00433 
00434     if (*n == 1) {
00435         if (alleig || indeig) {
00436             *m = 1;
00437             w[1] = d__[1];
00438         } else {
00439             if (wl < d__[1] && wu >= d__[1]) {
00440                 *m = 1;
00441                 w[1] = d__[1];
00442             }
00443         }
00444         if (wantz && ! zquery) {
00445             z__[z_dim1 + 1] = 1.f;
00446             isuppz[1] = 1;
00447             isuppz[2] = 1;
00448         }
00449         return 0;
00450     }
00451 
00452     if (*n == 2) {
00453         if (! wantz) {
00454             slae2_(&d__[1], &e[1], &d__[2], &r1, &r2);
00455         } else if (wantz && ! zquery) {
00456             slaev2_(&d__[1], &e[1], &d__[2], &r1, &r2, &cs, &sn);
00457         }
00458         if (alleig || valeig && r2 > wl && r2 <= wu || indeig && iil == 1) {
00459             ++(*m);
00460             w[*m] = r2;
00461             if (wantz && ! zquery) {
00462                 z__[*m * z_dim1 + 1] = -sn;
00463                 z__[*m * z_dim1 + 2] = cs;
00464 /*              Note: At most one of SN and CS can be zero. */
00465                 if (sn != 0.f) {
00466                     if (cs != 0.f) {
00467                         isuppz[(*m << 1) - 1] = 1;
00468                         isuppz[(*m << 1) - 1] = 2;
00469                     } else {
00470                         isuppz[(*m << 1) - 1] = 1;
00471                         isuppz[(*m << 1) - 1] = 1;
00472                     }
00473                 } else {
00474                     isuppz[(*m << 1) - 1] = 2;
00475                     isuppz[*m * 2] = 2;
00476                 }
00477             }
00478         }
00479         if (alleig || valeig && r1 > wl && r1 <= wu || indeig && iiu == 2) {
00480             ++(*m);
00481             w[*m] = r1;
00482             if (wantz && ! zquery) {
00483                 z__[*m * z_dim1 + 1] = cs;
00484                 z__[*m * z_dim1 + 2] = sn;
00485 /*              Note: At most one of SN and CS can be zero. */
00486                 if (sn != 0.f) {
00487                     if (cs != 0.f) {
00488                         isuppz[(*m << 1) - 1] = 1;
00489                         isuppz[(*m << 1) - 1] = 2;
00490                     } else {
00491                         isuppz[(*m << 1) - 1] = 1;
00492                         isuppz[(*m << 1) - 1] = 1;
00493                     }
00494                 } else {
00495                     isuppz[(*m << 1) - 1] = 2;
00496                     isuppz[*m * 2] = 2;
00497                 }
00498             }
00499         }
00500         return 0;
00501     }
00502 /*     Continue with general N */
00503     indgrs = 1;
00504     inderr = (*n << 1) + 1;
00505     indgp = *n * 3 + 1;
00506     indd = (*n << 2) + 1;
00507     inde2 = *n * 5 + 1;
00508     indwrk = *n * 6 + 1;
00509 
00510     iinspl = 1;
00511     iindbl = *n + 1;
00512     iindw = (*n << 1) + 1;
00513     iindwk = *n * 3 + 1;
00514 
00515 /*     Scale matrix to allowable range, if necessary. */
00516 /*     The allowable range is related to the PIVMIN parameter; see the */
00517 /*     comments in SLARRD.  The preference for scaling small values */
00518 /*     up is heuristic; we expect users' matrices not to be close to the */
00519 /*     RMAX threshold. */
00520 
00521     scale = 1.f;
00522     tnrm = slanst_("M", n, &d__[1], &e[1]);
00523     if (tnrm > 0.f && tnrm < rmin) {
00524         scale = rmin / tnrm;
00525     } else if (tnrm > rmax) {
00526         scale = rmax / tnrm;
00527     }
00528     if (scale != 1.f) {
00529         sscal_(n, &scale, &d__[1], &c__1);
00530         i__1 = *n - 1;
00531         sscal_(&i__1, &scale, &e[1], &c__1);
00532         tnrm *= scale;
00533         if (valeig) {
00534 /*           If eigenvalues in interval have to be found, */
00535 /*           scale (WL, WU] accordingly */
00536             wl *= scale;
00537             wu *= scale;
00538         }
00539     }
00540 
00541 /*     Compute the desired eigenvalues of the tridiagonal after splitting */
00542 /*     into smaller subblocks if the corresponding off-diagonal elements */
00543 /*     are small */
00544 /*     THRESH is the splitting parameter for SLARRE */
00545 /*     A negative THRESH forces the old splitting criterion based on the */
00546 /*     size of the off-diagonal. A positive THRESH switches to splitting */
00547 /*     which preserves relative accuracy. */
00548 
00549     if (*tryrac) {
00550 /*        Test whether the matrix warrants the more expensive relative approach. */
00551         slarrr_(n, &d__[1], &e[1], &iinfo);
00552     } else {
00553 /*        The user does not care about relative accurately eigenvalues */
00554         iinfo = -1;
00555     }
00556 /*     Set the splitting criterion */
00557     if (iinfo == 0) {
00558         thresh = eps;
00559     } else {
00560         thresh = -eps;
00561 /*        relative accuracy is desired but T does not guarantee it */
00562         *tryrac = FALSE_;
00563     }
00564 
00565     if (*tryrac) {
00566 /*        Copy original diagonal, needed to guarantee relative accuracy */
00567         scopy_(n, &d__[1], &c__1, &work[indd], &c__1);
00568     }
00569 /*     Store the squares of the offdiagonal values of T */
00570     i__1 = *n - 1;
00571     for (j = 1; j <= i__1; ++j) {
00572 /* Computing 2nd power */
00573         r__1 = e[j];
00574         work[inde2 + j - 1] = r__1 * r__1;
00575 /* L5: */
00576     }
00577 /*     Set the tolerance parameters for bisection */
00578     if (! wantz) {
00579 /*        SLARRE computes the eigenvalues to full precision. */
00580         rtol1 = eps * 4.f;
00581         rtol2 = eps * 4.f;
00582     } else {
00583 /*        SLARRE computes the eigenvalues to less than full precision. */
00584 /*        SLARRV will refine the eigenvalue approximations, and we can */
00585 /*        need less accurate initial bisection in SLARRE. */
00586 /*        Note: these settings do only affect the subset case and SLARRE */
00587 /* Computing MAX */
00588         r__1 = sqrt(eps) * .05f, r__2 = eps * 4.f;
00589         rtol1 = dmax(r__1,r__2);
00590 /* Computing MAX */
00591         r__1 = sqrt(eps) * .005f, r__2 = eps * 4.f;
00592         rtol2 = dmax(r__1,r__2);
00593     }
00594     slarre_(range, n, &wl, &wu, &iil, &iiu, &d__[1], &e[1], &work[inde2], &
00595             rtol1, &rtol2, &thresh, &nsplit, &iwork[iinspl], m, &w[1], &work[
00596             inderr], &work[indgp], &iwork[iindbl], &iwork[iindw], &work[
00597             indgrs], &pivmin, &work[indwrk], &iwork[iindwk], &iinfo);
00598     if (iinfo != 0) {
00599         *info = abs(iinfo) + 10;
00600         return 0;
00601     }
00602 /*     Note that if RANGE .NE. 'V', SLARRE computes bounds on the desired */
00603 /*     part of the spectrum. All desired eigenvalues are contained in */
00604 /*     (WL,WU] */
00605     if (wantz) {
00606 
00607 /*        Compute the desired eigenvectors corresponding to the computed */
00608 /*        eigenvalues */
00609 
00610         slarrv_(n, &wl, &wu, &d__[1], &e[1], &pivmin, &iwork[iinspl], m, &
00611                 c__1, m, &c_b18, &rtol1, &rtol2, &w[1], &work[inderr], &work[
00612                 indgp], &iwork[iindbl], &iwork[iindw], &work[indgrs], &z__[
00613                 z_offset], ldz, &isuppz[1], &work[indwrk], &iwork[iindwk], &
00614                 iinfo);
00615         if (iinfo != 0) {
00616             *info = abs(iinfo) + 20;
00617             return 0;
00618         }
00619     } else {
00620 /*        SLARRE computes eigenvalues of the (shifted) root representation */
00621 /*        SLARRV returns the eigenvalues of the unshifted matrix. */
00622 /*        However, if the eigenvectors are not desired by the user, we need */
00623 /*        to apply the corresponding shifts from SLARRE to obtain the */
00624 /*        eigenvalues of the original matrix. */
00625         i__1 = *m;
00626         for (j = 1; j <= i__1; ++j) {
00627             itmp = iwork[iindbl + j - 1];
00628             w[j] += e[iwork[iinspl + itmp - 1]];
00629 /* L20: */
00630         }
00631     }
00632 
00633     if (*tryrac) {
00634 /*        Refine computed eigenvalues so that they are relatively accurate */
00635 /*        with respect to the original matrix T. */
00636         ibegin = 1;
00637         wbegin = 1;
00638         i__1 = iwork[iindbl + *m - 1];
00639         for (jblk = 1; jblk <= i__1; ++jblk) {
00640             iend = iwork[iinspl + jblk - 1];
00641             in = iend - ibegin + 1;
00642             wend = wbegin - 1;
00643 /*           check if any eigenvalues have to be refined in this block */
00644 L36:
00645             if (wend < *m) {
00646                 if (iwork[iindbl + wend] == jblk) {
00647                     ++wend;
00648                     goto L36;
00649                 }
00650             }
00651             if (wend < wbegin) {
00652                 ibegin = iend + 1;
00653                 goto L39;
00654             }
00655             offset = iwork[iindw + wbegin - 1] - 1;
00656             ifirst = iwork[iindw + wbegin - 1];
00657             ilast = iwork[iindw + wend - 1];
00658             rtol2 = eps * 4.f;
00659             slarrj_(&in, &work[indd + ibegin - 1], &work[inde2 + ibegin - 1], 
00660                     &ifirst, &ilast, &rtol2, &offset, &w[wbegin], &work[
00661                     inderr + wbegin - 1], &work[indwrk], &iwork[iindwk], &
00662                     pivmin, &tnrm, &iinfo);
00663             ibegin = iend + 1;
00664             wbegin = wend + 1;
00665 L39:
00666             ;
00667         }
00668     }
00669 
00670 /*     If matrix was scaled, then rescale eigenvalues appropriately. */
00671 
00672     if (scale != 1.f) {
00673         r__1 = 1.f / scale;
00674         sscal_(m, &r__1, &w[1], &c__1);
00675     }
00676 
00677 /*     If eigenvalues are not in increasing order, then sort them, */
00678 /*     possibly along with eigenvectors. */
00679 
00680     if (nsplit > 1) {
00681         if (! wantz) {
00682             slasrt_("I", m, &w[1], &iinfo);
00683             if (iinfo != 0) {
00684                 *info = 3;
00685                 return 0;
00686             }
00687         } else {
00688             i__1 = *m - 1;
00689             for (j = 1; j <= i__1; ++j) {
00690                 i__ = 0;
00691                 tmp = w[j];
00692                 i__2 = *m;
00693                 for (jj = j + 1; jj <= i__2; ++jj) {
00694                     if (w[jj] < tmp) {
00695                         i__ = jj;
00696                         tmp = w[jj];
00697                     }
00698 /* L50: */
00699                 }
00700                 if (i__ != 0) {
00701                     w[i__] = w[j];
00702                     w[j] = tmp;
00703                     if (wantz) {
00704                         sswap_(n, &z__[i__ * z_dim1 + 1], &c__1, &z__[j * 
00705                                 z_dim1 + 1], &c__1);
00706                         itmp = isuppz[(i__ << 1) - 1];
00707                         isuppz[(i__ << 1) - 1] = isuppz[(j << 1) - 1];
00708                         isuppz[(j << 1) - 1] = itmp;
00709                         itmp = isuppz[i__ * 2];
00710                         isuppz[i__ * 2] = isuppz[j * 2];
00711                         isuppz[j * 2] = itmp;
00712                     }
00713                 }
00714 /* L60: */
00715             }
00716         }
00717     }
00718 
00719 
00720     work[1] = (real) lwmin;
00721     iwork[1] = liwmin;
00722     return 0;
00723 
00724 /*     End of SSTEMR */
00725 
00726 } /* sstemr_ */


swiftnav
Author(s):
autogenerated on Sat Jun 8 2019 18:56:14