sstech.c
Go to the documentation of this file.
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_ */


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