/* dsvdct.f -- translated by f2c (version 20061008). You must link the resulting object file with libf2c: on Microsoft Windows system, link with libf2c.lib; on Linux or Unix systems, link with .../path/to/libf2c.a -lm or, if you install libf2c.a in a standard place, with -lf2c -lm -- in that order, at the end of the command line, as in cc *.o -lf2c -lm Source for libf2c is in /netlib/f2c/libf2c.zip, e.g., http://www.netlib.org/f2c/libf2c.zip */ #include "f2c.h" #include "blaswrap.h" /* Subroutine */ int dsvdct_(integer *n, doublereal *s, doublereal *e, doublereal *shift, integer *num) { /* System generated locals */ integer i__1; doublereal d__1, d__2, d__3, d__4; /* Builtin functions */ double sqrt(doublereal); /* Local variables */ integer i__; doublereal u, m1, m2, mx, tmp, tom, sun, sov, unfl, ovfl, ssun; extern doublereal dlamch_(char *); doublereal sshift; /* -- LAPACK test routine (version 3.1) -- */ /* Univ. of Tennessee, Univ. of California Berkeley and NAG Ltd.. */ /* November 2006 */ /* .. Scalar Arguments .. */ /* .. */ /* .. Array Arguments .. */ /* .. */ /* Purpose */ /* ======= */ /* DSVDCT counts the number NUM of eigenvalues of a 2*N by 2*N */ /* tridiagonal matrix T which are less than or equal to SHIFT. T is */ /* formed by putting zeros on the diagonal and making the off-diagonals */ /* equal to S(1), E(1), S(2), E(2), ... , E(N-1), S(N). If SHIFT is */ /* positive, NUM is equal to N plus the number of singular values of a */ /* bidiagonal matrix B less than or equal to SHIFT. Here B has diagonal */ /* entries S(1), ..., S(N) and superdiagonal entries E(1), ... E(N-1). */ /* If SHIFT is negative, NUM is equal to the number of singular values */ /* of B greater than or equal to -SHIFT. */ /* See W. Kahan "Accurate Eigenvalues of a Symmetric Tridiagonal */ /* Matrix", Report CS41, Computer Science Dept., Stanford University, */ /* July 21, 1966 */ /* Arguments */ /* ========= */ /* N (input) INTEGER */ /* The dimension of the bidiagonal matrix B. */ /* S (input) DOUBLE PRECISION array, dimension (N) */ /* The diagonal entries of the bidiagonal matrix B. */ /* E (input) DOUBLE PRECISION array of dimension (N-1) */ /* The superdiagonal entries of the bidiagonal matrix B. */ /* SHIFT (input) DOUBLE PRECISION */ /* The shift, used as described under Purpose. */ /* NUM (output) INTEGER */ /* The number of eigenvalues of T less than or equal to SHIFT. */ /* ===================================================================== */ /* .. Parameters .. */ /* .. */ /* .. Local Scalars .. */ /* .. */ /* .. External Functions .. */ /* .. */ /* .. Intrinsic Functions .. */ /* .. */ /* .. Executable Statements .. */ /* Get machine constants */ /* Parameter adjustments */ --e; --s; /* Function Body */ unfl = dlamch_("Safe minimum") * 2; ovfl = 1. / unfl; /* Find largest entry */ mx = abs(s[1]); i__1 = *n - 1; for (i__ = 1; i__ <= i__1; ++i__) { /* Computing MAX */ d__3 = mx, d__4 = (d__1 = s[i__ + 1], abs(d__1)), d__3 = max(d__3, d__4), d__4 = (d__2 = e[i__], abs(d__2)); mx = max(d__3,d__4); /* L10: */ } if (mx == 0.) { if (*shift < 0.) { *num = 0; } else { *num = *n << 1; } return 0; } /* Compute scale factors as in Kahan's report */ sun = sqrt(unfl); ssun = sqrt(sun); sov = sqrt(ovfl); tom = ssun * sov; if (mx <= 1.) { m1 = 1. / mx; m2 = tom; } else { m1 = 1.; m2 = tom / mx; } /* Begin counting */ u = 1.; *num = 0; sshift = *shift * m1 * m2; u = -sshift; if (u <= sun) { if (u <= 0.) { ++(*num); if (u > -sun) { u = -sun; } } else { u = sun; } } tmp = s[1] * m1 * m2; u = -tmp * (tmp / u) - sshift; if (u <= sun) { if (u <= 0.) { ++(*num); if (u > -sun) { u = -sun; } } else { u = sun; } } i__1 = *n - 1; for (i__ = 1; i__ <= i__1; ++i__) { tmp = e[i__] * m1 * m2; u = -tmp * (tmp / u) - sshift; if (u <= sun) { if (u <= 0.) { ++(*num); if (u > -sun) { u = -sun; } } else { u = sun; } } tmp = s[i__ + 1] * m1 * m2; u = -tmp * (tmp / u) - sshift; if (u <= sun) { if (u <= 0.) { ++(*num); if (u > -sun) { u = -sun; } } else { u = sun; } } /* L20: */ } return 0; /* End of DSVDCT */ } /* dsvdct_ */