Trailing-Edge
-
PDP-10 Archives
-
SRI_NIC_PERM_FS_1_19910112
-
kcc-5/lib/math/sqrt.c
There are 7 other files named sqrt.c in the archive. Click here to see a list.
/*
* +++ NAME +++
*
* SQRT Double precision square root
*
* +++ INDEX +++
*
* SQRT
* machine independent routines
* math libraries
*
* +++ DESCRIPTION +++
*
* Returns double precision square root of double precision
* floating point argument.
*
* +++ USAGE +++
*
* double sqrt(x)
* double x;
*
* +++ REFERENCES +++
*
* Fortran IV-PLUS user's guide, Digital Equipment Corp. pp B-7.
*
* Computer Approximations, J.F. Hart et al, John Wiley & Sons,
* 1968, pp. 89-96.
*
* +++ RESTRICTIONS +++
*
* The relative error is 10**(-30.1) after three applications
* of Heron's iteration for the square root.
*
* However, this assumes exact arithmetic in the iterations
* and initial approximation. Additional errors may occur
* due to truncation, rounding, or machine precision limits.
*
* +++ PROGRAMMER +++
*
* Fred Fish
* Goodyear Aerospace Corp, Arizona Div.
* (602) 932-7000 work
* (602) 894-6881 home
*
* Updated Dec 85 for inclusion in standard math library. This routine
* now conforms with the description of the sqrt function as defined in
* Harbison & Steele's "C: A Reference Manual", section 11.3.23
*
* +++ INTERNALS +++
*
* Computes square root by:
*
* (1) Range reduction of argument to [0.5,1.0]
* by application of identity:
*
* sqrt(x) = 2**(k/2) * sqrt(x * 2**(-k))
*
* k is the exponent when x is written as
* a mantissa times a power of 2 (m * 2**k).
* It is assumed that the mantissa is
* already normalized (0.5 =< m < 1.0).
*
* (2) An approximation to sqrt(m) is obtained
* from:
*
* u = sqrt(m) = (P0 + P1*m) / (Q0 + Q1*m)
*
* P0 = 0.594604482
* P1 = 2.54164041
* Q0 = 2.13725758
* Q1 = 1.0
*
* (coefficients from HART table #350 pg 193)
*
* (3) Three applications of Heron's iteration are
* performed using:
*
* y[n+1] = 0.5 * (y[n] + (m/y[n]))
*
* where y[0] = u = approx sqrt(m)
*
* (4) If the value of k was odd then y is either
* multiplied by the square root of two or
* divided by the square root of two for k positive
* or negative respectively. This rescales y
* by multiplying by 2**frac(k/2).
*
* (5) Finally, y is rescaled by int(k/2) which
* is equivalent to multiplication by 2**int(k/2).
*
* The result of steps 4 and 5 is that the value
* of y between 0.5 and 1.0 has been rescaled by
* 2**(k/2) which removes the original rescaling
* done prior to finding the mantissa square root.
*
* ---
*/
#include "math.h"
#include "errno.h"
#define P0 0.594604482 /* Approximation coeff */
#define P1 2.54164041 /* Approximation coeff */
#define Q0 2.13725758 /* Approximation coeff */
#define Q1 1.0 /* Approximation coeff */
#define ITERATIONS 3 /* Number of iterations */
double sqrt(x)
double x;
{
register int k, kmod2, rescale, count;
double m, u, y, ynext;
if (x == 0.0)
return 0.0;
else if (x < 0.0) {
errno = EDOM;
return 0.0;
} else {
k = _xexp(x);
m = _xmant(x);
u = (P0 + P1 * m) / (Q0 + Q1 * m);
for (count = 0, y = u; count < ITERATIONS; count++) {
ynext = 0.5 * (y + (m / y));
y = ynext;
}
rescale = k / 2;
if ((kmod2 = k % 2) < 0)
y /= SQRT2;
else if (kmod2 > 0)
y *= SQRT2;
return ldexp(y, rescale);
}
}