#include "clapack.h" /* Subroutine */ int dlarrr_(integer *n, doublereal *d__, doublereal *e, integer *info) { /* System generated locals */ integer i__1; doublereal d__1; /* Builtin functions */ double sqrt(doublereal); /* Local variables */ integer i__; doublereal eps, tmp, tmp2, rmin; extern doublereal dlamch_(char *); doublereal offdig, safmin; logical yesrel; doublereal smlnum, offdig2; /* -- LAPACK auxiliary routine (version 3.1) -- */ /* Univ. of Tennessee, Univ. of California Berkeley and NAG Ltd.. */ /* November 2006 */ /* .. Scalar Arguments .. */ /* .. */ /* .. Array Arguments .. */ /* .. */ /* Purpose */ /* ======= */ /* Perform tests to decide whether the symmetric tridiagonal matrix T */ /* warrants expensive computations which guarantee high relative accuracy */ /* in the eigenvalues. */ /* Arguments */ /* ========= */ /* N (input) INTEGER */ /* The order of the matrix. N > 0. */ /* D (input) DOUBLE PRECISION array, dimension (N) */ /* The N diagonal elements of the tridiagonal matrix T. */ /* E (input/output) DOUBLE PRECISION array, dimension (N) */ /* On entry, the first (N-1) entries contain the subdiagonal */ /* elements of the tridiagonal matrix T; E(N) is set to ZERO. */ /* INFO (output) INTEGER */ /* INFO = 0(default) : the matrix warrants computations preserving */ /* relative accuracy. */ /* INFO = 1 : the matrix warrants computations guaranteeing */ /* only absolute accuracy. */ /* Further Details */ /* =============== */ /* Based on contributions by */ /* Beresford Parlett, University of California, Berkeley, USA */ /* Jim Demmel, University of California, Berkeley, USA */ /* Inderjit Dhillon, University of Texas, Austin, USA */ /* Osni Marques, LBNL/NERSC, USA */ /* Christof Voemel, University of California, Berkeley, USA */ /* ===================================================================== */ /* .. Parameters .. */ /* .. */ /* .. Local Scalars .. */ /* .. */ /* .. External Functions .. */ /* .. */ /* .. Intrinsic Functions .. */ /* .. */ /* .. Executable Statements .. */ /* As a default, do NOT go for relative-accuracy preserving computations. */ /* Parameter adjustments */ --e; --d__; /* Function Body */ *info = 1; safmin = dlamch_("Safe minimum"); eps = dlamch_("Precision"); smlnum = safmin / eps; rmin = sqrt(smlnum); /* Tests for relative accuracy */ /* Test for scaled diagonal dominance */ /* Scale the diagonal entries to one and check whether the sum of the */ /* off-diagonals is less than one */ /* The sdd relative error bounds have a 1/(1- 2*x) factor in them, */ /* x = max(OFFDIG + OFFDIG2), so when x is close to 1/2, no relative */ /* accuracy is promised. In the notation of the code fragment below, */ /* 1/(1 - (OFFDIG + OFFDIG2)) is the condition number. */ /* We don't think it is worth going into "sdd mode" unless the relative */ /* condition number is reasonable, not 1/macheps. */ /* The threshold should be compatible with other thresholds used in the */ /* code. We set OFFDIG + OFFDIG2 <= .999 =: RELCOND, it corresponds */ /* to losing at most 3 decimal digits: 1 / (1 - (OFFDIG + OFFDIG2)) <= 1000 */ /* instead of the current OFFDIG + OFFDIG2 < 1 */ yesrel = TRUE_; offdig = 0.; tmp = sqrt((abs(d__[1]))); if (tmp < rmin) { yesrel = FALSE_; } if (! yesrel) { goto L11; } i__1 = *n; for (i__ = 2; i__ <= i__1; ++i__) { tmp2 = sqrt((d__1 = d__[i__], abs(d__1))); if (tmp2 < rmin) { yesrel = FALSE_; } if (! yesrel) { goto L11; } offdig2 = (d__1 = e[i__ - 1], abs(d__1)) / (tmp * tmp2); if (offdig + offdig2 >= .999) { yesrel = FALSE_; } if (! yesrel) { goto L11; } tmp = tmp2; offdig = offdig2; /* L10: */ } L11: if (yesrel) { *info = 0; return 0; } else { } /* *** MORE TO BE IMPLEMENTED *** */ /* Test if the lower bidiagonal matrix L from T = L D L^T */ /* (zero shift facto) is well conditioned */ /* Test if the upper bidiagonal matrix U from T = U D U^T */ /* (zero shift facto) is well conditioned. */ /* In this case, the matrix needs to be flipped and, at the end */ /* of the eigenvector computation, the flip needs to be applied */ /* to the computed eigenvectors (and the support) */ return 0; /* END OF DLARRR */ } /* dlarrr_ */