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


swiftnav
Author(s):
autogenerated on Sat Jun 8 2019 18:55:34