home *** CD-ROM | disk | FTP | other *** search
- /* sqrt.c
- *
- * Square root
- *
- *
- *
- * SYNOPSIS:
- *
- * double x, y, sqrt();
- *
- * y = sqrt( x );
- *
- *
- *
- * DESCRIPTION:
- *
- * Returns the square root of x.
- *
- * Range reduction involves isolating the power of two of the
- * argument and using a polynomial approximation to obtain
- * a rough value for the square root. Then Heron's iteration
- * is used three times to converge to an accurate value.
- *
- *
- *
- * ACCURACY:
- *
- *
- * Relative error:
- * arithmetic range # trials peak rms
- * DEC 0, 30 2000 2.1e-17 5.2e-18
- * IEEE 0,1.7e308 15000 1.6e-16 5.9e-17
- *
- *
- * ERROR MESSAGES:
- *
- * message condition value returned
- * sqrt domain x < 0 0.0
- *
- */
-
- /*
- Cephes Math Library Release 2.0: April, 1987
- Copyright 1984, 1987 by Stephen L. Moshier
- Direct inquiries to 30 Frost Street, Cambridge, MA 02140
- */
-
- #include "mconf.h"
-
- extern double SQRT2; /* SQRT2 = 1.41421356237309504880 */
-
- double sqrt(x)
- double x;
- {
- short e, *q;
- double z, w;
- #ifdef UNK
- double frexp(), ldexp();
- #endif
-
- if( x <= 0.0 )
- {
- if( x < 0.0 )
- mtherr( "sqrt", DOMAIN );
- return( 0.0 );
- }
- w = x;
- /* separate exponent and significand */
- #ifdef UNK
- z = frexp( x, &e );
- #endif
- #ifdef DEC
- q = (short *)&x;
- e = ((*q >> 7) & 0377) - 0200;
- *q &= 0177;
- *q |= 040000;
- z = x;
- #endif
- #ifdef IBMPC
- q = (short *)&x;
- q += 3;
- e = ((*q >> 4) & 0x0fff) - 0x3fe;
- *q &= 0x000f;
- *q |= 0x3fe0;
- z = x;
- #endif
- #ifdef MIEEE
- q = (short *)&x;
- e = ((*q >> 4) & 0x0fff) - 0x3fe;
- *q &= 0x000f;
- *q |= 0x3fe0;
- z = x;
- #endif
-
- /* approximate square root of number between 0.5 and 1
- * relative error of approximation = 7.47e-3
- */
- x = 4.173075996388649989089E-1 + 5.9016206709064458299663E-1 * z;
-
- /* adjust for odd powers of 2 */
- if( (e & 1) != 0 )
- x *= SQRT2;
-
- /* re-insert exponent */
- #ifdef UNK
- x = ldexp( x, (e >> 1) );
- #endif
- #ifdef DEC
- *q += ((e >> 1) & 0377) << 7;
- *q &= 077777;
- #endif
- #ifdef IBMPC
- *q += ((e >>1) & 0x7ff) << 4;
- *q &= 077777;
- #endif
- #ifdef MIEEE
- *q += ((e >>1) & 0x7ff) << 4;
- *q &= 077777;
- #endif
-
- /* Newton iterations: */
- #ifdef UNK
- x += w/x;
- x = ldexp( x, -1 ); /* divide by 2 */
- x += w/x;
- x = ldexp( x, -1 );
- x += w/x;
- x = ldexp( x, -1 );
- #endif
- #ifdef DEC
- x += w/x;
- *q -= 0200;
- x += w/x;
- *q -= 0200;
- x += w/x;
- *q -= 0200;
- #endif
- #ifdef IBMPC
- x += w/x;
- *q -= 0x10;
- x += w/x;
- *q -= 0x10;
- x += w/x;
- *q -= 0x10;
- #endif
- #ifdef MIEEE
- x += w/x;
- *q -= 0x10;
- x += w/x;
- *q -= 0x10;
- x += w/x;
- *q -= 0x10;
- #endif
-
- return(x);
- }
-