about summary refs log tree commit diff
path: root/sysdeps
diff options
context:
space:
mode:
authorJoseph Myers <joseph@codesourcery.com>2015-05-15 22:07:57 +0000
committerJoseph Myers <joseph@codesourcery.com>2015-05-15 22:07:57 +0000
commit8020a808870dc6199e584562b3b64f52054359e8 (patch)
treece9400206b43fc1db091871c50d2e5e10c78c1fb /sysdeps
parent5a608ccc2d676aa124f6b55a7b20d071e408ca31 (diff)
downloadglibc-8020a808870dc6199e584562b3b64f52054359e8.tar.gz
glibc-8020a808870dc6199e584562b3b64f52054359e8.tar.xz
glibc-8020a808870dc6199e584562b3b64f52054359e8.zip
Fix atanhl missing underflows (bug 16352).
Similar to various other bugs in this area, some atanh implementations
do not raise the underflow exception for subnormal arguments, when the
result is tiny and inexact.  This patch forces the exception in a
similar way to previous fixes.  (No change in this regard is needed
for the i386 implementation; special handling to force underflows in
these cases will only be needed there when the spurious underflows,
bug 18049, get fixed.)

Tested for x86_64, x86, powerpc and mips64.

	[BZ #16352]
	* sysdeps/i386/fpu/e_atanh.S (dbl_min): New object.
	(__ieee754_atanh): Force underflow exception for results with
	small absolute value.
	* sysdeps/i386/fpu/e_atanhf.S (flt_min): New object.
	(__ieee754_atanhf): Force underflow exception for results with
	small absolute value.
	* sysdeps/ieee754/dbl-64/e_atanh.c: Include <float.h>.
	(__ieee754_atanh): Force underflow exception for results with
	small absolute value.
	* sysdeps/ieee754/flt-32/e_atanhf.c: Include <float.h>.
	(__ieee754_atanhf): Force underflow exception for results with
	small absolute value.
	* sysdeps/ieee754/ldbl-128/e_atanhl.c: Include <float.h>.
	(__ieee754_atanhl): Force underflow exception for results with
	small absolute value.
	* sysdeps/ieee754/ldbl-128ibm/e_atanhl.c: Include <float.h>.
	(__ieee754_atanhl): Force underflow exception for results with
	small absolute value.
	* sysdeps/ieee754/ldbl-96/e_atanhl.c: Include <float.h>.
	(__ieee754_atanhl): Force underflow exception for results with
	small absolute value.
	* math/auto-libm-test-in: Do not allow missing underflow
	exceptions from atanh.
	* math/auto-libm-test-out: Regenerated.
Diffstat (limited to 'sysdeps')
-rw-r--r--sysdeps/i386/fpu/e_atanh.S20
-rw-r--r--sysdeps/i386/fpu/e_atanhf.S20
-rw-r--r--sysdeps/ieee754/dbl-64/e_atanh.c6
-rw-r--r--sysdeps/ieee754/flt-32/e_atanhf.c6
-rw-r--r--sysdeps/ieee754/ldbl-128/e_atanhl.c11
-rw-r--r--sysdeps/ieee754/ldbl-128ibm/e_atanhl.c11
-rw-r--r--sysdeps/ieee754/ldbl-96/e_atanhl.c6
7 files changed, 76 insertions, 4 deletions
diff --git a/sysdeps/i386/fpu/e_atanh.S b/sysdeps/i386/fpu/e_atanh.S
index 16e149b905..90d19bc9d6 100644
--- a/sysdeps/i386/fpu/e_atanh.S
+++ b/sysdeps/i386/fpu/e_atanh.S
@@ -35,6 +35,13 @@ limit:	.double 0.29
 ln2_2:	.tfloat 0.3465735902799726547086160
 	ASM_SIZE_DIRECTIVE(ln2_2)
 
+	.section .rodata.cst8,"aM",@progbits,8
+
+	.p2align 3
+	.type dbl_min,@object
+dbl_min:	.byte 0, 0, 0, 0, 0, 0, 0x10, 0
+	ASM_SIZE_DIRECTIVE(dbl_min)
+
 #ifdef PIC
 #define MO(op) op##@GOTOFF(%edx)
 #else
@@ -81,7 +88,18 @@ ENTRY(__ieee754_atanh)
 	sahf
 	jae	4f
 	fyl2xp1			// 0.5*ln2*ld(1+2*|x|+(2*|x|^2)/(1-|x|))
-	jecxz	3f
+	fcoml	MO(dbl_min)
+	fnstsw
+	sahf
+	jae	8f
+	subl	$8, %esp
+	cfi_adjust_cfa_offset (8)
+	fld	%st(0)
+	fmul	%st(0)
+	fstpl	(%esp)
+	addl	$8, %esp
+	cfi_adjust_cfa_offset (-8)
+8:	jecxz	3f
 	fchs			// 0.5*ln2*ld(1+2*x+(2*x^2)/(1-x))
 3:	ret
 
diff --git a/sysdeps/i386/fpu/e_atanhf.S b/sysdeps/i386/fpu/e_atanhf.S
index 0021d9c47d..1c8969e5ec 100644
--- a/sysdeps/i386/fpu/e_atanhf.S
+++ b/sysdeps/i386/fpu/e_atanhf.S
@@ -36,6 +36,13 @@ limit:	.double 0.29
 ln2_2:	.tfloat 0.3465735902799726547086160
 	ASM_SIZE_DIRECTIVE(ln2_2)
 
+	.section .rodata.cst4,"aM",@progbits,4
+
+	.p2align 2
+	.type flt_min,@object
+flt_min:	.byte 0, 0, 0x80, 0
+	ASM_SIZE_DIRECTIVE(flt_min)
+
 #ifdef PIC
 #define MO(op) op##@GOTOFF(%edx)
 #else
@@ -77,7 +84,18 @@ ENTRY(__ieee754_atanhf)
 	sahf
 	jae	4f
 	fyl2xp1			// 0.5*ln2*ld(1+2*|x|+(2*|x|^2)/(1-|x|))
-	jecxz	3f
+	fcoms	MO(flt_min)
+	fnstsw
+	sahf
+	jae	6f
+	subl	$4, %esp
+	cfi_adjust_cfa_offset (4)
+	fld	%st(0)
+	fmul	%st(0)
+	fstps	(%esp)
+	addl	$4, %esp
+	cfi_adjust_cfa_offset (-4)
+6:	jecxz	3f
 	fchs			// 0.5*ln2*ld(1+2*x+(2*x^2)/(1-x))
 3:	ret
 
diff --git a/sysdeps/ieee754/dbl-64/e_atanh.c b/sysdeps/ieee754/dbl-64/e_atanh.c
index b95399ddab..6b00b800f2 100644
--- a/sysdeps/ieee754/dbl-64/e_atanh.c
+++ b/sysdeps/ieee754/dbl-64/e_atanh.c
@@ -35,6 +35,7 @@
 
  */
 
+#include <float.h>
 #include <inttypes.h>
 #include <math.h>
 #include <math_private.h>
@@ -51,6 +52,11 @@ __ieee754_atanh (double x)
       if (__glibc_unlikely (xa < 0x1.0p-28))
 	{
 	  math_force_eval (huge + x);
+	  if (fabs (x) < DBL_MIN)
+	    {
+	      double force_underflow = x * x;
+	      math_force_eval (force_underflow);
+	    }
 	  return x;
 	}
 
diff --git a/sysdeps/ieee754/flt-32/e_atanhf.c b/sysdeps/ieee754/flt-32/e_atanhf.c
index a6d8bd139f..bc74960e16 100644
--- a/sysdeps/ieee754/flt-32/e_atanhf.c
+++ b/sysdeps/ieee754/flt-32/e_atanhf.c
@@ -35,6 +35,7 @@
 
  */
 
+#include <float.h>
 #include <inttypes.h>
 #include <math.h>
 #include <math_private.h>
@@ -51,6 +52,11 @@ __ieee754_atanhf (float x)
       if (__glibc_unlikely (xa < 0x1.0p-28f))
 	{
 	  math_force_eval (huge + x);
+	  if (fabsf (x) < FLT_MIN)
+	    {
+	      float force_underflow = x * x;
+	      math_force_eval (force_underflow);
+	    }
 	  return x;
 	}
 
diff --git a/sysdeps/ieee754/ldbl-128/e_atanhl.c b/sysdeps/ieee754/ldbl-128/e_atanhl.c
index c5cceb5224..a5a7ee0712 100644
--- a/sysdeps/ieee754/ldbl-128/e_atanhl.c
+++ b/sysdeps/ieee754/ldbl-128/e_atanhl.c
@@ -32,6 +32,7 @@
  *
  */
 
+#include <float.h>
 #include <math.h>
 #include <math_private.h>
 
@@ -57,7 +58,15 @@ __ieee754_atanhl(long double x)
 	    else
 	      return (x-x)/(x-x);
 	  }
-	if(ix<0x3fc60000 && (huge+x)>zero) return x;	/* x < 2^-57 */
+	if(ix<0x3fc60000 && (huge+x)>zero)	/* x < 2^-57 */
+	  {
+	    if (fabsl (x) < LDBL_MIN)
+	      {
+		long double force_underflow = x * x;
+		math_force_eval (force_underflow);
+	      }
+	    return x;
+	  }
 
 	if(ix<0x3ffe0000) {		/* x < 0.5 */
 	    t = u.value+u.value;
diff --git a/sysdeps/ieee754/ldbl-128ibm/e_atanhl.c b/sysdeps/ieee754/ldbl-128ibm/e_atanhl.c
index 5a989992f5..bcd1fce4ed 100644
--- a/sysdeps/ieee754/ldbl-128ibm/e_atanhl.c
+++ b/sysdeps/ieee754/ldbl-128ibm/e_atanhl.c
@@ -28,6 +28,7 @@
  *
  */
 
+#include <float.h>
 #include <math.h>
 #include <math_private.h>
 
@@ -54,7 +55,15 @@ __ieee754_atanhl(long double x)
 	    if (t == one)
 		return x/zero;
 	}
-	if(ix<0x3c70000000000000LL&&(huge+x)>zero) return x;	/* x<2**-56 */
+	if(ix<0x3c70000000000000LL&&(huge+x)>zero)	/* x<2**-56 */
+	  {
+	    if (fabsl (x) < LDBL_MIN)
+	      {
+		long double force_underflow = x * x;
+		math_force_eval (force_underflow);
+	      }
+	    return x;
+	  }
 	x = fabsl (x);
 	if(ix<0x3fe0000000000000LL) {		/* x < 0.5 */
 	    t = x+x;
diff --git a/sysdeps/ieee754/ldbl-96/e_atanhl.c b/sysdeps/ieee754/ldbl-96/e_atanhl.c
index 305d50e309..9a957c9065 100644
--- a/sysdeps/ieee754/ldbl-96/e_atanhl.c
+++ b/sysdeps/ieee754/ldbl-96/e_atanhl.c
@@ -32,6 +32,7 @@
  *
  */
 
+#include <float.h>
 #include <math.h>
 #include <math_private.h>
 
@@ -54,6 +55,11 @@ __ieee754_atanhl(long double x)
 	    return x/zero;
 	if(ix<0x3fdf) {
 	    math_force_eval(huge+x);
+	    if (fabsl (x) < LDBL_MIN)
+	      {
+		long double force_underflow = x * x;
+		math_force_eval (force_underflow);
+	      }
 	    return x;	/* x<2**-32 */
 	}
 	SET_LDOUBLE_EXP(x,ix);