about summary refs log tree commit diff
diff options
context:
space:
mode:
authorJoseph Myers <joseph@codesourcery.com>2012-03-02 20:51:39 +0000
committerJoseph Myers <joseph@codesourcery.com>2012-03-02 20:51:39 +0000
commit804360ed837e3347c9cd9738f25345d2587a1242 (patch)
treee2e9d62c3198feedb7dbd8c8ac5ff1bf0bf66275
parenta6d06d7b86f724046b462115556d0df682f9f703 (diff)
downloadglibc-804360ed837e3347c9cd9738f25345d2587a1242.tar.gz
glibc-804360ed837e3347c9cd9738f25345d2587a1242.tar.xz
glibc-804360ed837e3347c9cd9738f25345d2587a1242.zip
Fix sin, cos, tan in non-default rounding modes (bug 3976).
-rw-r--r--ChangeLog26
-rw-r--r--math/libm-test.inc421
-rw-r--r--sysdeps/i386/fpu/libm-test-ulps483
-rw-r--r--sysdeps/ieee754/dbl-64/s_sin.c109
-rw-r--r--sysdeps/ieee754/dbl-64/s_tan.c117
-rw-r--r--sysdeps/x86_64/fpu/libm-test-ulps378
6 files changed, 1451 insertions, 83 deletions
diff --git a/ChangeLog b/ChangeLog
index b856c4ba5a..6b5a9a408a 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,31 @@
 2012-03-02  Joseph Myers  <joseph@codesourcery.com>
 
+	[BZ #3976]
+	* sysdeps/ieee754/dbl-64/s_sin.c: Include <fenv.h>
+	(__sin): Save and restore rounding mode and use round-to-nearest
+	for all computations.
+	(__cos): Save and restore rounding mode and use round-to-nearest
+	for all computations.
+	* sysdeps/ieee754/dbl-64/s_tan.c: Include "math_private.h" and
+	<fenv.h>.
+	(tan): Save and restore rounding mode and use round-to-nearest for
+	all computations.
+	* math/libm-test.inc (cos_test_tonearest): New function.
+	(cos_test_towardzero): Likewise.
+	(cos_test_downward): Likewise.
+	(cos_test_upward): Likewise.
+	(sin_test_tonearest): Likewise.
+	(sin_test_towardzero): Likewise.
+	(sin_test_downward): Likewise.
+	(sin_test_upward): Likewise.
+	(tan_test_tonearest): Likewise.
+	(tan_test_towardzero): Likewise.
+	(tan_test_downward): Likewise.
+	(tan_test_upward): Likewise.
+	(main): Call the new functions.
+	* sysdeps/i386/fpu/libm-test-ulps: Update.
+	* sysdeps/x86_64/fpu/libm-test-ulps: Likewise.
+
 	[BZ #10135]
 	* sysdeps/ieee754/dbl-64/s_scalbln.c (__scalbln): First test for
 	small n, then large n, before computing and testing k+n.
diff --git a/math/libm-test.inc b/math/libm-test.inc
index ef7a253662..61c62dd1b0 100644
--- a/math/libm-test.inc
+++ b/math/libm-test.inc
@@ -2017,6 +2017,142 @@ cos_test (void)
 
 
 static void
+cos_test_tonearest (void)
+{
+  int save_round_mode;
+  errno = 0;
+  FUNC(cos) (0);
+  if (errno == ENOSYS)
+    /* Function not implemented.  */
+    return;
+
+  START (cos_tonearest);
+
+  save_round_mode = fegetround ();
+
+  if (!fesetround (FE_TONEAREST))
+    {
+      TEST_f_f (cos, 1, 0.5403023058681397174009366074429766037323L);
+      TEST_f_f (cos, 2, -0.4161468365471423869975682295007621897660L);
+      TEST_f_f (cos, 3, -0.9899924966004454572715727947312613023937L);
+      TEST_f_f (cos, 4, -0.6536436208636119146391681830977503814241L);
+      TEST_f_f (cos, 5, 0.2836621854632262644666391715135573083344L);
+      TEST_f_f (cos, 6, 0.9601702866503660205456522979229244054519L);
+      TEST_f_f (cos, 7, 0.7539022543433046381411975217191820122183L);
+      TEST_f_f (cos, 8, -0.1455000338086135258688413818311946826093L);
+      TEST_f_f (cos, 9, -0.9111302618846769883682947111811653112463L);
+      TEST_f_f (cos, 10, -0.8390715290764524522588639478240648345199L);
+    }
+
+  fesetround (save_round_mode);
+
+  END (cos_tonearest);
+}
+
+
+static void
+cos_test_towardzero (void)
+{
+  int save_round_mode;
+  errno = 0;
+  FUNC(cos) (0);
+  if (errno == ENOSYS)
+    /* Function not implemented.  */
+    return;
+
+  START (cos_towardzero);
+
+  save_round_mode = fegetround ();
+
+  if (!fesetround (FE_TOWARDZERO))
+    {
+      TEST_f_f (cos, 1, 0.5403023058681397174009366074429766037323L);
+      TEST_f_f (cos, 2, -0.4161468365471423869975682295007621897660L);
+      TEST_f_f (cos, 3, -0.9899924966004454572715727947312613023937L);
+      TEST_f_f (cos, 4, -0.6536436208636119146391681830977503814241L);
+      TEST_f_f (cos, 5, 0.2836621854632262644666391715135573083344L);
+      TEST_f_f (cos, 6, 0.9601702866503660205456522979229244054519L);
+      TEST_f_f (cos, 7, 0.7539022543433046381411975217191820122183L);
+      TEST_f_f (cos, 8, -0.1455000338086135258688413818311946826093L);
+      TEST_f_f (cos, 9, -0.9111302618846769883682947111811653112463L);
+      TEST_f_f (cos, 10, -0.8390715290764524522588639478240648345199L);
+    }
+
+  fesetround (save_round_mode);
+
+  END (cos_towardzero);
+}
+
+
+static void
+cos_test_downward (void)
+{
+  int save_round_mode;
+  errno = 0;
+  FUNC(cos) (0);
+  if (errno == ENOSYS)
+    /* Function not implemented.  */
+    return;
+
+  START (cos_downward);
+
+  save_round_mode = fegetround ();
+
+  if (!fesetround (FE_DOWNWARD))
+    {
+      TEST_f_f (cos, 1, 0.5403023058681397174009366074429766037323L);
+      TEST_f_f (cos, 2, -0.4161468365471423869975682295007621897660L);
+      TEST_f_f (cos, 3, -0.9899924966004454572715727947312613023937L);
+      TEST_f_f (cos, 4, -0.6536436208636119146391681830977503814241L);
+      TEST_f_f (cos, 5, 0.2836621854632262644666391715135573083344L);
+      TEST_f_f (cos, 6, 0.9601702866503660205456522979229244054519L);
+      TEST_f_f (cos, 7, 0.7539022543433046381411975217191820122183L);
+      TEST_f_f (cos, 8, -0.1455000338086135258688413818311946826093L);
+      TEST_f_f (cos, 9, -0.9111302618846769883682947111811653112463L);
+      TEST_f_f (cos, 10, -0.8390715290764524522588639478240648345199L);
+    }
+
+  fesetround (save_round_mode);
+
+  END (cos_downward);
+}
+
+
+static void
+cos_test_upward (void)
+{
+  int save_round_mode;
+  errno = 0;
+  FUNC(cos) (0);
+  if (errno == ENOSYS)
+    /* Function not implemented.  */
+    return;
+
+  START (cos_upward);
+
+  save_round_mode = fegetround ();
+
+  if (!fesetround (FE_UPWARD))
+    {
+      TEST_f_f (cos, 1, 0.5403023058681397174009366074429766037323L);
+      TEST_f_f (cos, 2, -0.4161468365471423869975682295007621897660L);
+      TEST_f_f (cos, 3, -0.9899924966004454572715727947312613023937L);
+      TEST_f_f (cos, 4, -0.6536436208636119146391681830977503814241L);
+      TEST_f_f (cos, 5, 0.2836621854632262644666391715135573083344L);
+      TEST_f_f (cos, 6, 0.9601702866503660205456522979229244054519L);
+      TEST_f_f (cos, 7, 0.7539022543433046381411975217191820122183L);
+      TEST_f_f (cos, 8, -0.1455000338086135258688413818311946826093L);
+      TEST_f_f (cos, 9, -0.9111302618846769883682947111811653112463L);
+      TEST_f_f (cos, 10, -0.8390715290764524522588639478240648345199L);
+    }
+
+  fesetround (save_round_mode);
+
+  END (cos_upward);
+}
+
+
+static void
 cosh_test (void)
 {
   errno = 0;
@@ -5914,6 +6050,142 @@ sin_test (void)
 
 
 static void
+sin_test_tonearest (void)
+{
+  int save_round_mode;
+  errno = 0;
+  FUNC(sin) (0);
+  if (errno == ENOSYS)
+    /* Function not implemented.  */
+    return;
+
+  START (sin_tonearest);
+
+  save_round_mode = fegetround ();
+
+  if (!fesetround (FE_TONEAREST))
+    {
+      TEST_f_f (sin, 1, 0.8414709848078965066525023216302989996226L);
+      TEST_f_f (sin, 2, 0.9092974268256816953960198659117448427023L);
+      TEST_f_f (sin, 3, 0.1411200080598672221007448028081102798469L);
+      TEST_f_f (sin, 4, -0.7568024953079282513726390945118290941359L);
+      TEST_f_f (sin, 5, -0.9589242746631384688931544061559939733525L);
+      TEST_f_f (sin, 6, -0.2794154981989258728115554466118947596280L);
+      TEST_f_f (sin, 7, 0.6569865987187890903969990915936351779369L);
+      TEST_f_f (sin, 8, 0.9893582466233817778081235982452886721164L);
+      TEST_f_f (sin, 9, 0.4121184852417565697562725663524351793439L);
+      TEST_f_f (sin, 10, -0.5440211108893698134047476618513772816836L);
+    }
+
+  fesetround (save_round_mode);
+
+  END (sin_tonearest);
+}
+
+
+static void
+sin_test_towardzero (void)
+{
+  int save_round_mode;
+  errno = 0;
+  FUNC(sin) (0);
+  if (errno == ENOSYS)
+    /* Function not implemented.  */
+    return;
+
+  START (sin_towardzero);
+
+  save_round_mode = fegetround ();
+
+  if (!fesetround (FE_TOWARDZERO))
+    {
+      TEST_f_f (sin, 1, 0.8414709848078965066525023216302989996226L);
+      TEST_f_f (sin, 2, 0.9092974268256816953960198659117448427023L);
+      TEST_f_f (sin, 3, 0.1411200080598672221007448028081102798469L);
+      TEST_f_f (sin, 4, -0.7568024953079282513726390945118290941359L);
+      TEST_f_f (sin, 5, -0.9589242746631384688931544061559939733525L);
+      TEST_f_f (sin, 6, -0.2794154981989258728115554466118947596280L);
+      TEST_f_f (sin, 7, 0.6569865987187890903969990915936351779369L);
+      TEST_f_f (sin, 8, 0.9893582466233817778081235982452886721164L);
+      TEST_f_f (sin, 9, 0.4121184852417565697562725663524351793439L);
+      TEST_f_f (sin, 10, -0.5440211108893698134047476618513772816836L);
+    }
+
+  fesetround (save_round_mode);
+
+  END (sin_towardzero);
+}
+
+
+static void
+sin_test_downward (void)
+{
+  int save_round_mode;
+  errno = 0;
+  FUNC(sin) (0);
+  if (errno == ENOSYS)
+    /* Function not implemented.  */
+    return;
+
+  START (sin_downward);
+
+  save_round_mode = fegetround ();
+
+  if (!fesetround (FE_DOWNWARD))
+    {
+      TEST_f_f (sin, 1, 0.8414709848078965066525023216302989996226L);
+      TEST_f_f (sin, 2, 0.9092974268256816953960198659117448427023L);
+      TEST_f_f (sin, 3, 0.1411200080598672221007448028081102798469L);
+      TEST_f_f (sin, 4, -0.7568024953079282513726390945118290941359L);
+      TEST_f_f (sin, 5, -0.9589242746631384688931544061559939733525L);
+      TEST_f_f (sin, 6, -0.2794154981989258728115554466118947596280L);
+      TEST_f_f (sin, 7, 0.6569865987187890903969990915936351779369L);
+      TEST_f_f (sin, 8, 0.9893582466233817778081235982452886721164L);
+      TEST_f_f (sin, 9, 0.4121184852417565697562725663524351793439L);
+      TEST_f_f (sin, 10, -0.5440211108893698134047476618513772816836L);
+    }
+
+  fesetround (save_round_mode);
+
+  END (sin_downward);
+}
+
+
+static void
+sin_test_upward (void)
+{
+  int save_round_mode;
+  errno = 0;
+  FUNC(sin) (0);
+  if (errno == ENOSYS)
+    /* Function not implemented.  */
+    return;
+
+  START (sin_upward);
+
+  save_round_mode = fegetround ();
+
+  if (!fesetround (FE_UPWARD))
+    {
+      TEST_f_f (sin, 1, 0.8414709848078965066525023216302989996226L);
+      TEST_f_f (sin, 2, 0.9092974268256816953960198659117448427023L);
+      TEST_f_f (sin, 3, 0.1411200080598672221007448028081102798469L);
+      TEST_f_f (sin, 4, -0.7568024953079282513726390945118290941359L);
+      TEST_f_f (sin, 5, -0.9589242746631384688931544061559939733525L);
+      TEST_f_f (sin, 6, -0.2794154981989258728115554466118947596280L);
+      TEST_f_f (sin, 7, 0.6569865987187890903969990915936351779369L);
+      TEST_f_f (sin, 8, 0.9893582466233817778081235982452886721164L);
+      TEST_f_f (sin, 9, 0.4121184852417565697562725663524351793439L);
+      TEST_f_f (sin, 10, -0.5440211108893698134047476618513772816836L);
+    }
+
+  fesetround (save_round_mode);
+
+  END (sin_upward);
+}
+
+
+static void
 sincos_test (void)
 {
   FLOAT sin_res, cos_res;
@@ -6034,6 +6306,143 @@ tan_test (void)
   END (tan);
 }
 
+
+static void
+tan_test_tonearest (void)
+{
+  int save_round_mode;
+  errno = 0;
+  FUNC(tan) (0);
+  if (errno == ENOSYS)
+    /* Function not implemented.  */
+    return;
+
+  START (tan_tonearest);
+
+  save_round_mode = fegetround ();
+
+  if (!fesetround (FE_TONEAREST))
+    {
+      TEST_f_f (tan, 1, 1.5574077246549022305069748074583601730873L);
+      TEST_f_f (tan, 2, -2.1850398632615189916433061023136825434320L);
+      TEST_f_f (tan, 3, -0.1425465430742778052956354105339134932261L);
+      TEST_f_f (tan, 4, 1.1578212823495775831373424182673239231198L);
+      TEST_f_f (tan, 5, -3.3805150062465856369827058794473439087096L);
+      TEST_f_f (tan, 6, -0.2910061913847491570536995888681755428312L);
+      TEST_f_f (tan, 7, 0.8714479827243187364564508896003135663222L);
+      TEST_f_f (tan, 8, -6.7997114552203786999252627596086333648814L);
+      TEST_f_f (tan, 9, -0.4523156594418098405903708757987855343087L);
+      TEST_f_f (tan, 10, 0.6483608274590866712591249330098086768169L);
+    }
+
+  fesetround (save_round_mode);
+
+  END (tan_tonearest);
+}
+
+
+static void
+tan_test_towardzero (void)
+{
+  int save_round_mode;
+  errno = 0;
+  FUNC(tan) (0);
+  if (errno == ENOSYS)
+    /* Function not implemented.  */
+    return;
+
+  START (tan_towardzero);
+
+  save_round_mode = fegetround ();
+
+  if (!fesetround (FE_TOWARDZERO))
+    {
+      TEST_f_f (tan, 1, 1.5574077246549022305069748074583601730873L);
+      TEST_f_f (tan, 2, -2.1850398632615189916433061023136825434320L);
+      TEST_f_f (tan, 3, -0.1425465430742778052956354105339134932261L);
+      TEST_f_f (tan, 4, 1.1578212823495775831373424182673239231198L);
+      TEST_f_f (tan, 5, -3.3805150062465856369827058794473439087096L);
+      TEST_f_f (tan, 6, -0.2910061913847491570536995888681755428312L);
+      TEST_f_f (tan, 7, 0.8714479827243187364564508896003135663222L);
+      TEST_f_f (tan, 8, -6.7997114552203786999252627596086333648814L);
+      TEST_f_f (tan, 9, -0.4523156594418098405903708757987855343087L);
+      TEST_f_f (tan, 10, 0.6483608274590866712591249330098086768169L);
+    }
+
+  fesetround (save_round_mode);
+
+  END (tan_towardzero);
+}
+
+
+static void
+tan_test_downward (void)
+{
+  int save_round_mode;
+  errno = 0;
+  FUNC(tan) (0);
+  if (errno == ENOSYS)
+    /* Function not implemented.  */
+    return;
+
+  START (tan_downward);
+
+  save_round_mode = fegetround ();
+
+  if (!fesetround (FE_DOWNWARD))
+    {
+      TEST_f_f (tan, 1, 1.5574077246549022305069748074583601730873L);
+      TEST_f_f (tan, 2, -2.1850398632615189916433061023136825434320L);
+      TEST_f_f (tan, 3, -0.1425465430742778052956354105339134932261L);
+      TEST_f_f (tan, 4, 1.1578212823495775831373424182673239231198L);
+      TEST_f_f (tan, 5, -3.3805150062465856369827058794473439087096L);
+      TEST_f_f (tan, 6, -0.2910061913847491570536995888681755428312L);
+      TEST_f_f (tan, 7, 0.8714479827243187364564508896003135663222L);
+      TEST_f_f (tan, 8, -6.7997114552203786999252627596086333648814L);
+      TEST_f_f (tan, 9, -0.4523156594418098405903708757987855343087L);
+      TEST_f_f (tan, 10, 0.6483608274590866712591249330098086768169L);
+    }
+
+  fesetround (save_round_mode);
+
+  END (tan_downward);
+}
+
+
+static void
+tan_test_upward (void)
+{
+  int save_round_mode;
+  errno = 0;
+  FUNC(tan) (0);
+  if (errno == ENOSYS)
+    /* Function not implemented.  */
+    return;
+
+  START (tan_upward);
+
+  save_round_mode = fegetround ();
+
+  if (!fesetround (FE_UPWARD))
+    {
+      TEST_f_f (tan, 1, 1.5574077246549022305069748074583601730873L);
+      TEST_f_f (tan, 2, -2.1850398632615189916433061023136825434320L);
+      TEST_f_f (tan, 3, -0.1425465430742778052956354105339134932261L);
+      TEST_f_f (tan, 4, 1.1578212823495775831373424182673239231198L);
+      TEST_f_f (tan, 5, -3.3805150062465856369827058794473439087096L);
+      TEST_f_f (tan, 6, -0.2910061913847491570536995888681755428312L);
+      TEST_f_f (tan, 7, 0.8714479827243187364564508896003135663222L);
+      TEST_f_f (tan, 8, -6.7997114552203786999252627596086333648814L);
+      TEST_f_f (tan, 9, -0.4523156594418098405903708757987855343087L);
+      TEST_f_f (tan, 10, 0.6483608274590866712591249330098086768169L);
+    }
+
+  fesetround (save_round_mode);
+
+  END (tan_upward);
+}
+
+
 static void
 tanh_test (void)
 {
@@ -6532,9 +6941,21 @@ main (int argc, char **argv)
   atan_test ();
   atan2_test ();
   cos_test ();
+  cos_test_tonearest ();
+  cos_test_towardzero ();
+  cos_test_downward ();
+  cos_test_upward ();
   sin_test ();
+  sin_test_tonearest ();
+  sin_test_towardzero ();
+  sin_test_downward ();
+  sin_test_upward ();
   sincos_test ();
   tan_test ();
+  tan_test_tonearest ();
+  tan_test_towardzero ();
+  tan_test_downward ();
+  tan_test_upward ();
 
   /* Hyperbolic functions:  */
   acosh_test ();
diff --git a/sysdeps/i386/fpu/libm-test-ulps b/sysdeps/i386/fpu/libm-test-ulps
index 389253e1e3..cb22d45655 100644
--- a/sysdeps/i386/fpu/libm-test-ulps
+++ b/sysdeps/i386/fpu/libm-test-ulps
@@ -280,6 +280,130 @@ ifloat: 1
 ildouble: 1
 ldouble: 1
 
+# cos_downward
+Test "cos_downward (1) == 0.5403023058681397174009366074429766037323":
+double: 1
+idouble: 1
+ildouble: 1
+ldouble: 1
+Test "cos_downward (10) == -0.8390715290764524522588639478240648345199":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+Test "cos_downward (3) == -0.9899924966004454572715727947312613023937":
+double: 1
+idouble: 1
+Test "cos_downward (4) == -0.6536436208636119146391681830977503814241":
+float: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+Test "cos_downward (5) == 0.2836621854632262644666391715135573083344":
+float: 1
+ifloat: 1
+Test "cos_downward (7) == 0.7539022543433046381411975217191820122183":
+float: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+Test "cos_downward (8) == -0.1455000338086135258688413818311946826093":
+ildouble: 1
+ldouble: 1
+Test "cos_downward (9) == -0.9111302618846769883682947111811653112463":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+
+# cos_tonearest
+Test "cos_tonearest (8) == -0.1455000338086135258688413818311946826093":
+ildouble: 1
+ldouble: 1
+
+# cos_towardzero
+Test "cos_towardzero (1) == 0.5403023058681397174009366074429766037323":
+double: 1
+idouble: 1
+ildouble: 1
+ldouble: 1
+Test "cos_towardzero (10) == -0.8390715290764524522588639478240648345199":
+ildouble: 1
+ldouble: 1
+Test "cos_towardzero (2) == -0.4161468365471423869975682295007621897660":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+Test "cos_towardzero (3) == -0.9899924966004454572715727947312613023937":
+float: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+Test "cos_towardzero (4) == -0.6536436208636119146391681830977503814241":
+double: 1
+idouble: 1
+Test "cos_towardzero (5) == 0.2836621854632262644666391715135573083344":
+float: 1
+ifloat: 1
+Test "cos_towardzero (7) == 0.7539022543433046381411975217191820122183":
+float: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+Test "cos_towardzero (8) == -0.1455000338086135258688413818311946826093":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+
+# cos_upward
+Test "cos_upward (1) == 0.5403023058681397174009366074429766037323":
+float: 1
+ifloat: 1
+Test "cos_upward (10) == -0.8390715290764524522588639478240648345199":
+ildouble: 1
+ldouble: 1
+Test "cos_upward (2) == -0.4161468365471423869975682295007621897660":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+Test "cos_upward (3) == -0.9899924966004454572715727947312613023937":
+float: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+Test "cos_upward (4) == -0.6536436208636119146391681830977503814241":
+double: 1
+idouble: 1
+Test "cos_upward (5) == 0.2836621854632262644666391715135573083344":
+double: 1
+idouble: 1
+ildouble: 1
+ldouble: 1
+Test "cos_upward (6) == 0.9601702866503660205456522979229244054519":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+Test "cos_upward (7) == 0.7539022543433046381411975217191820122183":
+double: 1
+idouble: 1
+Test "cos_upward (8) == -0.1455000338086135258688413818311946826093":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+
 # cosh
 Test "cosh (0.75) == 1.29468328467684468784170818539018176":
 ildouble: 1
@@ -773,6 +897,135 @@ ifloat: 1
 ildouble: 1
 ldouble: 1
 
+# sin_downward
+Test "sin_downward (1) == 0.8414709848078965066525023216302989996226":
+ildouble: 1
+ldouble: 1
+Test "sin_downward (10) == -0.5440211108893698134047476618513772816836":
+double: 1
+idouble: 1
+ildouble: 1
+ldouble: 1
+Test "sin_downward (2) == 0.9092974268256816953960198659117448427023":
+double: 1
+idouble: 1
+Test "sin_downward (3) == 0.1411200080598672221007448028081102798469":
+ildouble: 1
+ldouble: 1
+Test "sin_downward (4) == -0.7568024953079282513726390945118290941359":
+double: 1
+idouble: 1
+ildouble: 1
+ldouble: 1
+Test "sin_downward (5) == -0.9589242746631384688931544061559939733525":
+double: 1
+idouble: 1
+ildouble: 1
+ldouble: 1
+Test "sin_downward (6) == -0.2794154981989258728115554466118947596280":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+Test "sin_downward (7) == 0.6569865987187890903969990915936351779369":
+ildouble: 1
+ldouble: 1
+Test "sin_downward (8) == 0.9893582466233817778081235982452886721164":
+double: 1
+idouble: 1
+ildouble: 1
+ldouble: 1
+Test "sin_downward (9) == 0.4121184852417565697562725663524351793439":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+
+# sin_tonearest
+Test "sin_tonearest (10) == -0.5440211108893698134047476618513772816836":
+ildouble: 1
+ldouble: 1
+Test "sin_tonearest (4) == -0.7568024953079282513726390945118290941359":
+ildouble: 1
+ldouble: 1
+
+# sin_towardzero
+Test "sin_towardzero (1) == 0.8414709848078965066525023216302989996226":
+ildouble: 1
+ldouble: 1
+Test "sin_towardzero (10) == -0.5440211108893698134047476618513772816836":
+float: 1
+ifloat: 1
+Test "sin_towardzero (2) == 0.9092974268256816953960198659117448427023":
+double: 1
+idouble: 1
+Test "sin_towardzero (3) == 0.1411200080598672221007448028081102798469":
+ildouble: 1
+ldouble: 1
+Test "sin_towardzero (4) == -0.7568024953079282513726390945118290941359":
+float: 1
+ifloat: 1
+Test "sin_towardzero (5) == -0.9589242746631384688931544061559939733525":
+float: 1
+ifloat: 1
+Test "sin_towardzero (6) == -0.2794154981989258728115554466118947596280":
+ildouble: 1
+ldouble: 1
+Test "sin_towardzero (7) == 0.6569865987187890903969990915936351779369":
+ildouble: 1
+ldouble: 1
+Test "sin_towardzero (8) == 0.9893582466233817778081235982452886721164":
+double: 1
+idouble: 1
+ildouble: 1
+ldouble: 1
+Test "sin_towardzero (9) == 0.4121184852417565697562725663524351793439":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+
+# sin_upward
+Test "sin_upward (1) == 0.8414709848078965066525023216302989996226":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+Test "sin_upward (10) == -0.5440211108893698134047476618513772816836":
+float: 1
+ifloat: 1
+Test "sin_upward (2) == 0.9092974268256816953960198659117448427023":
+float: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+Test "sin_upward (3) == 0.1411200080598672221007448028081102798469":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+Test "sin_upward (4) == -0.7568024953079282513726390945118290941359":
+float: 1
+ifloat: 1
+Test "sin_upward (5) == -0.9589242746631384688931544061559939733525":
+float: 1
+ifloat: 1
+Test "sin_upward (6) == -0.2794154981989258728115554466118947596280":
+ildouble: 1
+ldouble: 1
+Test "sin_upward (7) == 0.6569865987187890903969990915936351779369":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+Test "sin_upward (8) == 0.9893582466233817778081235982452886721164":
+float: 1
+ifloat: 1
+
 # sincos
 Test "sincos (M_PI_6l*2.0, &sin_res, &cos_res) puts 0.5 in cos_res":
 double: 1
@@ -804,6 +1057,152 @@ Test "tan (pi/4) == 1":
 double: 1
 idouble: 1
 
+# tan_downward
+Test "tan_downward (1) == 1.5574077246549022305069748074583601730873":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+Test "tan_downward (10) == 0.6483608274590866712591249330098086768169":
+float: 1
+ifloat: 1
+Test "tan_downward (2) == -2.1850398632615189916433061023136825434320":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+Test "tan_downward (3) == -0.1425465430742778052956354105339134932261":
+double: 1
+idouble: 1
+ildouble: 1
+ldouble: 1
+Test "tan_downward (4) == 1.1578212823495775831373424182673239231198":
+float: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+Test "tan_downward (6) == -0.2910061913847491570536995888681755428312":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+Test "tan_downward (7) == 0.8714479827243187364564508896003135663222":
+double: 1
+idouble: 1
+Test "tan_downward (8) == -6.7997114552203786999252627596086333648814":
+float: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+Test "tan_downward (9) == -0.4523156594418098405903708757987855343087":
+float: 1
+ifloat: 1
+
+# tan_tonearest
+Test "tan_tonearest (1) == 1.5574077246549022305069748074583601730873":
+ildouble: 1
+ldouble: 1
+Test "tan_tonearest (2) == -2.1850398632615189916433061023136825434320":
+ildouble: 1
+ldouble: 1
+Test "tan_tonearest (6) == -0.2910061913847491570536995888681755428312":
+ildouble: 1
+ldouble: 1
+Test "tan_tonearest (8) == -6.7997114552203786999252627596086333648814":
+ildouble: 1
+ldouble: 1
+Test "tan_tonearest (9) == -0.4523156594418098405903708757987855343087":
+ildouble: 1
+ldouble: 1
+
+# tan_towardzero
+Test "tan_towardzero (1) == 1.5574077246549022305069748074583601730873":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+Test "tan_towardzero (10) == 0.6483608274590866712591249330098086768169":
+float: 1
+ifloat: 1
+Test "tan_towardzero (2) == -2.1850398632615189916433061023136825434320":
+ildouble: 1
+ldouble: 1
+Test "tan_towardzero (3) == -0.1425465430742778052956354105339134932261":
+float: 1
+ifloat: 1
+Test "tan_towardzero (4) == 1.1578212823495775831373424182673239231198":
+float: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+Test "tan_towardzero (5) == -3.3805150062465856369827058794473439087096":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+Test "tan_towardzero (6) == -0.2910061913847491570536995888681755428312":
+ildouble: 1
+ldouble: 1
+Test "tan_towardzero (7) == 0.8714479827243187364564508896003135663222":
+double: 1
+idouble: 1
+Test "tan_towardzero (8) == -6.7997114552203786999252627596086333648814":
+double: 1
+idouble: 1
+ildouble: 2
+ldouble: 2
+Test "tan_towardzero (9) == -0.4523156594418098405903708757987855343087":
+double: 1
+idouble: 1
+ildouble: 1
+ldouble: 1
+
+# tan_upward
+Test "tan_upward (1) == 1.5574077246549022305069748074583601730873":
+ildouble: 1
+ldouble: 1
+Test "tan_upward (10) == 0.6483608274590866712591249330098086768169":
+double: 1
+idouble: 1
+ildouble: 1
+ldouble: 1
+Test "tan_upward (2) == -2.1850398632615189916433061023136825434320":
+ildouble: 1
+ldouble: 1
+Test "tan_upward (3) == -0.1425465430742778052956354105339134932261":
+float: 1
+ifloat: 1
+Test "tan_upward (4) == 1.1578212823495775831373424182673239231198":
+double: 1
+idouble: 1
+Test "tan_upward (5) == -3.3805150062465856369827058794473439087096":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+Test "tan_upward (6) == -0.2910061913847491570536995888681755428312":
+ildouble: 1
+ldouble: 1
+Test "tan_upward (7) == 0.8714479827243187364564508896003135663222":
+float: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+Test "tan_upward (8) == -6.7997114552203786999252627596086333648814":
+double: 1
+idouble: 1
+ildouble: 2
+ldouble: 2
+Test "tan_upward (9) == -0.4523156594418098405903708757987855343087":
+double: 1
+idouble: 1
+ildouble: 1
+ldouble: 1
+
 # tgamma
 Test "tgamma (-0.5) == -2 sqrt (pi)":
 double: 2
@@ -1138,6 +1537,34 @@ ifloat: 1
 ildouble: 1
 ldouble: 1
 
+Function: "cos_downward":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+
+Function: "cos_tonearest":
+ildouble: 1
+ldouble: 1
+
+Function: "cos_towardzero":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+
+Function: "cos_upward":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+
 Function: "cosh":
 ildouble: 1
 
@@ -1306,6 +1733,34 @@ ifloat: 1
 ildouble: 1
 ldouble: 1
 
+Function: "sin_downward":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+
+Function: "sin_tonearest":
+ildouble: 1
+ldouble: 1
+
+Function: "sin_towardzero":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+
+Function: "sin_upward":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+
 Function: "sincos":
 double: 1
 float: 1
@@ -1322,6 +1777,34 @@ Function: "tan":
 double: 1
 idouble: 1
 
+Function: "tan_downward":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+
+Function: "tan_tonearest":
+ildouble: 1
+ldouble: 1
+
+Function: "tan_towardzero":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+ildouble: 2
+ldouble: 2
+
+Function: "tan_upward":
+double: 1
+float: 1
+idouble: 1
+ifloat: 1
+ildouble: 2
+ldouble: 2
+
 Function: "tgamma":
 double: 2
 float: 1
diff --git a/sysdeps/ieee754/dbl-64/s_sin.c b/sysdeps/ieee754/dbl-64/s_sin.c
index 5b79854004..32ba66d1a0 100644
--- a/sysdeps/ieee754/dbl-64/s_sin.c
+++ b/sysdeps/ieee754/dbl-64/s_sin.c
@@ -53,6 +53,7 @@
 #include "usncs.h"
 #include "MathLib.h"
 #include "math_private.h"
+#include <fenv.h>
 
 #ifndef SECTION
 # define SECTION
@@ -107,12 +108,16 @@ __sin(double x){
 #if 0
 	int4 nn;
 #endif
+	fenv_t env;
+	double retval = 0;
+
+	libc_feholdexcept_setround (&env, FE_TONEAREST);
 
 	u.x = x;
 	m = u.i[HIGH_HALF];
 	k = 0x7fffffff&m;              /* no sign           */
 	if (k < 0x3e500000)            /* if x->0 =>sin(x)=x */
-	 return x;
+	  { retval = x; goto ret; }
  /*---------------------------- 2^-26 < |x|< 0.25 ----------------------*/
 	else  if (k < 0x3fd00000){
 	  xx = x*x;
@@ -120,7 +125,8 @@ __sin(double x){
 	  t = ((((s5.x*xx + s4.x)*xx + s3.x)*xx + s2.x)*xx + s1.x)*(xx*x);
 	  res = x+t;
 	  cor = (x-res)+t;
-	  return (res == res + 1.07*cor)? res : slow(x);
+	  retval = (res == res + 1.07*cor)? res : slow(x);
+	  goto ret;
 	}    /*  else  if (k < 0x3fd00000)    */
 /*---------------------------- 0.25<|x|< 0.855469---------------------- */
 	else if (k < 0x3feb6000)  {
@@ -137,7 +143,8 @@ __sin(double x){
 	  cor=(ssn+s*ccs-sn*c)+cs*s;
 	  res=sn+cor;
 	  cor=(sn-res)+cor;
-	  return (res==res+1.096*cor)? res : slow1(x);
+	  retval = (res==res+1.096*cor)? res : slow1(x);
+	  goto ret;
 	}    /*   else  if (k < 0x3feb6000)    */
 
 /*----------------------- 0.855469  <|x|<2.426265  ----------------------*/
@@ -163,7 +170,8 @@ __sin(double x){
 	  cor=(ccs-s*ssn-cs*c)-sn*s;
 	  res=cs+cor;
 	  cor=(cs-res)+cor;
-	  return (res==res+1.020*cor)? ((m>0)?res:-res) : slow2(x);
+	  retval = (res==res+1.020*cor)? ((m>0)?res:-res) : slow2(x);
+	  goto ret;
 	} /*   else  if (k < 0x400368fd)    */
 
 /*-------------------------- 2.426265<|x|< 105414350 ----------------------*/
@@ -189,7 +197,8 @@ __sin(double x){
 	      res = a+t;
 	      cor = (a-res)+t;
 	      cor = (cor>0)? 1.02*cor+eps : 1.02*cor -eps;
-	      return (res == res + cor)? res : sloww(a,da,x);
+	      retval = (res == res + cor)? res : sloww(a,da,x);
+	      goto ret;
 	    }
 	    else  {
 	      if (a>0)
@@ -210,7 +219,8 @@ __sin(double x){
 	      res=sn+cor;
 	      cor=(sn-res)+cor;
 	      cor = (cor>0)? 1.035*cor+eps : 1.035*cor-eps;
-	      return (res==res+cor)? ((m)?res:-res) : sloww1(a,da,x);
+	      retval = (res==res+cor)? ((m)?res:-res) : sloww1(a,da,x);
+	      goto ret;
 	    }
 	    break;
 
@@ -232,7 +242,8 @@ __sin(double x){
 	    res=cs+cor;
 	    cor=(cs-res)+cor;
 	    cor = (cor>0)? 1.025*cor+eps : 1.025*cor-eps;
-	    return (res==res+cor)? ((n&2)?-res:res) : sloww2(a,da,x,n);
+	    retval = (res==res+cor)? ((n&2)?-res:res) : sloww2(a,da,x,n);
+	    goto ret;
 
 	    break;
 
@@ -268,7 +279,8 @@ __sin(double x){
 	      res = a+t;
 	      cor = (a-res)+t;
 	      cor = (cor>0)? 1.02*cor+eps : 1.02*cor -eps;
-	      return (res == res + cor)? res : bsloww(a,da,x,n);
+	      retval = (res == res + cor)? res : bsloww(a,da,x,n);
+	      goto ret;
 	    }
 	    else  {
 	      if (a>0) {m=1;t=a;db=da;}
@@ -287,7 +299,8 @@ __sin(double x){
 	      res=sn+cor;
 	      cor=(sn-res)+cor;
 	      cor = (cor>0)? 1.035*cor+eps : 1.035*cor-eps;
-	      return (res==res+cor)? ((m)?res:-res) : bsloww1(a,da,x,n);
+	      retval = (res==res+cor)? ((m)?res:-res) : bsloww1(a,da,x,n);
+	      goto ret;
 		   }
 	    break;
 
@@ -309,7 +322,8 @@ __sin(double x){
 	    res=cs+cor;
 	    cor=(cs-res)+cor;
 	    cor = (cor>0)? 1.025*cor+eps : 1.025*cor-eps;
-	    return (res==res+cor)? ((n&2)?-res:res) : bsloww2(a,da,x,n);
+	    retval = (res==res+cor)? ((n&2)?-res:res) : bsloww2(a,da,x,n);
+	    goto ret;
 
 	    break;
 
@@ -323,17 +337,20 @@ __sin(double x){
 	  n = __branred(x,&a,&da);
 	  switch (n) {
 	  case 0:
-	    if (a*a < 0.01588) return bsloww(a,da,x,n);
-	    else return bsloww1(a,da,x,n);
+	    if (a*a < 0.01588) retval = bsloww(a,da,x,n);
+	    else retval = bsloww1(a,da,x,n);
+	    goto ret;
 	    break;
 	  case 2:
-	    if (a*a < 0.01588) return bsloww(-a,-da,x,n);
-	    else return bsloww1(-a,-da,x,n);
+	    if (a*a < 0.01588) retval = bsloww(-a,-da,x,n);
+	    else retval = bsloww1(-a,-da,x,n);
+	    goto ret;
 	    break;
 
 	  case 1:
 	  case 3:
-	    return  bsloww2(a,da,x,n);
+	    retval = bsloww2(a,da,x,n);
+	    goto ret;
 	    break;
 	  }
 
@@ -343,9 +360,13 @@ __sin(double x){
 	else {
 	  if (k == 0x7ff00000 && u.i[LOW_HALF] == 0)
 	    __set_errno (EDOM);
-	  return x / x;
+	  retval = x / x;
+	  goto ret;
 	}
-	return 0;         /* unreachable */
+
+ ret:
+	libc_feupdateenv (&env);
+	return retval;
 }
 
 
@@ -362,11 +383,16 @@ __cos(double x)
   mynumber u,v;
   int4 k,m,n;
 
+  fenv_t env;
+  double retval = 0;
+
+  libc_feholdexcept_setround (&env, FE_TONEAREST);
+
   u.x = x;
   m = u.i[HIGH_HALF];
   k = 0x7fffffff&m;
 
-  if (k < 0x3e400000 ) return 1.0; /* |x|<2^-27 => cos(x)=1 */
+  if (k < 0x3e400000 ) { retval = 1.0; goto ret; } /* |x|<2^-27 => cos(x)=1 */
 
   else if (k < 0x3feb6000 ) {/* 2^-27 < |x| < 0.855469 */
     y=ABS(x);
@@ -383,7 +409,8 @@ __cos(double x)
     cor=(ccs-s*ssn-cs*c)-sn*s;
     res=cs+cor;
     cor=(cs-res)+cor;
-    return (res==res+1.020*cor)? res : cslow2(x);
+    retval = (res==res+1.020*cor)? res : cslow2(x);
+    goto ret;
 
 }    /*   else  if (k < 0x3feb6000)    */
 
@@ -397,7 +424,8 @@ __cos(double x)
       res = a+t;
       cor = (a-res)+t;
       cor = (cor>0)? 1.02*cor+1.0e-31 : 1.02*cor -1.0e-31;
-      return (res == res + cor)? res : csloww(a,da,x);
+      retval = (res == res + cor)? res : csloww(a,da,x);
+      goto ret;
     }
     else  {
       if (a>0) {m=1;t=a;db=da;}
@@ -416,7 +444,8 @@ __cos(double x)
       res=sn+cor;
       cor=(sn-res)+cor;
       cor = (cor>0)? 1.035*cor+1.0e-31 : 1.035*cor-1.0e-31;
-      return (res==res+cor)? ((m)?res:-res) : csloww1(a,da,x);
+      retval = (res==res+cor)? ((m)?res:-res) : csloww1(a,da,x);
+      goto ret;
 }
 
 }    /*   else  if (k < 0x400368fd)    */
@@ -443,7 +472,8 @@ __cos(double x)
 	res = a+t;
 	cor = (a-res)+t;
 	cor = (cor>0)? 1.02*cor+eps : 1.02*cor -eps;
-	return (res == res + cor)? res : csloww(a,da,x);
+	retval = (res == res + cor)? res : csloww(a,da,x);
+	goto ret;
       }
       else  {
 	if (a>0) {m=1;t=a;db=da;}
@@ -462,7 +492,8 @@ __cos(double x)
 	res=sn+cor;
 	cor=(sn-res)+cor;
 	cor = (cor>0)? 1.035*cor+eps : 1.035*cor-eps;
-	return (res==res+cor)? ((m)?res:-res) : csloww1(a,da,x);
+	retval = (res==res+cor)? ((m)?res:-res) : csloww1(a,da,x);
+	goto ret;
       }
       break;
 
@@ -483,7 +514,8 @@ __cos(double x)
       res=cs+cor;
       cor=(cs-res)+cor;
       cor = (cor>0)? 1.025*cor+eps : 1.025*cor-eps;
-      return (res==res+cor)? ((n)?-res:res) : csloww2(a,da,x,n);
+      retval = (res==res+cor)? ((n)?-res:res) : csloww2(a,da,x,n);
+      goto ret;
 
 	   break;
 
@@ -518,7 +550,8 @@ __cos(double x)
 	res = a+t;
 	cor = (a-res)+t;
 	cor = (cor>0)? 1.02*cor+eps : 1.02*cor -eps;
-	return (res == res + cor)? res : bsloww(a,da,x,n);
+	retval = (res == res + cor)? res : bsloww(a,da,x,n);
+	goto ret;
       }
       else  {
 	if (a>0) {m=1;t=a;db=da;}
@@ -537,7 +570,8 @@ __cos(double x)
 	res=sn+cor;
 	cor=(sn-res)+cor;
 	cor = (cor>0)? 1.035*cor+eps : 1.035*cor-eps;
-	return (res==res+cor)? ((m)?res:-res) : bsloww1(a,da,x,n);
+	retval = (res==res+cor)? ((m)?res:-res) : bsloww1(a,da,x,n);
+	goto ret;
       }
       break;
 
@@ -558,7 +592,8 @@ __cos(double x)
       res=cs+cor;
       cor=(cs-res)+cor;
       cor = (cor>0)? 1.025*cor+eps : 1.025*cor-eps;
-      return (res==res+cor)? ((n)?-res:res) : bsloww2(a,da,x,n);
+      retval = (res==res+cor)? ((n)?-res:res) : bsloww2(a,da,x,n);
+      goto ret;
       break;
 
     }
@@ -570,17 +605,20 @@ __cos(double x)
     n = __branred(x,&a,&da);
     switch (n) {
     case 1:
-      if (a*a < 0.01588) return bsloww(-a,-da,x,n);
-      else return bsloww1(-a,-da,x,n);
+      if (a*a < 0.01588) retval = bsloww(-a,-da,x,n);
+      else retval = bsloww1(-a,-da,x,n);
+      goto ret;
       break;
 		case 3:
-		  if (a*a < 0.01588) return bsloww(a,da,x,n);
-		  else return bsloww1(a,da,x,n);
+		  if (a*a < 0.01588) retval = bsloww(a,da,x,n);
+		  else retval = bsloww1(a,da,x,n);
+		  goto ret;
 		  break;
 
     case 0:
     case 2:
-      return  bsloww2(a,da,x,n);
+      retval = bsloww2(a,da,x,n);
+      goto ret;
       break;
     }
 
@@ -592,10 +630,13 @@ __cos(double x)
   else {
     if (k == 0x7ff00000 && u.i[LOW_HALF] == 0)
       __set_errno (EDOM);
-    return x / x; /* |x| > 2^1024 */
+    retval = x / x; /* |x| > 2^1024 */
+    goto ret;
   }
-  return 0;
 
+ ret:
+  libc_feupdateenv (&env);
+  return retval;
 }
 
 /************************************************************************/
diff --git a/sysdeps/ieee754/dbl-64/s_tan.c b/sysdeps/ieee754/dbl-64/s_tan.c
index 962a4eba6b..2c26756ff2 100644
--- a/sysdeps/ieee754/dbl-64/s_tan.c
+++ b/sysdeps/ieee754/dbl-64/s_tan.c
@@ -39,6 +39,8 @@
 #include "mpa.h"
 #include "MathLib.h"
 #include "math.h"
+#include "math_private.h"
+#include <fenv.h>
 
 #ifndef SECTION
 # define SECTION
@@ -66,21 +68,27 @@ tan(double x) {
   mp_no mpy;
 #endif
 
+  fenv_t env;
+  double retval;
+
   int __branred(double, double *, double *);
   int __mpranred(double, mp_no *, int);
 
+  libc_feholdexcept_setround (&env, FE_TONEAREST);
+
   /* x=+-INF, x=NaN */
   num.d = x;  ux = num.i[HIGH_HALF];
   if ((ux&0x7ff00000)==0x7ff00000) {
     if ((ux&0x7fffffff)==0x7ff00000)
       __set_errno (EDOM);
-    return x-x;
+    retval = x-x;
+    goto ret;
   }
 
   w=(x<ZERO) ? -x : x;
 
   /* (I) The case abs(x) <= 1.259e-8 */
-  if (w<=g1.d)  return x;
+  if (w<=g1.d) { retval = x; goto ret; }
 
   /* (II) The case 1.259e-8 < abs(x) <= 0.0608 */
   if (w<=g2.d) {
@@ -88,7 +96,7 @@ tan(double x) {
     /* First stage */
     x2 = x*x;
     t2 = x*x2*(d3.d+x2*(d5.d+x2*(d7.d+x2*(d9.d+x2*d11.d))));
-    if ((y=x+(t2-u1.d*t2)) == x+(t2+u1.d*t2))  return y;
+    if ((y=x+(t2-u1.d*t2)) == x+(t2+u1.d*t2)) { retval = y; goto ret; }
 
     /* Second stage */
     c1 = x2*(a15.d+x2*(a17.d+x2*(a19.d+x2*(a21.d+x2*(a23.d+x2*(a25.d+
@@ -108,8 +116,9 @@ tan(double x) {
     MUL2(x2,xx2,c2,cc2,c1,cc1,t1,t2,t3,t4,t5,t6,t7,t8)
     MUL2(x ,zero.d,c1,cc1,c2,cc2,t1,t2,t3,t4,t5,t6,t7,t8)
     ADD2(x    ,zero.d,c2,cc2,c1,cc1,t1,t2)
-    if ((y=c1+(cc1-u2.d*c1)) == c1+(cc1+u2.d*c1))  return y;
-    return tanMp(x);
+    if ((y=c1+(cc1-u2.d*c1)) == c1+(cc1+u2.d*c1)) { retval = y; goto ret; }
+    retval = tanMp(x);
+    goto ret;
   }
 
   /* (III) The case 0.0608 < abs(x) <= 0.787 */
@@ -120,10 +129,10 @@ tan(double x) {
     z = w-xfg[i][0].d;  z2 = z*z;   s = (x<ZERO) ? MONE : ONE;
     pz = z+z*z2*(e0.d+z2*e1.d);
     fi = xfg[i][1].d;   gi = xfg[i][2].d;   t2 = pz*(gi+fi)/(gi-pz);
-    if ((y=fi+(t2-fi*u3.d))==fi+(t2+fi*u3.d))  return (s*y);
+    if ((y=fi+(t2-fi*u3.d))==fi+(t2+fi*u3.d)) { retval = (s*y); goto ret; }
     t3 = (t2<ZERO) ? -t2 : t2;
     t4 = fi*ua3.d+t3*ub3.d;
-    if ((y=fi+(t2-t4))==fi+(t2+t4))  return (s*y);
+    if ((y=fi+(t2-t4))==fi+(t2+t4)) { retval = (s*y); goto ret; }
 
     /* Second stage */
     ffi = xfg[i][3].d;
@@ -141,8 +150,9 @@ tan(double x) {
     SUB2(one.d,zero.d,c3,cc3,c1,cc1,t1,t2)
     DIV2(c2,cc2,c1,cc1,c3,cc3,t1,t2,t3,t4,t5,t6,t7,t8,t9,t10)
 
-    if ((y=c3+(cc3-u4.d*c3))==c3+(cc3+u4.d*c3))  return (s*y);
-    return tanMp(x);
+      if ((y=c3+(cc3-u4.d*c3))==c3+(cc3+u4.d*c3)) { retval = (s*y); goto ret; }
+    retval = tanMp(x);
+    goto ret;
   }
 
   /* (---) The case 0.787 < abs(x) <= 25 */
@@ -160,7 +170,7 @@ tan(double x) {
     else         {ya= a;  yya= da;  sy= ONE;}
 
     /* (IV),(V) The case 0.787 < abs(x) <= 25,    abs(y) <= 1e-7 */
-    if (ya<=gy1.d)  return tanMp(x);
+    if (ya<=gy1.d) { retval = tanMp(x); goto ret; }
 
     /* (VI) The case 0.787 < abs(x) <= 25,    1e-7 < abs(y) <= 0.0608 */
     if (ya<=gy2.d) {
@@ -170,10 +180,10 @@ tan(double x) {
 	/* First stage -cot */
 	EADD(a,t2,b,db)
 	DIV2(one.d,zero.d,b,db,c,dc,t1,t2,t3,t4,t5,t6,t7,t8,t9,t10)
-	if ((y=c+(dc-u6.d*c))==c+(dc+u6.d*c))  return (-y); }
+	if ((y=c+(dc-u6.d*c))==c+(dc+u6.d*c)) { retval = (-y); goto ret; } }
       else {
 	/* First stage tan */
-	if ((y=a+(t2-u5.d*a))==a+(t2+u5.d*a))  return y; }
+	if ((y=a+(t2-u5.d*a))==a+(t2+u5.d*a)) { retval = y; goto ret; } }
       /* Second stage */
       /* Range reduction by algorithm ii */
       t = (x*hpinv.d + toint.d);
@@ -211,11 +221,12 @@ tan(double x) {
       if (n) {
 	/* Second stage -cot */
 	DIV2(one.d,zero.d,c1,cc1,c2,cc2,t1,t2,t3,t4,t5,t6,t7,t8,t9,t10)
-	if ((y=c2+(cc2-u8.d*c2)) == c2+(cc2+u8.d*c2))  return (-y); }
+	if ((y=c2+(cc2-u8.d*c2)) == c2+(cc2+u8.d*c2)) { retval = (-y); goto ret; } }
       else {
 	/* Second stage tan */
-	if ((y=c1+(cc1-u7.d*c1)) == c1+(cc1+u7.d*c1))  return y; }
-      return tanMp(x);
+	if ((y=c1+(cc1-u7.d*c1)) == c1+(cc1+u7.d*c1)) { retval = y; goto ret; } }
+      retval = tanMp(x);
+      goto ret;
     }
 
     /* (VII) The case 0.787 < abs(x) <= 25,    0.0608 < abs(y) <= 0.787 */
@@ -229,17 +240,17 @@ tan(double x) {
     if (n) {
       /* -cot */
       t2 = pz*(fi+gi)/(fi+pz);
-      if ((y=gi-(t2-gi*u10.d))==gi-(t2+gi*u10.d))  return (-sy*y);
+      if ((y=gi-(t2-gi*u10.d))==gi-(t2+gi*u10.d)) { retval = (-sy*y); goto ret; }
       t3 = (t2<ZERO) ? -t2 : t2;
       t4 = gi*ua10.d+t3*ub10.d;
-      if ((y=gi-(t2-t4))==gi-(t2+t4))  return (-sy*y); }
+      if ((y=gi-(t2-t4))==gi-(t2+t4)) { retval = (-sy*y); goto ret; } }
     else   {
       /* tan */
       t2 = pz*(gi+fi)/(gi-pz);
-      if ((y=fi+(t2-fi*u9.d))==fi+(t2+fi*u9.d))  return (sy*y);
+      if ((y=fi+(t2-fi*u9.d))==fi+(t2+fi*u9.d)) { retval = (sy*y); goto ret; }
       t3 = (t2<ZERO) ? -t2 : t2;
       t4 = fi*ua9.d+t3*ub9.d;
-      if ((y=fi+(t2-t4))==fi+(t2+t4))  return (sy*y); }
+      if ((y=fi+(t2-t4))==fi+(t2+t4)) { retval = (sy*y); goto ret; } }
 
     /* Second stage */
     ffi = xfg[i][3].d;
@@ -260,13 +271,14 @@ tan(double x) {
     if (n) {
       /* -cot */
       DIV2(c1,cc1,c2,cc2,c3,cc3,t1,t2,t3,t4,t5,t6,t7,t8,t9,t10)
-      if ((y=c3+(cc3-u12.d*c3))==c3+(cc3+u12.d*c3))  return (-sy*y); }
+      if ((y=c3+(cc3-u12.d*c3))==c3+(cc3+u12.d*c3)) { retval = (-sy*y); goto ret; } }
     else {
       /* tan */
       DIV2(c2,cc2,c1,cc1,c3,cc3,t1,t2,t3,t4,t5,t6,t7,t8,t9,t10)
-      if ((y=c3+(cc3-u11.d*c3))==c3+(cc3+u11.d*c3))  return (sy*y); }
+      if ((y=c3+(cc3-u11.d*c3))==c3+(cc3+u11.d*c3)) { retval = (sy*y); goto ret; } }
 
-    return tanMp(x);
+    retval = tanMp(x);
+    goto ret;
   }
 
   /* (---) The case 25 < abs(x) <= 1e8 */
@@ -288,7 +300,7 @@ tan(double x) {
     else         {ya= a;  yya= da;  sy= ONE;}
 
     /* (+++) The case 25 < abs(x) <= 1e8,    abs(y) <= 1e-7 */
-    if (ya<=gy1.d)  return tanMp(x);
+    if (ya<=gy1.d) { retval = tanMp(x); goto ret; }
 
     /* (VIII) The case 25 < abs(x) <= 1e8,    1e-7 < abs(y) <= 0.0608 */
     if (ya<=gy2.d) {
@@ -298,10 +310,10 @@ tan(double x) {
 	/* First stage -cot */
 	EADD(a,t2,b,db)
 	DIV2(one.d,zero.d,b,db,c,dc,t1,t2,t3,t4,t5,t6,t7,t8,t9,t10)
-	if ((y=c+(dc-u14.d*c))==c+(dc+u14.d*c))  return (-y); }
+	if ((y=c+(dc-u14.d*c))==c+(dc+u14.d*c)) { retval = (-y); goto ret; } }
       else {
 	/* First stage tan */
-	if ((y=a+(t2-u13.d*a))==a+(t2+u13.d*a))  return y; }
+	if ((y=a+(t2-u13.d*a))==a+(t2+u13.d*a)) { retval = y; goto ret; } }
 
       /* Second stage */
       MUL2(a,da,a,da,x2,xx2,t1,t2,t3,t4,t5,t6,t7,t8)
@@ -325,11 +337,12 @@ tan(double x) {
       if (n) {
 	/* Second stage -cot */
 	DIV2(one.d,zero.d,c1,cc1,c2,cc2,t1,t2,t3,t4,t5,t6,t7,t8,t9,t10)
-	if ((y=c2+(cc2-u16.d*c2)) == c2+(cc2+u16.d*c2))  return (-y); }
+	if ((y=c2+(cc2-u16.d*c2)) == c2+(cc2+u16.d*c2)) { retval = (-y); goto ret; } }
       else {
 	/* Second stage tan */
-	if ((y=c1+(cc1-u15.d*c1)) == c1+(cc1+u15.d*c1))  return (y); }
-      return tanMp(x);
+	if ((y=c1+(cc1-u15.d*c1)) == c1+(cc1+u15.d*c1)) { retval = (y); goto ret; } }
+      retval = tanMp(x);
+      goto ret;
     }
 
     /* (IX) The case 25 < abs(x) <= 1e8,    0.0608 < abs(y) <= 0.787 */
@@ -342,17 +355,17 @@ tan(double x) {
     if (n) {
       /* -cot */
       t2 = pz*(fi+gi)/(fi+pz);
-      if ((y=gi-(t2-gi*u18.d))==gi-(t2+gi*u18.d))  return (-sy*y);
+      if ((y=gi-(t2-gi*u18.d))==gi-(t2+gi*u18.d)) { retval = (-sy*y); goto ret; }
       t3 = (t2<ZERO) ? -t2 : t2;
       t4 = gi*ua18.d+t3*ub18.d;
-      if ((y=gi-(t2-t4))==gi-(t2+t4))  return (-sy*y); }
+      if ((y=gi-(t2-t4))==gi-(t2+t4)) { retval = (-sy*y); goto ret; } }
     else   {
       /* tan */
       t2 = pz*(gi+fi)/(gi-pz);
-      if ((y=fi+(t2-fi*u17.d))==fi+(t2+fi*u17.d))  return (sy*y);
+      if ((y=fi+(t2-fi*u17.d))==fi+(t2+fi*u17.d)) { retval = (sy*y); goto ret; }
       t3 = (t2<ZERO) ? -t2 : t2;
       t4 = fi*ua17.d+t3*ub17.d;
-      if ((y=fi+(t2-t4))==fi+(t2+t4))  return (sy*y); }
+      if ((y=fi+(t2-t4))==fi+(t2+t4)) { retval = (sy*y); goto ret; } }
 
     /* Second stage */
     ffi = xfg[i][3].d;
@@ -373,12 +386,13 @@ tan(double x) {
     if (n) {
       /* -cot */
       DIV2(c1,cc1,c2,cc2,c3,cc3,t1,t2,t3,t4,t5,t6,t7,t8,t9,t10)
-      if ((y=c3+(cc3-u20.d*c3))==c3+(cc3+u20.d*c3))  return (-sy*y); }
+      if ((y=c3+(cc3-u20.d*c3))==c3+(cc3+u20.d*c3)) { retval = (-sy*y); goto ret; } }
     else {
       /* tan */
       DIV2(c2,cc2,c1,cc1,c3,cc3,t1,t2,t3,t4,t5,t6,t7,t8,t9,t10)
-      if ((y=c3+(cc3-u19.d*c3))==c3+(cc3+u19.d*c3))  return (sy*y); }
-    return tanMp(x);
+      if ((y=c3+(cc3-u19.d*c3))==c3+(cc3+u19.d*c3)) { retval = (sy*y); goto ret; } }
+    retval = tanMp(x);
+    goto ret;
   }
 
   /* (---) The case 1e8 < abs(x) < 2**1024 */
@@ -389,7 +403,7 @@ tan(double x) {
   else         {ya= a;  yya= da;  sy= ONE;}
 
   /* (+++) The case 1e8 < abs(x) < 2**1024,    abs(y) <= 1e-7 */
-  if (ya<=gy1.d)  return tanMp(x);
+  if (ya<=gy1.d) { retval = tanMp(x); goto ret; }
 
   /* (X) The case 1e8 < abs(x) < 2**1024,    1e-7 < abs(y) <= 0.0608 */
   if (ya<=gy2.d) {
@@ -399,10 +413,10 @@ tan(double x) {
       /* First stage -cot */
       EADD(a,t2,b,db)
       DIV2(one.d,zero.d,b,db,c,dc,t1,t2,t3,t4,t5,t6,t7,t8,t9,t10)
-      if ((y=c+(dc-u22.d*c))==c+(dc+u22.d*c))  return (-y); }
+      if ((y=c+(dc-u22.d*c))==c+(dc+u22.d*c)) { retval = (-y); goto ret; } }
     else {
       /* First stage tan */
-      if ((y=a+(t2-u21.d*a))==a+(t2+u21.d*a))  return y; }
+      if ((y=a+(t2-u21.d*a))==a+(t2+u21.d*a)) { retval = y; goto ret; } }
 
     /* Second stage */
     /* Reduction by algorithm iv */
@@ -431,11 +445,12 @@ tan(double x) {
     if (n) {
       /* Second stage -cot */
       DIV2(one.d,zero.d,c1,cc1,c2,cc2,t1,t2,t3,t4,t5,t6,t7,t8,t9,t10)
-      if ((y=c2+(cc2-u24.d*c2)) == c2+(cc2+u24.d*c2))  return (-y); }
+      if ((y=c2+(cc2-u24.d*c2)) == c2+(cc2+u24.d*c2)) { retval = (-y); goto ret; } }
     else {
       /* Second stage tan */
-      if ((y=c1+(cc1-u23.d*c1)) == c1+(cc1+u23.d*c1))  return y; }
-    return tanMp(x);
+      if ((y=c1+(cc1-u23.d*c1)) == c1+(cc1+u23.d*c1)) { retval = y; goto ret; } }
+    retval = tanMp(x);
+    goto ret;
   }
 
   /* (XI) The case 1e8 < abs(x) < 2**1024,    0.0608 < abs(y) <= 0.787 */
@@ -448,17 +463,17 @@ tan(double x) {
   if (n) {
     /* -cot */
     t2 = pz*(fi+gi)/(fi+pz);
-    if ((y=gi-(t2-gi*u26.d))==gi-(t2+gi*u26.d))  return (-sy*y);
+    if ((y=gi-(t2-gi*u26.d))==gi-(t2+gi*u26.d)) { retval = (-sy*y); goto ret; }
     t3 = (t2<ZERO) ? -t2 : t2;
     t4 = gi*ua26.d+t3*ub26.d;
-    if ((y=gi-(t2-t4))==gi-(t2+t4))  return (-sy*y); }
+    if ((y=gi-(t2-t4))==gi-(t2+t4)) { retval = (-sy*y); goto ret; } }
   else   {
     /* tan */
     t2 = pz*(gi+fi)/(gi-pz);
-    if ((y=fi+(t2-fi*u25.d))==fi+(t2+fi*u25.d))  return (sy*y);
+    if ((y=fi+(t2-fi*u25.d))==fi+(t2+fi*u25.d)) { retval = (sy*y); goto ret; }
     t3 = (t2<ZERO) ? -t2 : t2;
     t4 = fi*ua25.d+t3*ub25.d;
-    if ((y=fi+(t2-t4))==fi+(t2+t4))  return (sy*y); }
+    if ((y=fi+(t2-t4))==fi+(t2+t4)) { retval = (sy*y); goto ret; } }
 
   /* Second stage */
   ffi = xfg[i][3].d;
@@ -479,14 +494,18 @@ tan(double x) {
   if (n) {
     /* -cot */
     DIV2(c1,cc1,c2,cc2,c3,cc3,t1,t2,t3,t4,t5,t6,t7,t8,t9,t10)
-    if ((y=c3+(cc3-u28.d*c3))==c3+(cc3+u28.d*c3))  return (-sy*y); }
+    if ((y=c3+(cc3-u28.d*c3))==c3+(cc3+u28.d*c3)) { retval = (-sy*y); goto ret; } }
   else {
     /* tan */
     DIV2(c2,cc2,c1,cc1,c3,cc3,t1,t2,t3,t4,t5,t6,t7,t8,t9,t10)
-    if ((y=c3+(cc3-u27.d*c3))==c3+(cc3+u27.d*c3))  return (sy*y); }
-  return tanMp(x);
-}
+    if ((y=c3+(cc3-u27.d*c3))==c3+(cc3+u27.d*c3)) { retval = (sy*y); goto ret; } }
+  retval = tanMp(x);
+  goto ret;
 
+ ret:
+  libc_feupdateenv (&env);
+  return retval;
+}
 
 /* multiple precision stage                                              */
 /* Convert x to multi precision number,compute tan(x) by mptan() routine */
diff --git a/sysdeps/x86_64/fpu/libm-test-ulps b/sysdeps/x86_64/fpu/libm-test-ulps
index 74df77ce2a..0185f285a1 100644
--- a/sysdeps/x86_64/fpu/libm-test-ulps
+++ b/sysdeps/x86_64/fpu/libm-test-ulps
@@ -327,6 +327,107 @@ ifloat: 1
 ildouble: 1
 ldouble: 1
 
+# cos_downward
+Test "cos_downward (1) == 0.5403023058681397174009366074429766037323":
+float: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+Test "cos_downward (2) == -0.4161468365471423869975682295007621897660":
+float: 1
+ifloat: 1
+Test "cos_downward (3) == -0.9899924966004454572715727947312613023937":
+float: 1
+ifloat: 1
+Test "cos_downward (4) == -0.6536436208636119146391681830977503814241":
+float: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+Test "cos_downward (5) == 0.2836621854632262644666391715135573083344":
+float: 1
+ifloat: 1
+Test "cos_downward (7) == 0.7539022543433046381411975217191820122183":
+float: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+Test "cos_downward (8) == -0.1455000338086135258688413818311946826093":
+float: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+Test "cos_downward (9) == -0.9111302618846769883682947111811653112463":
+ildouble: 1
+ldouble: 1
+
+# cos_tonearest
+Test "cos_tonearest (7) == 0.7539022543433046381411975217191820122183":
+float: 1
+ifloat: 1
+Test "cos_tonearest (8) == -0.1455000338086135258688413818311946826093":
+ildouble: 1
+ldouble: 1
+Test "cos_tonearest (9) == -0.9111302618846769883682947111811653112463":
+ildouble: 1
+ldouble: 1
+
+# cos_towardzero
+Test "cos_towardzero (1) == 0.5403023058681397174009366074429766037323":
+ildouble: 1
+ldouble: 1
+Test "cos_towardzero (10) == -0.8390715290764524522588639478240648345199":
+ildouble: 1
+ldouble: 1
+Test "cos_towardzero (2) == -0.4161468365471423869975682295007621897660":
+float: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+Test "cos_towardzero (3) == -0.9899924966004454572715727947312613023937":
+float: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+Test "cos_towardzero (5) == 0.2836621854632262644666391715135573083344":
+float: 1
+ifloat: 1
+Test "cos_towardzero (7) == 0.7539022543433046381411975217191820122183":
+float: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+Test "cos_towardzero (8) == -0.1455000338086135258688413818311946826093":
+float: 1
+ifloat: 1
+
+# cos_upward
+Test "cos_upward (10) == -0.8390715290764524522588639478240648345199":
+float: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+Test "cos_upward (2) == -0.4161468365471423869975682295007621897660":
+ildouble: 1
+ldouble: 1
+Test "cos_upward (3) == -0.9899924966004454572715727947312613023937":
+ildouble: 1
+ldouble: 1
+Test "cos_upward (5) == 0.2836621854632262644666391715135573083344":
+ildouble: 1
+ldouble: 1
+Test "cos_upward (6) == 0.9601702866503660205456522979229244054519":
+float: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+Test "cos_upward (7) == 0.7539022543433046381411975217191820122183":
+float: 1
+ifloat: 1
+Test "cos_upward (9) == -0.9111302618846769883682947111811653112463":
+float: 2
+ifloat: 2
+
 # cpow
 Test "Real part of: cpow (0.75 + 1.25 i, 0.0 + 1.0 i) == 0.331825439177608832276067945276730566 + 0.131338600281188544930936345230903032 i":
 float: 1
@@ -831,6 +932,107 @@ Test "log1p (-0.25) == -0.287682072451780927439219005993827432":
 float: 1
 ifloat: 1
 
+# sin_downward
+Test "sin_downward (1) == 0.8414709848078965066525023216302989996226":
+ildouble: 1
+ldouble: 1
+Test "sin_downward (10) == -0.5440211108893698134047476618513772816836":
+float: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+Test "sin_downward (3) == 0.1411200080598672221007448028081102798469":
+float: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+Test "sin_downward (4) == -0.7568024953079282513726390945118290941359":
+ildouble: 1
+ldouble: 1
+Test "sin_downward (5) == -0.9589242746631384688931544061559939733525":
+float: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+Test "sin_downward (6) == -0.2794154981989258728115554466118947596280":
+float: 1
+ifloat: 1
+Test "sin_downward (7) == 0.6569865987187890903969990915936351779369":
+ildouble: 1
+ldouble: 1
+Test "sin_downward (8) == 0.9893582466233817778081235982452886721164":
+ildouble: 1
+ldouble: 1
+Test "sin_downward (9) == 0.4121184852417565697562725663524351793439":
+ildouble: 1
+ldouble: 1
+
+# sin_tonearest
+Test "sin_tonearest (1) == 0.8414709848078965066525023216302989996226":
+float: 1
+ifloat: 1
+Test "sin_tonearest (10) == -0.5440211108893698134047476618513772816836":
+ildouble: 1
+ldouble: 1
+Test "sin_tonearest (4) == -0.7568024953079282513726390945118290941359":
+ildouble: 1
+ldouble: 1
+Test "sin_tonearest (9) == 0.4121184852417565697562725663524351793439":
+ildouble: 1
+ldouble: 1
+
+# sin_towardzero
+Test "sin_towardzero (1) == 0.8414709848078965066525023216302989996226":
+float: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+Test "sin_towardzero (10) == -0.5440211108893698134047476618513772816836":
+float: 1
+ifloat: 1
+Test "sin_towardzero (3) == 0.1411200080598672221007448028081102798469":
+ildouble: 1
+ldouble: 1
+Test "sin_towardzero (4) == -0.7568024953079282513726390945118290941359":
+float: 1
+ifloat: 1
+Test "sin_towardzero (5) == -0.9589242746631384688931544061559939733525":
+float: 1
+ifloat: 1
+Test "sin_towardzero (6) == -0.2794154981989258728115554466118947596280":
+ildouble: 1
+ldouble: 1
+Test "sin_towardzero (7) == 0.6569865987187890903969990915936351779369":
+ildouble: 1
+ldouble: 1
+Test "sin_towardzero (8) == 0.9893582466233817778081235982452886721164":
+ildouble: 1
+ldouble: 1
+Test "sin_towardzero (9) == 0.4121184852417565697562725663524351793439":
+float: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+
+# sin_upward
+Test "sin_upward (1) == 0.8414709848078965066525023216302989996226":
+float: 1
+ifloat: 1
+Test "sin_upward (2) == 0.9092974268256816953960198659117448427023":
+float: 2
+ifloat: 2
+ildouble: 1
+ldouble: 1
+Test "sin_upward (4) == -0.7568024953079282513726390945118290941359":
+float: 1
+ifloat: 1
+Test "sin_upward (6) == -0.2794154981989258728115554466118947596280":
+ildouble: 1
+ldouble: 1
+Test "sin_upward (9) == 0.4121184852417565697562725663524351793439":
+float: 1
+ifloat: 1
+
 # sincos
 Test "sincos (0.80190127184058835, &sin_res, &cos_res) puts 0.69534156199418473 in cos_res":
 double: 1
@@ -868,6 +1070,112 @@ Test "tan (pi/4) == 1":
 double: 1
 idouble: 1
 
+# tan_downward
+Test "tan_downward (1) == 1.5574077246549022305069748074583601730873":
+float: 1
+ifloat: 1
+Test "tan_downward (10) == 0.6483608274590866712591249330098086768169":
+float: 1
+ifloat: 1
+Test "tan_downward (2) == -2.1850398632615189916433061023136825434320":
+float: 1
+ifloat: 1
+Test "tan_downward (4) == 1.1578212823495775831373424182673239231198":
+ildouble: 1
+ldouble: 1
+Test "tan_downward (5) == -3.3805150062465856369827058794473439087096":
+ildouble: 1
+ldouble: 1
+Test "tan_downward (6) == -0.2910061913847491570536995888681755428312":
+float: 1
+ifloat: 1
+Test "tan_downward (8) == -6.7997114552203786999252627596086333648814":
+float: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+Test "tan_downward (9) == -0.4523156594418098405903708757987855343087":
+float: 1
+ifloat: 1
+
+# tan_tonearest
+Test "tan_tonearest (6) == -0.2910061913847491570536995888681755428312":
+ildouble: 1
+ldouble: 1
+Test "tan_tonearest (8) == -6.7997114552203786999252627596086333648814":
+ildouble: 1
+ldouble: 1
+Test "tan_tonearest (9) == -0.4523156594418098405903708757987855343087":
+ildouble: 1
+ldouble: 1
+
+# tan_towardzero
+Test "tan_towardzero (10) == 0.6483608274590866712591249330098086768169":
+float: 1
+ifloat: 1
+Test "tan_towardzero (2) == -2.1850398632615189916433061023136825434320":
+ildouble: 1
+ldouble: 1
+Test "tan_towardzero (3) == -0.1425465430742778052956354105339134932261":
+float: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+Test "tan_towardzero (4) == 1.1578212823495775831373424182673239231198":
+float: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+Test "tan_towardzero (5) == -3.3805150062465856369827058794473439087096":
+float: 1
+ifloat: 1
+Test "tan_towardzero (6) == -0.2910061913847491570536995888681755428312":
+ildouble: 1
+ldouble: 1
+Test "tan_towardzero (8) == -6.7997114552203786999252627596086333648814":
+ildouble: 2
+ldouble: 2
+Test "tan_towardzero (9) == -0.4523156594418098405903708757987855343087":
+float: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+
+# tan_upward
+Test "tan_upward (1) == 1.5574077246549022305069748074583601730873":
+float: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+Test "tan_upward (10) == 0.6483608274590866712591249330098086768169":
+float: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+Test "tan_upward (2) == -2.1850398632615189916433061023136825434320":
+ildouble: 1
+ldouble: 1
+Test "tan_upward (3) == -0.1425465430742778052956354105339134932261":
+float: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+Test "tan_upward (5) == -3.3805150062465856369827058794473439087096":
+float: 1
+ifloat: 1
+Test "tan_upward (6) == -0.2910061913847491570536995888681755428312":
+ildouble: 1
+ldouble: 1
+Test "tan_upward (7) == 0.8714479827243187364564508896003135663222":
+ildouble: 1
+ldouble: 1
+Test "tan_upward (8) == -6.7997114552203786999252627596086333648814":
+ildouble: 2
+ldouble: 2
+Test "tan_upward (9) == -0.4523156594418098405903708757987855343087":
+ildouble: 1
+ldouble: 1
+
 # tgamma
 Test "tgamma (-0.5) == -2 sqrt (pi)":
 double: 1
@@ -1214,6 +1522,30 @@ ifloat: 1
 ildouble: 1
 ldouble: 1
 
+Function: "cos_downward":
+float: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+
+Function: "cos_tonearest":
+float: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+
+Function: "cos_towardzero":
+float: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+
+Function: "cos_upward":
+float: 2
+ifloat: 2
+ildouble: 1
+ldouble: 1
+
 Function: Real part of "cpow":
 double: 2
 float: 5
@@ -1386,6 +1718,30 @@ Function: "log1p":
 float: 1
 ifloat: 1
 
+Function: "sin_downward":
+float: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+
+Function: "sin_tonearest":
+float: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+
+Function: "sin_towardzero":
+float: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+
+Function: "sin_upward":
+float: 2
+ifloat: 2
+ildouble: 1
+ldouble: 1
+
 Function: "sincos":
 double: 1
 float: 1
@@ -1402,6 +1758,28 @@ Function: "tan":
 double: 1
 idouble: 1
 
+Function: "tan_downward":
+float: 1
+ifloat: 1
+ildouble: 1
+ldouble: 1
+
+Function: "tan_tonearest":
+ildouble: 1
+ldouble: 1
+
+Function: "tan_towardzero":
+float: 1
+ifloat: 1
+ildouble: 2
+ldouble: 2
+
+Function: "tan_upward":
+float: 1
+ifloat: 1
+ildouble: 2
+ldouble: 2
+
 Function: "tgamma":
 double: 1
 float: 1