00001 /* slarrj.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 /* Subroutine */ int slarrj_(integer *n, real *d__, real *e2, integer *ifirst, 00017 integer *ilast, real *rtol, integer *offset, real *w, real *werr, 00018 real *work, integer *iwork, real *pivmin, real *spdiam, integer *info) 00019 { 00020 /* System generated locals */ 00021 integer i__1, i__2; 00022 real r__1, r__2; 00023 00024 /* Builtin functions */ 00025 double log(doublereal); 00026 00027 /* Local variables */ 00028 integer i__, j, k, p; 00029 real s; 00030 integer i1, i2, ii; 00031 real fac, mid; 00032 integer cnt; 00033 real tmp, left; 00034 integer iter, nint, prev, next, savi1; 00035 real right, width, dplus; 00036 integer olnint, maxitr; 00037 00038 00039 /* -- LAPACK auxiliary routine (version 3.2) -- */ 00040 /* Univ. of Tennessee, Univ. of California Berkeley and NAG Ltd.. */ 00041 /* November 2006 */ 00042 00043 /* .. Scalar Arguments .. */ 00044 /* .. */ 00045 /* .. Array Arguments .. */ 00046 /* .. */ 00047 00048 /* Purpose */ 00049 /* ======= */ 00050 00051 /* Given the initial eigenvalue approximations of T, SLARRJ */ 00052 /* does bisection to refine the eigenvalues of T, */ 00053 /* W( IFIRST-OFFSET ) through W( ILAST-OFFSET ), to more accuracy. Initial */ 00054 /* guesses for these eigenvalues are input in W, the corresponding estimate */ 00055 /* of the error in these guesses in WERR. During bisection, intervals */ 00056 /* [left, right] are maintained by storing their mid-points and */ 00057 /* semi-widths in the arrays W and WERR respectively. */ 00058 00059 /* Arguments */ 00060 /* ========= */ 00061 00062 /* N (input) INTEGER */ 00063 /* The order of the matrix. */ 00064 00065 /* D (input) REAL array, dimension (N) */ 00066 /* The N diagonal elements of T. */ 00067 00068 /* E2 (input) REAL array, dimension (N-1) */ 00069 /* The Squares of the (N-1) subdiagonal elements of T. */ 00070 00071 /* IFIRST (input) INTEGER */ 00072 /* The index of the first eigenvalue to be computed. */ 00073 00074 /* ILAST (input) INTEGER */ 00075 /* The index of the last eigenvalue to be computed. */ 00076 00077 /* RTOL (input) REAL */ 00078 /* Tolerance for the convergence of the bisection intervals. */ 00079 /* An interval [LEFT,RIGHT] has converged if */ 00080 /* RIGHT-LEFT.LT.RTOL*MAX(|LEFT|,|RIGHT|). */ 00081 00082 /* OFFSET (input) INTEGER */ 00083 /* Offset for the arrays W and WERR, i.e., the IFIRST-OFFSET */ 00084 /* through ILAST-OFFSET elements of these arrays are to be used. */ 00085 00086 /* W (input/output) REAL array, dimension (N) */ 00087 /* On input, W( IFIRST-OFFSET ) through W( ILAST-OFFSET ) are */ 00088 /* estimates of the eigenvalues of L D L^T indexed IFIRST through */ 00089 /* ILAST. */ 00090 /* On output, these estimates are refined. */ 00091 00092 /* WERR (input/output) REAL array, dimension (N) */ 00093 /* On input, WERR( IFIRST-OFFSET ) through WERR( ILAST-OFFSET ) are */ 00094 /* the errors in the estimates of the corresponding elements in W. */ 00095 /* On output, these errors are refined. */ 00096 00097 /* WORK (workspace) REAL array, dimension (2*N) */ 00098 /* Workspace. */ 00099 00100 /* IWORK (workspace) INTEGER array, dimension (2*N) */ 00101 /* Workspace. */ 00102 00103 /* PIVMIN (input) DOUBLE PRECISION */ 00104 /* The minimum pivot in the Sturm sequence for T. */ 00105 00106 /* SPDIAM (input) DOUBLE PRECISION */ 00107 /* The spectral diameter of T. */ 00108 00109 /* INFO (output) INTEGER */ 00110 /* Error flag. */ 00111 00112 /* Further Details */ 00113 /* =============== */ 00114 00115 /* Based on contributions by */ 00116 /* Beresford Parlett, University of California, Berkeley, USA */ 00117 /* Jim Demmel, University of California, Berkeley, USA */ 00118 /* Inderjit Dhillon, University of Texas, Austin, USA */ 00119 /* Osni Marques, LBNL/NERSC, USA */ 00120 /* Christof Voemel, University of California, Berkeley, USA */ 00121 00122 /* ===================================================================== */ 00123 00124 /* .. Parameters .. */ 00125 /* .. */ 00126 /* .. Local Scalars .. */ 00127 00128 /* .. */ 00129 /* .. Intrinsic Functions .. */ 00130 /* .. */ 00131 /* .. Executable Statements .. */ 00132 00133 /* Parameter adjustments */ 00134 --iwork; 00135 --work; 00136 --werr; 00137 --w; 00138 --e2; 00139 --d__; 00140 00141 /* Function Body */ 00142 *info = 0; 00143 00144 maxitr = (integer) ((log(*spdiam + *pivmin) - log(*pivmin)) / log(2.f)) + 00145 2; 00146 00147 /* Initialize unconverged intervals in [ WORK(2*I-1), WORK(2*I) ]. */ 00148 /* The Sturm Count, Count( WORK(2*I-1) ) is arranged to be I-1, while */ 00149 /* Count( WORK(2*I) ) is stored in IWORK( 2*I ). The integer IWORK( 2*I-1 ) */ 00150 /* for an unconverged interval is set to the index of the next unconverged */ 00151 /* interval, and is -1 or 0 for a converged interval. Thus a linked */ 00152 /* list of unconverged intervals is set up. */ 00153 00154 i1 = *ifirst; 00155 i2 = *ilast; 00156 /* The number of unconverged intervals */ 00157 nint = 0; 00158 /* The last unconverged interval found */ 00159 prev = 0; 00160 i__1 = i2; 00161 for (i__ = i1; i__ <= i__1; ++i__) { 00162 k = i__ << 1; 00163 ii = i__ - *offset; 00164 left = w[ii] - werr[ii]; 00165 mid = w[ii]; 00166 right = w[ii] + werr[ii]; 00167 width = right - mid; 00168 /* Computing MAX */ 00169 r__1 = dabs(left), r__2 = dabs(right); 00170 tmp = dmax(r__1,r__2); 00171 /* The following test prevents the test of converged intervals */ 00172 if (width < *rtol * tmp) { 00173 /* This interval has already converged and does not need refinement. */ 00174 /* (Note that the gaps might change through refining the */ 00175 /* eigenvalues, however, they can only get bigger.) */ 00176 /* Remove it from the list. */ 00177 iwork[k - 1] = -1; 00178 /* Make sure that I1 always points to the first unconverged interval */ 00179 if (i__ == i1 && i__ < i2) { 00180 i1 = i__ + 1; 00181 } 00182 if (prev >= i1 && i__ <= i2) { 00183 iwork[(prev << 1) - 1] = i__ + 1; 00184 } 00185 } else { 00186 /* unconverged interval found */ 00187 prev = i__; 00188 /* Make sure that [LEFT,RIGHT] contains the desired eigenvalue */ 00189 00190 /* Do while( CNT(LEFT).GT.I-1 ) */ 00191 00192 fac = 1.f; 00193 L20: 00194 cnt = 0; 00195 s = left; 00196 dplus = d__[1] - s; 00197 if (dplus < 0.f) { 00198 ++cnt; 00199 } 00200 i__2 = *n; 00201 for (j = 2; j <= i__2; ++j) { 00202 dplus = d__[j] - s - e2[j - 1] / dplus; 00203 if (dplus < 0.f) { 00204 ++cnt; 00205 } 00206 /* L30: */ 00207 } 00208 if (cnt > i__ - 1) { 00209 left -= werr[ii] * fac; 00210 fac *= 2.f; 00211 goto L20; 00212 } 00213 00214 /* Do while( CNT(RIGHT).LT.I ) */ 00215 00216 fac = 1.f; 00217 L50: 00218 cnt = 0; 00219 s = right; 00220 dplus = d__[1] - s; 00221 if (dplus < 0.f) { 00222 ++cnt; 00223 } 00224 i__2 = *n; 00225 for (j = 2; j <= i__2; ++j) { 00226 dplus = d__[j] - s - e2[j - 1] / dplus; 00227 if (dplus < 0.f) { 00228 ++cnt; 00229 } 00230 /* L60: */ 00231 } 00232 if (cnt < i__) { 00233 right += werr[ii] * fac; 00234 fac *= 2.f; 00235 goto L50; 00236 } 00237 ++nint; 00238 iwork[k - 1] = i__ + 1; 00239 iwork[k] = cnt; 00240 } 00241 work[k - 1] = left; 00242 work[k] = right; 00243 /* L75: */ 00244 } 00245 savi1 = i1; 00246 00247 /* Do while( NINT.GT.0 ), i.e. there are still unconverged intervals */ 00248 /* and while (ITER.LT.MAXITR) */ 00249 00250 iter = 0; 00251 L80: 00252 prev = i1 - 1; 00253 i__ = i1; 00254 olnint = nint; 00255 i__1 = olnint; 00256 for (p = 1; p <= i__1; ++p) { 00257 k = i__ << 1; 00258 ii = i__ - *offset; 00259 next = iwork[k - 1]; 00260 left = work[k - 1]; 00261 right = work[k]; 00262 mid = (left + right) * .5f; 00263 /* semiwidth of interval */ 00264 width = right - mid; 00265 /* Computing MAX */ 00266 r__1 = dabs(left), r__2 = dabs(right); 00267 tmp = dmax(r__1,r__2); 00268 if (width < *rtol * tmp || iter == maxitr) { 00269 /* reduce number of unconverged intervals */ 00270 --nint; 00271 /* Mark interval as converged. */ 00272 iwork[k - 1] = 0; 00273 if (i1 == i__) { 00274 i1 = next; 00275 } else { 00276 /* Prev holds the last unconverged interval previously examined */ 00277 if (prev >= i1) { 00278 iwork[(prev << 1) - 1] = next; 00279 } 00280 } 00281 i__ = next; 00282 goto L100; 00283 } 00284 prev = i__; 00285 00286 /* Perform one bisection step */ 00287 00288 cnt = 0; 00289 s = mid; 00290 dplus = d__[1] - s; 00291 if (dplus < 0.f) { 00292 ++cnt; 00293 } 00294 i__2 = *n; 00295 for (j = 2; j <= i__2; ++j) { 00296 dplus = d__[j] - s - e2[j - 1] / dplus; 00297 if (dplus < 0.f) { 00298 ++cnt; 00299 } 00300 /* L90: */ 00301 } 00302 if (cnt <= i__ - 1) { 00303 work[k - 1] = mid; 00304 } else { 00305 work[k] = mid; 00306 } 00307 i__ = next; 00308 L100: 00309 ; 00310 } 00311 ++iter; 00312 /* do another loop if there are still unconverged intervals */ 00313 /* However, in the last iteration, all intervals are accepted */ 00314 /* since this is the best we can do. */ 00315 if (nint > 0 && iter <= maxitr) { 00316 goto L80; 00317 } 00318 00319 00320 /* At this point, all the intervals have converged */ 00321 i__1 = *ilast; 00322 for (i__ = savi1; i__ <= i__1; ++i__) { 00323 k = i__ << 1; 00324 ii = i__ - *offset; 00325 /* All intervals marked by '0' have been refined. */ 00326 if (iwork[k - 1] == 0) { 00327 w[ii] = (work[k - 1] + work[k]) * .5f; 00328 werr[ii] = work[k] - w[ii]; 00329 } 00330 /* L110: */ 00331 } 00332 00333 return 0; 00334 00335 /* End of SLARRJ */ 00336 00337 } /* slarrj_ */