Fix sincos errno setting (bug 15467) [committed].

Message ID alpine.DEB.2.10.1502112317530.19244@digraph.polyomino.org.uk
State Committed
Headers

Commit Message

Joseph Myers Feb. 11, 2015, 11:19 p.m. UTC
  This patch makes sincos set errno to EDOM when passed an infinity,
similarly to sin and cos.

Tested for x86_64, x86, powerpc and mips64.  I don't know if the
architecture-specific implementations for ia64 and m68k might need
corresponding fixes.  Committed.

2015-02-11  Joseph Myers  <joseph@codesourcery.com>

	[BZ #15467]
	* sysdeps/ieee754/dbl-64/s_sincos.c: Include <errno.h>.
	(__sincos): Set errno to EDOM for infinite argument.
	* sysdeps/ieee754/flt-32/s_sincosf.c: Include <errno.h>.
	(SINCOSF_FUNC): Set errno to EDOM for infinite argument.
	* sysdeps/ieee754/ldbl-128/s_sincosl.c: Include <errno.h>.
	(__sincosl): Set errno to EDOM for infinite argument.
	* sysdeps/ieee754/ldbl-128ibm/s_sincosl.c: Include <errno.h>.
	(__sincosl): Set errno to EDOM for infinite argument.
	* sysdeps/ieee754/ldbl-96/s_sincosl.c: Include <errno.h>.
	(__sincosl): Set errno to EDOM for infinite argument.
	* math/libm-test.inc (sincos_test_data): Test errno setting.
  

Patch

diff --git a/math/libm-test.inc b/math/libm-test.inc
index 6d7ff12..aa7ba2b 100644
--- a/math/libm-test.inc
+++ b/math/libm-test.inc
@@ -9335,9 +9335,9 @@  sin_test (void)
 
 static const struct test_fFF_11_data sincos_test_data[] =
   {
-    TEST_fFF_11 (sincos, plus_infty, qnan_value, qnan_value, INVALID_EXCEPTION),
-    TEST_fFF_11 (sincos, minus_infty, qnan_value, qnan_value, INVALID_EXCEPTION),
-    TEST_fFF_11 (sincos, qnan_value, qnan_value, qnan_value, NO_INEXACT_EXCEPTION),
+    TEST_fFF_11 (sincos, plus_infty, qnan_value, qnan_value, INVALID_EXCEPTION|ERRNO_EDOM),
+    TEST_fFF_11 (sincos, minus_infty, qnan_value, qnan_value, INVALID_EXCEPTION|ERRNO_EDOM),
+    TEST_fFF_11 (sincos, qnan_value, qnan_value, qnan_value, NO_INEXACT_EXCEPTION|ERRNO_UNCHANGED),
 
     AUTO_TESTS_fFF_11 (sincos),
   };
diff --git a/sysdeps/ieee754/dbl-64/s_sincos.c b/sysdeps/ieee754/dbl-64/s_sincos.c
index 7d3b101..c8a9999 100644
--- a/sysdeps/ieee754/dbl-64/s_sincos.c
+++ b/sysdeps/ieee754/dbl-64/s_sincos.c
@@ -17,6 +17,7 @@ 
    License along with the GNU C Library; if not, see
    <http://www.gnu.org/licenses/>.  */
 
+#include <errno.h>
 #include <math.h>
 
 #include <math_private.h>
@@ -36,6 +37,8 @@  __sincos (double x, double *sinx, double *cosx)
     {
       /* sin(Inf or NaN) is NaN */
       *sinx = *cosx = x - x;
+      if (__isinf_ns (x))
+	__set_errno (EDOM);
     }
   else
     {
diff --git a/sysdeps/ieee754/flt-32/s_sincosf.c b/sysdeps/ieee754/flt-32/s_sincosf.c
index 5cf5db0..596e076 100644
--- a/sysdeps/ieee754/flt-32/s_sincosf.c
+++ b/sysdeps/ieee754/flt-32/s_sincosf.c
@@ -17,6 +17,7 @@ 
    License along with the GNU C Library; if not, see
    <http://www.gnu.org/licenses/>.  */
 
+#include <errno.h>
 #include <math.h>
 
 #include <math_private.h>
@@ -46,6 +47,8 @@  SINCOSF_FUNC (float x, float *sinx, float *cosx)
     {
       /* sin(Inf or NaN) is NaN */
       *sinx = *cosx = x - x;
+      if (ix == 0x7f800000)
+	__set_errno (EDOM);
     }
   else
     {
diff --git a/sysdeps/ieee754/ldbl-128/s_sincosl.c b/sysdeps/ieee754/ldbl-128/s_sincosl.c
index 175a617..6c4cbd7 100644
--- a/sysdeps/ieee754/ldbl-128/s_sincosl.c
+++ b/sysdeps/ieee754/ldbl-128/s_sincosl.c
@@ -18,6 +18,7 @@ 
    License along with the GNU C Library; if not, see
    <http://www.gnu.org/licenses/>.  */
 
+#include <errno.h>
 #include <math.h>
 
 #include <math_private.h>
@@ -38,6 +39,8 @@  __sincosl (long double x, long double *sinx, long double *cosx)
     {
       /* sin(Inf or NaN) is NaN */
       *sinx = *cosx = x - x;
+      if (__isinf_nsl (x))
+	__set_errno (EDOM);
     }
   else
     {
diff --git a/sysdeps/ieee754/ldbl-128ibm/s_sincosl.c b/sysdeps/ieee754/ldbl-128ibm/s_sincosl.c
index f52e733..8a49c54 100644
--- a/sysdeps/ieee754/ldbl-128ibm/s_sincosl.c
+++ b/sysdeps/ieee754/ldbl-128ibm/s_sincosl.c
@@ -18,6 +18,7 @@ 
    License along with the GNU C Library; if not, see
    <http://www.gnu.org/licenses/>.  */
 
+#include <errno.h>
 #include <math.h>
 
 #include <math_private.h>
@@ -41,6 +42,8 @@  __sincosl (long double x, long double *sinx, long double *cosx)
     {
       /* sin(Inf or NaN) is NaN */
       *sinx = *cosx = x - x;
+      if (__isinf_nsl (x))
+	__set_errno (EDOM);
     }
   else
     {
diff --git a/sysdeps/ieee754/ldbl-96/s_sincosl.c b/sysdeps/ieee754/ldbl-96/s_sincosl.c
index c7a161a..37067bd 100644
--- a/sysdeps/ieee754/ldbl-96/s_sincosl.c
+++ b/sysdeps/ieee754/ldbl-96/s_sincosl.c
@@ -17,6 +17,7 @@ 
    License along with the GNU C Library; if not, see
    <http://www.gnu.org/licenses/>.  */
 
+#include <errno.h>
 #include <math.h>
 
 #include <math_private.h>
@@ -41,6 +42,8 @@  __sincosl (long double x, long double *sinx, long double *cosx)
     {
       /* sin(Inf or NaN) is NaN */
       *sinx = *cosx = x - x;
+      if (__isinf_nsl (x))
+	__set_errno (EDOM);
     }
   else
     {