diff options
| author | Rich Felker <dalias@aerifal.cx> | 2012-12-15 00:49:09 -0500 | 
|---|---|---|
| committer | Rich Felker <dalias@aerifal.cx> | 2012-12-15 00:49:09 -0500 | 
| commit | 969ddbc423238291d5c7982790bbe72720627ba4 (patch) | |
| tree | 54fb3d0a0ddb08549af2704be5dff2ad5dfb1c22 /src/math/atanhl.c | |
| parent | 9cb589939cdbfb2fe273bef3fe557a9a162ddd73 (diff) | |
| parent | a8f73bb1a685dd7d67669c6f6ceb255cfa967790 (diff) | |
| download | musl-969ddbc423238291d5c7982790bbe72720627ba4.tar.gz | |
Merge remote-tracking branch 'nsz/math'
Diffstat (limited to 'src/math/atanhl.c')
| -rw-r--r-- | src/math/atanhl.c | 69 | 
1 files changed, 18 insertions, 51 deletions
| diff --git a/src/math/atanhl.c b/src/math/atanhl.c index 931bae32..b4c5e58b 100644 --- a/src/math/atanhl.c +++ b/src/math/atanhl.c @@ -1,31 +1,3 @@ -/* origin: OpenBSD /usr/src/lib/libm/src/ld80/e_atanh.c */ -/* - * ==================================================== - * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. - * - * Developed at SunPro, a Sun Microsystems, Inc. business. - * Permission to use, copy, modify, and distribute this - * software is freely granted, provided that this notice - * is preserved. - * ==================================================== - */ -/* atanhl(x) - * Method : - *    1.Reduced x to positive by atanh(-x) = -atanh(x) - *    2.For x>=0.5 - *                   1              2x                          x - *      atanhl(x) = --- * log(1 + -------) = 0.5 * log1p(2 * --------) - *                   2             1 - x                      1 - x - * - *      For x<0.5 - *      atanhl(x) = 0.5*log1pl(2x+2x*x/(1-x)) - * - * Special cases: - *      atanhl(x) is NaN if |x| > 1 with signal; - *      atanhl(NaN) is that NaN with no signal; - *      atanhl(+-1) is +-INF with signal. - */ -  #include "libm.h"  #if LDBL_MANT_DIG == 53 && LDBL_MAX_EXP == 1024 @@ -34,31 +6,26 @@ long double atanhl(long double x)  	return atanh(x);  }  #elif LDBL_MANT_DIG == 64 && LDBL_MAX_EXP == 16384 -static const long double huge = 1e4900L; - +/* atanh(x) = log((1+x)/(1-x))/2 = log1p(2x/(1-x))/2 ~= x + x^3/3 + o(x^5) */  long double atanhl(long double x)  { -	long double t; -	int32_t ix; -	uint32_t se,i0,i1; +	union { +		long double f; +		struct{uint64_t m; uint16_t se; uint16_t pad;} i; +	} u = {.f = x}; +	unsigned e = u.i.se & 0x7fff; +	unsigned s = u.i.se >> 15; + +	/* |x| */ +	u.i.se = e; +	x = u.f; -	GET_LDOUBLE_WORDS(se, i0, i1, x); -	ix = se & 0x7fff; -	if ((ix+((((i0&0x7fffffff)|i1)|(-((i0&0x7fffffff)|i1)))>>31)) > 0x3fff) -		/* |x| > 1 */ -		return (x-x)/(x-x); -	if (ix == 0x3fff) -		return x/0.0; -	if (ix < 0x3fe3 && huge+x > 0.0)  /* x < 2**-28 */ -		return x; -	SET_LDOUBLE_EXP(x, ix); -	if (ix < 0x3ffe) {  /* x < 0.5 */ -		t = x + x; -		t = 0.5*log1pl(t + t*x/(1.0 - x)); -	} else -		t = 0.5*log1pl((x + x)/(1.0 - x)); -	if (se <= 0x7fff) -		return t; -	return -t; +	if (e < 0x3fff - 1) { +		/* |x| < 0.5, up to 1.7ulp error */ +		x = 0.5*log1pl(2*x + 2*x*x/(1-x)); +	} else { +		x = 0.5*log1pl(2*x/(1-x)); +	} +	return s ? -x : x;  }  #endif | 
