home *** CD-ROM | disk | FTP | other *** search
- /************************************************************************
- * *
- * N O T I C E *
- * *
- * Copyright Abandoned, 1987, Fred Fish *
- * *
- * This previously copyrighted work has been placed into the *
- * public domain by the author (Fred Fish) and may be freely used *
- * for any purpose, private or commercial. I would appreciate *
- * it, as a courtesy, if this notice is left in all copies and *
- * derivative works. Thank you, and enjoy... *
- * *
- * The author makes no warranty of any kind with respect to this *
- * product and explicitly disclaims any implied warranties of *
- * merchantability or fitness for any particular purpose. *
- * *
- ************************************************************************
- */
-
-
- /*
- * FUNCTION
- *
- * sqrt double precision square root
- *
- * KEY WORDS
- *
- * 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
- *
- * 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.
- *
- * NOTES
- *
- * The Convergent Technologies compiler optimizes division
- * by powers of two to "arithmetic shift right" instructions.
- * This is ok for positive integers but gives different
- * results than other C compilers for negative integers.
- * For example, (-1)/2 is -1 on the CT box, 0 on every other
- * machine I tried.
- *
- */
- /*
- * MODIFICATIONS
- *
- * This routine modified to use polynomial, instead of rational,
- * approximation with coefficients
- *
- * P0 0.22906994529e+00
- * P1 0.13006690496e+01
- * P2 -0.90932104982e+00
- * P3 0.50104207633e+00
- * P4 -0.12146838249e+00
- *
- * as given by Hart (op. cit.) in SQRT 0132. This approximation
- * gives around 5 digits correct. Two applications of Heron's
- * approximation will give more then practically achievable
- * 13-15 decimal digits. Multiplications by powers of 2 are
- * replaced by explicit calls to ldexp.
- *
- * Michal Jaegermann, 24 October 1990
- */
-
- #include <stdio.h>
- #include <pmluser.h>
- #include "pml.h"
-
- #ifdef OLD
- #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 */
-
- #endif
-
- #define P0 0.22906994529e+00 /* Hart SQRT 0132 */
- #define P1 0.13006690496e+01
- #define P2 -0.90932104982e+00
- #define P3 0.50104207633e+00
- #define P4 -0.12146838249e+00
-
- static char funcname[] = "sqrt";
-
-
- double sqrt (x)
- double x;
- {
- #ifdef OLD
- auto int k;
- register int bugfix;
- register int kmod2;
- register int count;
- auto int exponent;
- #else
- #ifdef __MSHORT__
- auto short k;
- #else
- auto int k;
- #endif
- #endif
- auto double m;
- auto double u;
- #ifdef OLD
- auto double y;
- #endif
- auto struct exception xcpt;
- extern double frexp ();
- extern double ldexp ();
-
- DBUG_ENTER ("sqrt");
- DBUG_3 ("sqrtin", "arg %le", x);
- if (x == 0.0) {
- xcpt.retval = 0.0;
- } else if (x < 0.0) {
- xcpt.type = DOMAIN;
- xcpt.name = funcname;
- xcpt.arg1 = x;
- if (!matherr (&xcpt)) {
- fprintf (stderr, "%s: DOMAIN error\n", funcname);
- errno = EDOM;
- xcpt.retval = 0.0;
- }
- } else {
- m = frexp (x, &k);
- #ifdef OLD
- u = (P0 + (P1 * m)) / (Q0 + (Q1 * m));
- for (count = 0, y = u; count < ITERATIONS; count++) {
- y = 0.5 * (y + (m / y));
- }
- if ((kmod2 = (k % 2)) < 0) {
- y /= SQRT2;
- } else if (kmod2 > 0) {
- y *= SQRT2;
- }
- bugfix = 2;
- xcpt.retval = ldexp (y, k/bugfix);
- #else
- u = (((P4 * m + P3) * m + P2) * m + P1) * m + P0;
- u = ldexp((u + (m / u)), -1); /* Heron's iteration */
- u += m / u; /* and a part of the second one */
- if (k & 1) {
- u *= SQRT2;
- }
- /*
- * here we rely on the fact that -3/2 and (-3 >> 1)
- * do give different results
- */
- xcpt.retval = ldexp (u, (k >> 1) - 1);
- #endif
- }
- DBUG_3 ("sqrtout", "result %le", xcpt.retval);
- DBUG_RETURN (xcpt.retval);
- }
-