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