diff options
Diffstat (limited to 'src/math')
| -rw-r--r-- | src/math/expl.c | 43 | 
1 files changed, 19 insertions, 24 deletions
| diff --git a/src/math/expl.c b/src/math/expl.c index b289ffec..50a04297 100644 --- a/src/math/expl.c +++ b/src/math/expl.c @@ -35,7 +35,7 @@   *     x    k  f   *    e  = 2  e.   * - * A Pade' form of degree 2/3 is used to approximate exp(f) - 1 + * A Pade' form of degree 5/6 is used to approximate exp(f) - 1   * in the basic range [-0.5 ln 2, 0.5 ln 2].   *   * @@ -86,42 +86,37 @@ static const long double Q[4] = {   2.0000000000000000000897E0L,  };  static const long double -C1 = 6.9314575195312500000000E-1L, -C2 = 1.4286068203094172321215E-6L, -MAXLOGL = 1.1356523406294143949492E4L, -MINLOGL = -1.13994985314888605586758E4L, -LOG2EL = 1.4426950408889634073599E0L; +LN2HI = 6.9314575195312500000000E-1L, +LN2LO = 1.4286068203094172321215E-6L, +LOG2E = 1.4426950408889634073599E0L;  long double expl(long double x)  {  	long double px, xx; -	int n; +	int k;  	if (isnan(x))  		return x; -	if (x > MAXLOGL) -		return INFINITY; -	if (x < MINLOGL) -		return 0.0; +	if (x > 11356.5234062941439488L) /* x > ln(2^16384 - 0.5) */ +		return x * 0x1p16383L; +	if (x < -11399.4985314888605581L) /* x < ln(2^-16446) */ +		return 0x1p-10000L * 0x1p-10000L; -	/* Express e**x = e**g 2**n -	 *   = e**g e**(n loge(2)) -	 *   = e**(g + n loge(2)) +	/* Express e**x = e**f 2**k +	 *   = e**(f + k ln(2))  	 */ -	px = floorl(LOG2EL * x + 0.5); /* floor() truncates toward -infinity. */ -	n = px; -	x -= px * C1; -	x -= px * C2; +	px = floorl(LOG2E * x + 0.5); +	k = px; +	x -= px * LN2HI; +	x -= px * LN2LO; -	/* rational approximation for exponential -	 * of the fractional part: -	 * e**x =  1 + 2x P(x**2)/(Q(x**2) - P(x**2)) +	/* rational approximation of the fractional part: +	 * e**x =  1 + 2x P(x**2)/(Q(x**2) - x P(x**2))  	 */  	xx = x * x;  	px = x * __polevll(xx, P, 2); -	x =  px/(__polevll(xx, Q, 3) - px); +	x = px/(__polevll(xx, Q, 3) - px);  	x = 1.0 + 2.0 * x; -	x = scalbnl(x, n); -	return x; +	return scalbnl(x, k);  }  #endif | 
