about summary refs log tree commit diff
path: root/sysdeps
diff options
context:
space:
mode:
authorJoseph Myers <joseph@codesourcery.com>2013-12-03 16:25:18 +0000
committerJoseph Myers <joseph@codesourcery.com>2013-12-03 16:25:18 +0000
commit34e16df5a1a46e128edb9eb44a09ac5762957136 (patch)
treed8751230a2270d89531af1f7c12868dae50f534f /sysdeps
parentd8e2dbe3e380729a1552d546da582b02202dde0a (diff)
downloadglibc-34e16df5a1a46e128edb9eb44a09ac5762957136.tar.gz
glibc-34e16df5a1a46e128edb9eb44a09ac5762957136.tar.xz
glibc-34e16df5a1a46e128edb9eb44a09ac5762957136.zip
Fix erfc errno setting on underflow (bug 6786).
Diffstat (limited to 'sysdeps')
-rw-r--r--sysdeps/i386/fpu/libm-test-ulps3
-rw-r--r--sysdeps/ieee754/dbl-64/s_erf.c17
-rw-r--r--sysdeps/ieee754/flt-32/s_erff.c19
-rw-r--r--sysdeps/ieee754/ldbl-128/s_erfl.c13
-rw-r--r--sysdeps/ieee754/ldbl-128ibm/s_erfl.c13
-rw-r--r--sysdeps/ieee754/ldbl-96/s_erfl.c13
-rw-r--r--sysdeps/x86_64/fpu/libm-test-ulps3
7 files changed, 71 insertions, 10 deletions
diff --git a/sysdeps/i386/fpu/libm-test-ulps b/sysdeps/i386/fpu/libm-test-ulps
index 0234a61b68..a492da30d6 100644
--- a/sysdeps/i386/fpu/libm-test-ulps
+++ b/sysdeps/i386/fpu/libm-test-ulps
@@ -5946,6 +5946,9 @@ double: 1
 idouble: 1
 ildouble: 1
 ldouble: 1
+Test "erfc (0x6.4p+4)":
+ildouble: 1
+ldouble: 1
 Test "erfc (0x7.fe8008p+0)":
 ildouble: 1
 ldouble: 1
diff --git a/sysdeps/ieee754/dbl-64/s_erf.c b/sysdeps/ieee754/dbl-64/s_erf.c
index aab4ed593e..3f37397224 100644
--- a/sysdeps/ieee754/dbl-64/s_erf.c
+++ b/sysdeps/ieee754/dbl-64/s_erf.c
@@ -112,6 +112,8 @@ static char rcsid[] = "$NetBSD: s_erf.c,v 1.8 1995/05/10 20:47:05 jtc Exp $";
  */
 
 
+#include <errno.h>
+#include <float.h>
 #include <math.h>
 #include <math_private.h>
 
@@ -391,14 +393,25 @@ __erfc (double x)
       r = __ieee754_exp (-z * z - 0.5625) *
 	  __ieee754_exp ((z - x) * (z + x) + R / S);
       if (hx > 0)
-	return r / x;
+	{
+#if FLT_EVAL_METHOD != 0
+	  volatile
+#endif
+	  double ret = r / x;
+	  if (ret == 0)
+	    __set_errno (ERANGE);
+	  return ret;
+	}
       else
 	return two - r / x;
     }
   else
     {
       if (hx > 0)
-	return tiny * tiny;
+	{
+	  __set_errno (ERANGE);
+	  return tiny * tiny;
+	}
       else
 	return two - tiny;
     }
diff --git a/sysdeps/ieee754/flt-32/s_erff.c b/sysdeps/ieee754/flt-32/s_erff.c
index 7d17f426e9..7c09589648 100644
--- a/sysdeps/ieee754/flt-32/s_erff.c
+++ b/sysdeps/ieee754/flt-32/s_erff.c
@@ -17,6 +17,8 @@
 static char rcsid[] = "$NetBSD: s_erff.c,v 1.4 1995/05/10 20:47:07 jtc Exp $";
 #endif
 
+#include <errno.h>
+#include <float.h>
 #include <math.h>
 #include <math_private.h>
 
@@ -203,9 +205,22 @@ float __erfcf(float x)
 	    SET_FLOAT_WORD(z,ix&0xffffe000);
 	    r  =  __ieee754_expf(-z*z-(float)0.5625)*
 			__ieee754_expf((z-x)*(z+x)+R/S);
-	    if(hx>0) return r/x; else return two-r/x;
+	    if(hx>0) {
+#if FLT_EVAL_METHOD != 0
+		volatile
+#endif
+		float ret = r/x;
+		if (ret == 0)
+		    __set_errno (ERANGE);
+		return ret;
+	    } else
+		return two-r/x;
 	} else {
-	    if(hx>0) return tiny*tiny; else return two-tiny;
+	    if(hx>0) {
+		__set_errno (ERANGE);
+		return tiny*tiny;
+	    } else
+		return two-tiny;
 	}
 }
 weak_alias (__erfcf, erfcf)
diff --git a/sysdeps/ieee754/ldbl-128/s_erfl.c b/sysdeps/ieee754/ldbl-128/s_erfl.c
index d9d4195ad2..ef65ed8922 100644
--- a/sysdeps/ieee754/ldbl-128/s_erfl.c
+++ b/sysdeps/ieee754/ldbl-128/s_erfl.c
@@ -96,6 +96,7 @@
  *		erfc/erf(NaN) is NaN
  */
 
+#include <errno.h>
 #include <math.h>
 #include <math_private.h>
 
@@ -918,14 +919,22 @@ __erfcl (long double x)
       r = __ieee754_expl (-z * z - 0.5625) *
 	__ieee754_expl ((z - x) * (z + x) + p);
       if ((sign & 0x80000000) == 0)
-	return r / x;
+	{
+	  long double ret = r / x;
+	  if (ret == 0)
+	    __set_errno (ERANGE);
+	  return ret;
+	}
       else
 	return two - r / x;
     }
   else
     {
       if ((sign & 0x80000000) == 0)
-	return tiny * tiny;
+	{
+	  __set_errno (ERANGE);
+	  return tiny * tiny;
+	}
       else
 	return two - tiny;
     }
diff --git a/sysdeps/ieee754/ldbl-128ibm/s_erfl.c b/sysdeps/ieee754/ldbl-128ibm/s_erfl.c
index c861c65ccf..95dc415845 100644
--- a/sysdeps/ieee754/ldbl-128ibm/s_erfl.c
+++ b/sysdeps/ieee754/ldbl-128ibm/s_erfl.c
@@ -101,6 +101,7 @@
  *		erfc/erf(NaN) is NaN
  */
 
+#include <errno.h>
 #include <math.h>
 #include <math_private.h>
 #include <math_ldbl_opt.h>
@@ -940,14 +941,22 @@ __erfcl (long double x)
       r = __ieee754_expl (-z * z - 0.5625) *
 	__ieee754_expl ((z - x) * (z + x) + p);
       if ((hx & 0x80000000) == 0)
-	return r / x;
+	{
+	  long double ret = r / x;
+	  if (ret == 0)
+	    __set_errno (ERANGE);
+	  return ret;
+	}
       else
 	return two - r / x;
     }
   else
     {
       if ((hx & 0x80000000) == 0)
-	return tiny * tiny;
+	{
+	  __set_errno (ERANGE);
+	  return tiny * tiny;
+	}
       else
 	return two - tiny;
     }
diff --git a/sysdeps/ieee754/ldbl-96/s_erfl.c b/sysdeps/ieee754/ldbl-96/s_erfl.c
index 17d2278524..47e4b9e909 100644
--- a/sysdeps/ieee754/ldbl-96/s_erfl.c
+++ b/sysdeps/ieee754/ldbl-96/s_erfl.c
@@ -104,6 +104,7 @@
  */
 
 
+#include <errno.h>
 #include <math.h>
 #include <math_private.h>
 
@@ -422,14 +423,22 @@ __erfcl (long double x)
       r = __ieee754_expl (-z * z - 0.5625) *
 	__ieee754_expl ((z - x) * (z + x) + R / S);
       if ((se & 0x8000) == 0)
-	return r / x;
+	{
+	  long double ret = r / x;
+	  if (ret == 0)
+	    __set_errno (ERANGE);
+	  return ret;
+	}
       else
 	return two - r / x;
     }
   else
     {
       if ((se & 0x8000) == 0)
-	return tiny * tiny;
+	{
+	  __set_errno (ERANGE);
+	  return tiny * tiny;
+	}
       else
 	return two - tiny;
     }
diff --git a/sysdeps/x86_64/fpu/libm-test-ulps b/sysdeps/x86_64/fpu/libm-test-ulps
index 209fd49b69..5c923e69b3 100644
--- a/sysdeps/x86_64/fpu/libm-test-ulps
+++ b/sysdeps/x86_64/fpu/libm-test-ulps
@@ -6776,6 +6776,9 @@ double: 1
 idouble: 1
 ildouble: 1
 ldouble: 1
+Test "erfc (0x6.4p+4)":
+ildouble: 1
+ldouble: 1
 Test "erfc (0x7.fe8008p+0)":
 float: 1
 ifloat: 1