This is the mail archive of the libc-alpha@sourceware.org mailing list for the glibc project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Test cosh, sinh in non-default rounding modes (bug 3976)


The submitter of bug 3976 reports wild results from cosh and sinh in
non-default rounding modes.  I can reproduce this with older glibc,
but not after my exp patch (the problems presumably arose from exp as
called by those functions).  This patch adds tests for cosh and sinh
in each rounding mode (with arguments that showed problems with older
glibc) to protect against this problem appearing again.

The error of 27ulp for long double sinh in round-upwards mode is
larger than ideal (it becomes the largest checked-in ulps value; the
largest was 24 after my recent change to reduce some values), but I
don't think it's enough to merit a separate bug (or making sinh save
and restore the rounding mode itself).

2012-03-02  Joseph Myers  <joseph@codesourcery.com>

	[BZ #3976]
	* math/libm-test.inc (cosh_test_tonearest): New function.
	(cosh_test_towardzero): Likewise.
	(cosh_test_downward): Likewise.
	(cosh_test_upward): Likewise.
	(sinh_test_tonearest): Likewise.
	(sinh_test_towardzero): Likewise.
	(sinh_test_downward): Likewise.
	(sinh_test_upward): Likewise.
	(main): Call the new functions.
	* sysdeps/i386/fpu/libm-test-ulps: Update.
	* sysdeps/x86_64/fpu/libm-test-ulps: Likewise.

diff --git a/math/libm-test.inc b/math/libm-test.inc
index 61c62dd..684955e 100644
--- a/math/libm-test.inc
+++ b/math/libm-test.inc
@@ -2178,6 +2178,114 @@ cosh_test (void)
 
 
 static void
+cosh_test_tonearest (void)
+{
+  int save_round_mode;
+  errno = 0;
+  FUNC(cosh) (0);
+  if (errno == ENOSYS)
+    /* Function not implemented.  */
+    return;
+
+  START (cosh_tonearest);
+
+  save_round_mode = fegetround ();
+
+  if (!fesetround (FE_TONEAREST))
+    {
+      TEST_f_f (cosh, 22, 1792456423.065795780980053377632656584997L);
+      TEST_f_f (cosh, 23, 4872401723.124451300068625740569997090344L);
+      TEST_f_f (cosh, 24, 13244561064.92173614708845674912733665919L);
+    }
+
+  fesetround (save_round_mode);
+
+  END (cosh_tonearest);
+}
+
+
+static void
+cosh_test_towardzero (void)
+{
+  int save_round_mode;
+  errno = 0;
+  FUNC(cosh) (0);
+  if (errno == ENOSYS)
+    /* Function not implemented.  */
+    return;
+
+  START (cosh_towardzero);
+
+  save_round_mode = fegetround ();
+
+  if (!fesetround (FE_TOWARDZERO))
+    {
+      TEST_f_f (cosh, 22, 1792456423.065795780980053377632656584997L);
+      TEST_f_f (cosh, 23, 4872401723.124451300068625740569997090344L);
+      TEST_f_f (cosh, 24, 13244561064.92173614708845674912733665919L);
+    }
+
+  fesetround (save_round_mode);
+
+  END (cosh_towardzero);
+}
+
+
+static void
+cosh_test_downward (void)
+{
+  int save_round_mode;
+  errno = 0;
+  FUNC(cosh) (0);
+  if (errno == ENOSYS)
+    /* Function not implemented.  */
+    return;
+
+  START (cosh_downward);
+
+  save_round_mode = fegetround ();
+
+  if (!fesetround (FE_DOWNWARD))
+    {
+      TEST_f_f (cosh, 22, 1792456423.065795780980053377632656584997L);
+      TEST_f_f (cosh, 23, 4872401723.124451300068625740569997090344L);
+      TEST_f_f (cosh, 24, 13244561064.92173614708845674912733665919L);
+    }
+
+  fesetround (save_round_mode);
+
+  END (cosh_downward);
+}
+
+
+static void
+cosh_test_upward (void)
+{
+  int save_round_mode;
+  errno = 0;
+  FUNC(cosh) (0);
+  if (errno == ENOSYS)
+    /* Function not implemented.  */
+    return;
+
+  START (cosh_upward);
+
+  save_round_mode = fegetround ();
+
+  if (!fesetround (FE_UPWARD))
+    {
+      TEST_f_f (cosh, 22, 1792456423.065795780980053377632656584997L);
+      TEST_f_f (cosh, 23, 4872401723.124451300068625740569997090344L);
+      TEST_f_f (cosh, 24, 13244561064.92173614708845674912733665919L);
+    }
+
+  fesetround (save_round_mode);
+
+  END (cosh_upward);
+}
+
+
+static void
 cpow_test (void)
 {
   errno = 0;
@@ -6243,6 +6351,115 @@ sinh_test (void)
   END (sinh);
 }
 
+
+static void
+sinh_test_tonearest (void)
+{
+  int save_round_mode;
+  errno = 0;
+  FUNC(sinh) (0);
+  if (errno == ENOSYS)
+    /* Function not implemented.  */
+    return;
+
+  START (sinh_tonearest);
+
+  save_round_mode = fegetround ();
+
+  if (!fesetround (FE_TONEAREST))
+    {
+      TEST_f_f (sinh, 22, 1792456423.065795780701106568345764104225L);
+      TEST_f_f (sinh, 23, 4872401723.124451299966006944252978187305L);
+      TEST_f_f (sinh, 24, 13244561064.92173614705070540368454568168L);
+    }
+
+  fesetround (save_round_mode);
+
+  END (sinh_tonearest);
+}
+
+
+static void
+sinh_test_towardzero (void)
+{
+  int save_round_mode;
+  errno = 0;
+  FUNC(sinh) (0);
+  if (errno == ENOSYS)
+    /* Function not implemented.  */
+    return;
+
+  START (sinh_towardzero);
+
+  save_round_mode = fegetround ();
+
+  if (!fesetround (FE_TOWARDZERO))
+    {
+      TEST_f_f (sinh, 22, 1792456423.065795780701106568345764104225L);
+      TEST_f_f (sinh, 23, 4872401723.124451299966006944252978187305L);
+      TEST_f_f (sinh, 24, 13244561064.92173614705070540368454568168L);
+    }
+
+  fesetround (save_round_mode);
+
+  END (sinh_towardzero);
+}
+
+
+static void
+sinh_test_downward (void)
+{
+  int save_round_mode;
+  errno = 0;
+  FUNC(sinh) (0);
+  if (errno == ENOSYS)
+    /* Function not implemented.  */
+    return;
+
+  START (sinh_downward);
+
+  save_round_mode = fegetround ();
+
+  if (!fesetround (FE_DOWNWARD))
+    {
+      TEST_f_f (sinh, 22, 1792456423.065795780701106568345764104225L);
+      TEST_f_f (sinh, 23, 4872401723.124451299966006944252978187305L);
+      TEST_f_f (sinh, 24, 13244561064.92173614705070540368454568168L);
+    }
+
+  fesetround (save_round_mode);
+
+  END (sinh_downward);
+}
+
+
+static void
+sinh_test_upward (void)
+{
+  int save_round_mode;
+  errno = 0;
+  FUNC(sinh) (0);
+  if (errno == ENOSYS)
+    /* Function not implemented.  */
+    return;
+
+  START (sinh_upward);
+
+  save_round_mode = fegetround ();
+
+  if (!fesetround (FE_UPWARD))
+    {
+      TEST_f_f (sinh, 22, 1792456423.065795780701106568345764104225L);
+      TEST_f_f (sinh, 23, 4872401723.124451299966006944252978187305L);
+      TEST_f_f (sinh, 24, 13244561064.92173614705070540368454568168L);
+    }
+
+  fesetround (save_round_mode);
+
+  END (sinh_upward);
+}
+
+
 static void
 sqrt_test (void)
 {
@@ -6962,7 +7179,15 @@ main (int argc, char **argv)
   asinh_test ();
   atanh_test ();
   cosh_test ();
+  cosh_test_tonearest ();
+  cosh_test_towardzero ();
+  cosh_test_downward ();
+  cosh_test_upward ();
   sinh_test ();
+  sinh_test_tonearest ();
+  sinh_test_towardzero ();
+  sinh_test_downward ();
+  sinh_test_upward ();
   tanh_test ();
 
   /* Exponential and logarithmic functions:  */
diff --git a/sysdeps/i386/fpu/libm-test-ulps b/sysdeps/i386/fpu/libm-test-ulps
index cb22d45..e17bc53 100644
--- a/sysdeps/i386/fpu/libm-test-ulps
+++ b/sysdeps/i386/fpu/libm-test-ulps
@@ -408,6 +408,42 @@ ifloat: 1
 Test "cosh (0.75) == 1.29468328467684468784170818539018176":
 ildouble: 1
 
+# cosh_downward
+Test "cosh_downward (22) == 1792456423.065795780980053377632656584997":
+double: 1
+float: 1
+ldouble: 2
+Test "cosh_downward (23) == 4872401723.124451300068625740569997090344":
+double: 1
+float: 1
+ldouble: 1
+Test "cosh_downward (24) == 13244561064.92173614708845674912733665919":
+float: 1
+ldouble: 1
+
+# cosh_tonearest
+Test "cosh_tonearest (22) == 1792456423.065795780980053377632656584997":
+ldouble: 1
+
+# cosh_towardzero
+Test "cosh_towardzero (22) == 1792456423.065795780980053377632656584997":
+double: 1
+float: 1
+ldouble: 2
+Test "cosh_towardzero (23) == 4872401723.124451300068625740569997090344":
+double: 1
+float: 1
+ldouble: 1
+Test "cosh_towardzero (24) == 13244561064.92173614708845674912733665919":
+float: 1
+ldouble: 1
+
+# cosh_upward
+Test "cosh_upward (23) == 4872401723.124451300068625740569997090344":
+ldouble: 1
+Test "cosh_upward (24) == 13244561064.92173614708845674912733665919":
+double: 1
+
 # cpow
 Test "Real part of: cpow (0.75 + 1.25 i, 0.0 + 1.0 i) == 0.331825439177608832276067945276730566 + 0.131338600281188544930936345230903032 i":
 float: 1
@@ -1052,6 +1088,58 @@ Test "sinh (0.75) == 0.822316731935829980703661634446913849":
 double: 1
 ildouble: 1
 
+# sinh_downward
+Test "sinh_downward (22) == 1792456423.065795780701106568345764104225":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+ldouble: 4
+Test "sinh_downward (23) == 4872401723.124451299966006944252978187305":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+Test "sinh_downward (24) == 13244561064.92173614705070540368454568168":
+float: 1
+ifloat: 1
+ldouble: 5
+
+# sinh_tonearest
+Test "sinh_tonearest (22) == 1792456423.065795780701106568345764104225":
+ldouble: 3
+Test "sinh_tonearest (23) == 4872401723.124451299966006944252978187305":
+ldouble: 1
+Test "sinh_tonearest (24) == 13244561064.92173614705070540368454568168":
+ldouble: 6
+
+# sinh_towardzero
+Test "sinh_towardzero (22) == 1792456423.065795780701106568345764104225":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+ldouble: 4
+Test "sinh_towardzero (23) == 4872401723.124451299966006944252978187305":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+Test "sinh_towardzero (24) == 13244561064.92173614705070540368454568168":
+float: 1
+ifloat: 1
+ldouble: 5
+
+# sinh_upward
+Test "sinh_upward (22) == 1792456423.065795780701106568345764104225":
+ldouble: 16
+Test "sinh_upward (23) == 4872401723.124451299966006944252978187305":
+ldouble: 27
+Test "sinh_upward (24) == 13244561064.92173614705070540368454568168":
+double: 1
+idouble: 1
+ldouble: 7
+
 # tan
 Test "tan (pi/4) == 1":
 double: 1
@@ -1568,6 +1656,23 @@ ldouble: 1
 Function: "cosh":
 ildouble: 1
 
+Function: "cosh_downward":
+double: 1
+float: 1
+ldouble: 2
+
+Function: "cosh_tonearest":
+ldouble: 1
+
+Function: "cosh_towardzero":
+double: 1
+float: 1
+ldouble: 2
+
+Function: "cosh_upward":
+double: 1
+ldouble: 1
+
 Function: Real part of "cpow":
 double: 1
 float: 4
@@ -1773,6 +1878,28 @@ Function: "sinh":
 double: 1
 ildouble: 1
 
+Function: "sinh_downward":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+ldouble: 5
+
+Function: "sinh_tonearest":
+ldouble: 6
+
+Function: "sinh_towardzero":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+ldouble: 5
+
+Function: "sinh_upward":
+double: 1
+idouble: 1
+ldouble: 27
+
 Function: "tan":
 double: 1
 idouble: 1
diff --git a/sysdeps/x86_64/fpu/libm-test-ulps b/sysdeps/x86_64/fpu/libm-test-ulps
index 0185f28..dd9e130 100644
--- a/sysdeps/x86_64/fpu/libm-test-ulps
+++ b/sysdeps/x86_64/fpu/libm-test-ulps
@@ -428,6 +428,50 @@ Test "cos_upward (9) == -0.9111302618846769883682947111811653112463":
 float: 2
 ifloat: 2
 
+# cosh_downward
+Test "cosh_downward (22) == 1792456423.065795780980053377632656584997":
+float: 1
+ifloat: 1
+ildouble: 2
+ldouble: 2
+Test "cosh_downward (23) == 4872401723.124451300068625740569997090344":
+float: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+Test "cosh_downward (24) == 13244561064.92173614708845674912733665919":
+float: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+
+# cosh_tonearest
+Test "cosh_tonearest (22) == 1792456423.065795780980053377632656584997":
+ildouble: 1
+ldouble: 1
+
+# cosh_towardzero
+Test "cosh_towardzero (22) == 1792456423.065795780980053377632656584997":
+float: 1
+ifloat: 1
+ildouble: 2
+ldouble: 2
+Test "cosh_towardzero (23) == 4872401723.124451300068625740569997090344":
+float: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+Test "cosh_towardzero (24) == 13244561064.92173614708845674912733665919":
+float: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+
+# cosh_upward
+Test "cosh_upward (23) == 4872401723.124451300068625740569997090344":
+ildouble: 1
+ldouble: 1
+
 # cpow
 Test "Real part of: cpow (0.75 + 1.25 i, 0.0 + 1.0 i) == 0.331825439177608832276067945276730566 + 0.131338600281188544930936345230903032 i":
 float: 1
@@ -1065,6 +1109,58 @@ Test "sinh (0x8p-32) == 1.86264514923095703232705808926175479e-9":
 ildouble: 1
 ldouble: 1
 
+# sinh_downward
+Test "sinh_downward (22) == 1792456423.065795780701106568345764104225":
+float: 1
+ifloat: 1
+ildouble: 4
+ldouble: 4
+Test "sinh_downward (23) == 4872401723.124451299966006944252978187305":
+float: 1
+ifloat: 1
+Test "sinh_downward (24) == 13244561064.92173614705070540368454568168":
+float: 1
+ifloat: 1
+ildouble: 5
+ldouble: 5
+
+# sinh_tonearest
+Test "sinh_tonearest (22) == 1792456423.065795780701106568345764104225":
+ildouble: 3
+ldouble: 3
+Test "sinh_tonearest (23) == 4872401723.124451299966006944252978187305":
+ildouble: 1
+ldouble: 1
+Test "sinh_tonearest (24) == 13244561064.92173614705070540368454568168":
+ildouble: 6
+ldouble: 6
+
+# sinh_towardzero
+Test "sinh_towardzero (22) == 1792456423.065795780701106568345764104225":
+float: 1
+ifloat: 1
+ildouble: 4
+ldouble: 4
+Test "sinh_towardzero (23) == 4872401723.124451299966006944252978187305":
+float: 1
+ifloat: 1
+Test "sinh_towardzero (24) == 13244561064.92173614705070540368454568168":
+float: 1
+ifloat: 1
+ildouble: 5
+ldouble: 5
+
+# sinh_upward
+Test "sinh_upward (22) == 1792456423.065795780701106568345764104225":
+ildouble: 16
+ldouble: 16
+Test "sinh_upward (23) == 4872401723.124451299966006944252978187305":
+ildouble: 27
+ldouble: 27
+Test "sinh_upward (24) == 13244561064.92173614705070540368454568168":
+ildouble: 7
+ldouble: 7
+
 # tan
 Test "tan (pi/4) == 1":
 double: 1
@@ -1546,6 +1642,26 @@ ifloat: 2
 ildouble: 1
 ldouble: 1
 
+Function: "cosh_downward":
+float: 1
+ifloat: 1
+ildouble: 2
+ldouble: 2
+
+Function: "cosh_tonearest":
+ildouble: 1
+ldouble: 1
+
+Function: "cosh_towardzero":
+float: 1
+ifloat: 1
+ildouble: 2
+ldouble: 2
+
+Function: "cosh_upward":
+ildouble: 1
+ldouble: 1
+
 Function: Real part of "cpow":
 double: 2
 float: 5
@@ -1754,6 +1870,26 @@ Function: "sinh":
 ildouble: 1
 ldouble: 1
 
+Function: "sinh_downward":
+float: 1
+ifloat: 1
+ildouble: 5
+ldouble: 5
+
+Function: "sinh_tonearest":
+ildouble: 6
+ldouble: 6
+
+Function: "sinh_towardzero":
+float: 1
+ifloat: 1
+ildouble: 5
+ldouble: 5
+
+Function: "sinh_upward":
+ildouble: 27
+ldouble: 27
+
 Function: "tan":
 double: 1
 idouble: 1

-- 
Joseph S. Myers
joseph@codesourcery.com


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]