cbrt.c 2.5 KB
Newer Older
G
geniusgogo 已提交
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142
/*							cbrt.c
 *
 *	Cube root
 *
 *
 *
 * SYNOPSIS:
 *
 * double x, y, cbrt();
 *
 * y = cbrt( x );
 *
 *
 *
 * DESCRIPTION:
 *
 * Returns the cube root of the argument, which may be negative.
 *
 * Range reduction involves determining the power of 2 of
 * the argument.  A polynomial of degree 2 applied to the
 * mantissa, and multiplication by the cube root of 1, 2, or 4
 * approximates the root to within about 0.1%.  Then Newton's
 * iteration is used three times to converge to an accurate
 * result.
 *
 *
 *
 * ACCURACY:
 *
 *                      Relative error:
 * arithmetic   domain     # trials      peak         rms
 *    DEC        -10,10     200000      1.8e-17     6.2e-18
 *    IEEE       0,1e308     30000      1.5e-16     5.0e-17
 *
 */
/*							cbrt.c  */

/*
Cephes Math Library Release 2.8:  June, 2000
Copyright 1984, 1991, 2000 by Stephen L. Moshier
*/


#include "mconf.h"

const static double CBRT2  = 1.2599210498948731647672;
const static double CBRT4  = 1.5874010519681994747517;
const static double CBRT2I = 0.79370052598409973737585;
const static double CBRT4I = 0.62996052494743658238361;

#ifdef ANSIPROT
extern double frexp ( double, int * );
extern double ldexp ( double, int );
extern int isnan ( double );
extern int isfinite ( double );
#else
double frexp(), ldexp();
int isnan(), isfinite();
#endif

double cbrt(x)
double x;
{
int e, rem, sign;
double z;

#ifdef NANS
if( isnan(x) )
  return x;
#endif
#ifdef INFINITIES
if( !isfinite(x) )
  return x;
#endif
if( x == 0 )
	return( x );
if( x > 0 )
	sign = 1;
else
	{
	sign = -1;
	x = -x;
	}

z = x;
/* extract power of 2, leaving
 * mantissa between 0.5 and 1
 */
x = frexp( x, &e );

/* Approximate cube root of number between .5 and 1,
 * peak relative error = 9.2e-6
 */
x = (((-1.3466110473359520655053e-1  * x
      + 5.4664601366395524503440e-1) * x
      - 9.5438224771509446525043e-1) * x
      + 1.1399983354717293273738e0 ) * x
      + 4.0238979564544752126924e-1;

/* exponent divided by 3 */
if( e >= 0 )
	{
	rem = e;
	e /= 3;
	rem -= 3*e;
	if( rem == 1 )
		x *= CBRT2;
	else if( rem == 2 )
		x *= CBRT4;
	}


/* argument less than 1 */

else
	{
	e = -e;
	rem = e;
	e /= 3;
	rem -= 3*e;
	if( rem == 1 )
		x *= CBRT2I;
	else if( rem == 2 )
		x *= CBRT4I;
	e = -e;
	}

/* multiply by power of 2 */
x = ldexp( x, e );

/* Newton iteration */
x -= ( x - (z/(x*x)) )*0.33333333333333333333;
#ifdef DEC
x -= ( x - (z/(x*x)) )/3.0;
#else
x -= ( x - (z/(x*x)) )*0.33333333333333333333;
#endif

if( sign < 0 )
	x = -x;
return(x);
}