00001 /* sstech.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 sstech_(integer *n, real *a, real *b, real *eig, real * 00017 tol, real *work, integer *info) 00018 { 00019 /* System generated locals */ 00020 integer i__1, i__2; 00021 real r__1, r__2, r__3; 00022 00023 /* Local variables */ 00024 integer i__, j; 00025 real mx, eps, emin; 00026 integer isub, bpnt, numl, numu, tpnt, count; 00027 real lower, upper, tuppr; 00028 extern doublereal slamch_(char *); 00029 real unflep; 00030 extern /* Subroutine */ int sstect_(integer *, real *, real *, real *, 00031 integer *); 00032 00033 00034 /* -- LAPACK test routine (version 3.1) -- */ 00035 /* Univ. of Tennessee, Univ. of California Berkeley and NAG Ltd.. */ 00036 /* November 2006 */ 00037 00038 /* .. Scalar Arguments .. */ 00039 /* .. */ 00040 /* .. Array Arguments .. */ 00041 /* .. */ 00042 00043 /* Purpose */ 00044 /* ======= */ 00045 00046 /* Let T be the tridiagonal matrix with diagonal entries A(1) ,..., */ 00047 /* A(N) and offdiagonal entries B(1) ,..., B(N-1)). SSTECH checks to */ 00048 /* see if EIG(1) ,..., EIG(N) are indeed accurate eigenvalues of T. */ 00049 /* It does this by expanding each EIG(I) into an interval */ 00050 /* [SVD(I) - EPS, SVD(I) + EPS], merging overlapping intervals if */ 00051 /* any, and using Sturm sequences to count and verify whether each */ 00052 /* resulting interval has the correct number of eigenvalues (using */ 00053 /* SSTECT). Here EPS = TOL*MACHEPS*MAXEIG, where MACHEPS is the */ 00054 /* machine precision and MAXEIG is the absolute value of the largest */ 00055 /* eigenvalue. If each interval contains the correct number of */ 00056 /* eigenvalues, INFO = 0 is returned, otherwise INFO is the index of */ 00057 /* the first eigenvalue in the first bad interval. */ 00058 00059 /* Arguments */ 00060 /* ========= */ 00061 00062 /* N (input) INTEGER */ 00063 /* The dimension of the tridiagonal matrix T. */ 00064 00065 /* A (input) REAL array, dimension (N) */ 00066 /* The diagonal entries of the tridiagonal matrix T. */ 00067 00068 /* B (input) REAL array, dimension (N-1) */ 00069 /* The offdiagonal entries of the tridiagonal matrix T. */ 00070 00071 /* EIG (input) REAL array, dimension (N) */ 00072 /* The purported eigenvalues to be checked. */ 00073 00074 /* TOL (input) REAL */ 00075 /* Error tolerance for checking, a multiple of the */ 00076 /* machine precision. */ 00077 00078 /* WORK (workspace) REAL array, dimension (N) */ 00079 00080 /* INFO (output) INTEGER */ 00081 /* 0 if the eigenvalues are all correct (to within */ 00082 /* 1 +- TOL*MACHEPS*MAXEIG) */ 00083 /* >0 if the interval containing the INFO-th eigenvalue */ 00084 /* contains the incorrect number of eigenvalues. */ 00085 00086 /* ===================================================================== */ 00087 00088 /* .. Parameters .. */ 00089 /* .. */ 00090 /* .. Local Scalars .. */ 00091 /* .. */ 00092 /* .. External Functions .. */ 00093 /* .. */ 00094 /* .. External Subroutines .. */ 00095 /* .. */ 00096 /* .. Intrinsic Functions .. */ 00097 /* .. */ 00098 /* .. Executable Statements .. */ 00099 00100 /* Check input parameters */ 00101 00102 /* Parameter adjustments */ 00103 --work; 00104 --eig; 00105 --b; 00106 --a; 00107 00108 /* Function Body */ 00109 *info = 0; 00110 if (*n == 0) { 00111 return 0; 00112 } 00113 if (*n < 0) { 00114 *info = -1; 00115 return 0; 00116 } 00117 if (*tol < 0.f) { 00118 *info = -5; 00119 return 0; 00120 } 00121 00122 /* Get machine constants */ 00123 00124 eps = slamch_("Epsilon") * slamch_("Base"); 00125 unflep = slamch_("Safe minimum") / eps; 00126 eps = *tol * eps; 00127 00128 /* Compute maximum absolute eigenvalue, error tolerance */ 00129 00130 mx = dabs(eig[1]); 00131 i__1 = *n; 00132 for (i__ = 2; i__ <= i__1; ++i__) { 00133 /* Computing MAX */ 00134 r__2 = mx, r__3 = (r__1 = eig[i__], dabs(r__1)); 00135 mx = dmax(r__2,r__3); 00136 /* L10: */ 00137 } 00138 /* Computing MAX */ 00139 r__1 = eps * mx; 00140 eps = dmax(r__1,unflep); 00141 00142 /* Sort eigenvalues from EIG into WORK */ 00143 00144 i__1 = *n; 00145 for (i__ = 1; i__ <= i__1; ++i__) { 00146 work[i__] = eig[i__]; 00147 /* L20: */ 00148 } 00149 i__1 = *n - 1; 00150 for (i__ = 1; i__ <= i__1; ++i__) { 00151 isub = 1; 00152 emin = work[1]; 00153 i__2 = *n + 1 - i__; 00154 for (j = 2; j <= i__2; ++j) { 00155 if (work[j] < emin) { 00156 isub = j; 00157 emin = work[j]; 00158 } 00159 /* L30: */ 00160 } 00161 if (isub != *n + 1 - i__) { 00162 work[isub] = work[*n + 1 - i__]; 00163 work[*n + 1 - i__] = emin; 00164 } 00165 /* L40: */ 00166 } 00167 00168 /* TPNT points to singular value at right endpoint of interval */ 00169 /* BPNT points to singular value at left endpoint of interval */ 00170 00171 tpnt = 1; 00172 bpnt = 1; 00173 00174 /* Begin loop over all intervals */ 00175 00176 L50: 00177 upper = work[tpnt] + eps; 00178 lower = work[bpnt] - eps; 00179 00180 /* Begin loop merging overlapping intervals */ 00181 00182 L60: 00183 if (bpnt == *n) { 00184 goto L70; 00185 } 00186 tuppr = work[bpnt + 1] + eps; 00187 if (tuppr < lower) { 00188 goto L70; 00189 } 00190 00191 /* Merge */ 00192 00193 ++bpnt; 00194 lower = work[bpnt] - eps; 00195 goto L60; 00196 L70: 00197 00198 /* Count singular values in interval [ LOWER, UPPER ] */ 00199 00200 sstect_(n, &a[1], &b[1], &lower, &numl); 00201 sstect_(n, &a[1], &b[1], &upper, &numu); 00202 count = numu - numl; 00203 if (count != bpnt - tpnt + 1) { 00204 00205 /* Wrong number of singular values in interval */ 00206 00207 *info = tpnt; 00208 goto L80; 00209 } 00210 tpnt = bpnt + 1; 00211 bpnt = tpnt; 00212 if (tpnt <= *n) { 00213 goto L50; 00214 } 00215 L80: 00216 return 0; 00217 00218 /* End of SSTECH */ 00219 00220 } /* sstech_ */