about summary refs log tree commit diff
diff options
context:
space:
mode:
authorJoseph Myers <joseph@codesourcery.com>2015-12-09 21:20:18 +0000
committerJoseph Myers <joseph@codesourcery.com>2015-12-09 21:20:18 +0000
commitca2fcac629b9b7781ccd52685b28741d89ff128f (patch)
tree8c2b6491a4672a338e965e8ca1fa0f8724d189a6
parente5a5315e2d290fe34e0fb80996c713b8b802dcc9 (diff)
downloadglibc-ca2fcac629b9b7781ccd52685b28741d89ff128f.tar.gz
glibc-ca2fcac629b9b7781ccd52685b28741d89ff128f.tar.xz
glibc-ca2fcac629b9b7781ccd52685b28741d89ff128f.zip
Fix ldbl-128ibm tanhl inaccuracy for small arguments (bug 19349).
The ldbl-128ibm implementation of tanhl is inaccurate for small
arguments, because it returns x*(1+x) (maybe in an attempt to raise
"inexact") when x itself would be the accurate return value but
multiplying by 1+x introduces large errors.  This patch fixes it to
return x in that case (when the mathematical result is x plus a
negligible remainder on the order of x^3) to avoid those errors.

Tested for powerpc.

	[BZ #19349]
	* sysdeps/ieee754/ldbl-128ibm/s_tanhl.c (__tanhl): Return argument
	when small.
-rw-r--r--ChangeLog4
-rw-r--r--sysdeps/ieee754/ldbl-128ibm/s_tanhl.c2
2 files changed, 5 insertions, 1 deletions
diff --git a/ChangeLog b/ChangeLog
index b2eddff236..b76c54b9a5 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,9 @@
 2015-12-09  Joseph Myers  <joseph@codesourcery.com>
 
+	[BZ #19349]
+	* sysdeps/ieee754/ldbl-128ibm/s_tanhl.c (__tanhl): Return argument
+	when small.
+
 	* sysdeps/unix/sysv/linux/i386/kernel-features.h
 	[__LINUX_KERNEL_VERSION >= 0x040300] (__ASSUME_SOCKET_SYSCALL):
 	New macro.
diff --git a/sysdeps/ieee754/ldbl-128ibm/s_tanhl.c b/sysdeps/ieee754/ldbl-128ibm/s_tanhl.c
index 292020cabf..e6457a1c1c 100644
--- a/sysdeps/ieee754/ldbl-128ibm/s_tanhl.c
+++ b/sysdeps/ieee754/ldbl-128ibm/s_tanhl.c
@@ -69,7 +69,7 @@ long double __tanhl(long double x)
 	    if (ix<0x3c60000000000000LL) 	/* |x|<2**-57 */
 	      {
 		math_check_force_underflow (x);
-		return x*(one+x);    	/* tanh(small) = small */
+		return x;		/* tanh(small) = small */
 	      }
 	    if (ix>=0x3ff0000000000000LL) {	/* |x|>=1  */
 		t = __expm1l(two*fabsl(x));