diff options
author | Joseph Myers <joseph@codesourcery.com> | 2015-02-25 11:13:41 +0000 |
---|---|---|
committer | Joseph Myers <joseph@codesourcery.com> | 2015-02-25 11:13:41 +0000 |
commit | 137cef7d433407bd2ded8bcc5bea70e5858df47a (patch) | |
tree | deb0a6e04c5e7220d1e4eebcf59ab9d792a8eca6 /sysdeps/ieee754/ldbl-128ibm/s_asinhl.c | |
parent | cb43bb0d68f001fc3d6e054d712ab8794b5fd1de (diff) | |
download | glibc-137cef7d433407bd2ded8bcc5bea70e5858df47a.zip glibc-137cef7d433407bd2ded8bcc5bea70e5858df47a.tar.gz glibc-137cef7d433407bd2ded8bcc5bea70e5858df47a.tar.bz2 |
Fix ldbl-128ibm asinhl inaccuracy (bug 18020).
The ldbl-128ibm implementation of asinhl uses cut-offs of 0x1p28 and
0x1p-29 to determine when to use simpler formulas that avoid possible
overflow / underflow. Both those cut-offs are inappropriate for this
format, resulting in large errors. This patch changes the code to use
more appropriate cut-offs of 0x1p56 and 0x1p-56, adding tests around
the cut-offs for various floating-point formats.
Tested for powerpc. Also tested for x86_64 and x86 and updated ulps.
[BZ #18020]
* sysdeps/ieee754/ldbl-128ibm/s_asinhl.c (__asinhl): Use 2**56 and
2**-56 not 2**28 and 2**-29 as thresholds for simpler formulas.
* math/auto-libm-test-in: Add more tests of asinh.
* math/auto-libm-test-out: Regenerated.
* sysdeps/i386/fpu/libm-test-ulps: Update.
* sysdeps/x86_64/fpu/libm-test-ulps: Likewise.
Diffstat (limited to 'sysdeps/ieee754/ldbl-128ibm/s_asinhl.c')
-rw-r--r-- | sysdeps/ieee754/ldbl-128ibm/s_asinhl.c | 8 |
1 files changed, 4 insertions, 4 deletions
diff --git a/sysdeps/ieee754/ldbl-128ibm/s_asinhl.c b/sysdeps/ieee754/ldbl-128ibm/s_asinhl.c index 043b151f..b76e114 100644 --- a/sysdeps/ieee754/ldbl-128ibm/s_asinhl.c +++ b/sysdeps/ieee754/ldbl-128ibm/s_asinhl.c @@ -44,15 +44,15 @@ long double __asinhl(long double x) EXTRACT_WORDS64 (hx, xhi); ix = hx&0x7fffffffffffffffLL; if(ix>=0x7ff0000000000000LL) return x+x; /* x is inf or NaN */ - if(ix< 0x3e20000000000000LL) { /* |x|<2**-29 */ + if(ix< 0x3c70000000000000LL) { /* |x|<2**-56 */ if(huge+x>one) return x; /* return x inexact except 0 */ } - if(ix>0x41b0000000000000LL) { /* |x| > 2**28 */ + if(ix>0x4370000000000000LL) { /* |x| > 2**56 */ w = __ieee754_logl(fabsl(x))+ln2; - } else if (ix>0x4000000000000000LL) { /* 2**28 > |x| > 2.0 */ + } else if (ix>0x4000000000000000LL) { /* 2**56 >= |x| > 2.0 */ t = fabs(x); w = __ieee754_logl(2.0*t+one/(__ieee754_sqrtl(x*x+one)+t)); - } else { /* 2.0 > |x| > 2**-29 */ + } else { /* 2.0 >= |x| >= 2**-56 */ t = x*x; w =__log1pl(fabsl(x)+t/(one+__ieee754_sqrtl(one+t))); } |