about summary refs log tree commit diff
path: root/sysdeps/libm-ieee754
diff options
context:
space:
mode:
Diffstat (limited to 'sysdeps/libm-ieee754')
-rw-r--r--sysdeps/libm-ieee754/s_ccosh.c15
-rw-r--r--sysdeps/libm-ieee754/s_ccoshf.c15
-rw-r--r--sysdeps/libm-ieee754/s_ccoshl.c15
-rw-r--r--sysdeps/libm-ieee754/s_cexp.c23
-rw-r--r--sysdeps/libm-ieee754/s_cexpf.c19
-rw-r--r--sysdeps/libm-ieee754/s_cexpl.c19
-rw-r--r--sysdeps/libm-ieee754/s_cosl.c7
-rw-r--r--sysdeps/libm-ieee754/s_cproj.c49
-rw-r--r--sysdeps/libm-ieee754/s_cprojf.c45
-rw-r--r--sysdeps/libm-ieee754/s_cprojl.c46
-rw-r--r--sysdeps/libm-ieee754/s_csinh.c17
-rw-r--r--sysdeps/libm-ieee754/s_csinhf.c17
-rw-r--r--sysdeps/libm-ieee754/s_csinhl.c15
-rw-r--r--sysdeps/libm-ieee754/s_ctan.c10
-rw-r--r--sysdeps/libm-ieee754/s_ctanf.c10
-rw-r--r--sysdeps/libm-ieee754/s_ctanh.c10
-rw-r--r--sysdeps/libm-ieee754/s_ctanhf.c10
-rw-r--r--sysdeps/libm-ieee754/s_ctanhl.c10
-rw-r--r--sysdeps/libm-ieee754/s_ctanl.c10
-rw-r--r--sysdeps/libm-ieee754/s_roundtol.c4
-rw-r--r--sysdeps/libm-ieee754/s_roundtoll.c4
-rw-r--r--sysdeps/libm-ieee754/s_sincos.c78
-rw-r--r--sysdeps/libm-ieee754/s_sincosf.c74
-rw-r--r--sysdeps/libm-ieee754/s_sincosl.c74
-rw-r--r--sysdeps/libm-ieee754/s_sinl.c7
25 files changed, 530 insertions, 73 deletions
diff --git a/sysdeps/libm-ieee754/s_ccosh.c b/sysdeps/libm-ieee754/s_ccosh.c
index b9d7b82f5e..fa958f491b 100644
--- a/sysdeps/libm-ieee754/s_ccosh.c
+++ b/sysdeps/libm-ieee754/s_ccosh.c
@@ -40,9 +40,12 @@ __ccosh (__complex__ double x)
 	{
 	  /* Imaginary part is finite.  */
 	  double cosh_val = __ieee754_cosh (__real__ x);
+	  double sinix, cosix;
 
-	  __real__ retval = cosh_val * __cos (__imag__ x);
-	  __imag__ retval = cosh_val * __sin (__imag__ x);
+	  __sincos (__imag__ x, &sinix, &cosix);
+
+	  __real__ retval = cosh_val * cosix;
+	  __imag__ retval = cosh_val * sinix;
 	}
       else
 	{
@@ -62,8 +65,12 @@ __ccosh (__complex__ double x)
       else if (icls > FP_ZERO)
 	{
 	  /* Imaginary part is finite.  */
-	  __real__ retval = __copysign (HUGE_VAL, __cos (__imag__ x));
-	  __imag__ retval = __copysign (HUGE_VAL, __sin (__imag__ x));
+	  double sinix, cosix;
+
+	  __sincos (__imag__ x, &sinix, &cosix);
+
+	  __real__ retval = __copysign (HUGE_VAL, cosix);
+	  __imag__ retval = __copysign (HUGE_VAL, sinix);
 	}
       else
 	{
diff --git a/sysdeps/libm-ieee754/s_ccoshf.c b/sysdeps/libm-ieee754/s_ccoshf.c
index 758ec5b579..aeeacbaed0 100644
--- a/sysdeps/libm-ieee754/s_ccoshf.c
+++ b/sysdeps/libm-ieee754/s_ccoshf.c
@@ -40,9 +40,12 @@ __ccoshf (__complex__ float x)
 	{
 	  /* Imaginary part is finite.  */
 	  float cosh_val = __ieee754_coshf (__real__ x);
+	  float sinix, cosix;
 
-	  __real__ retval = cosh_val * __cosf (__imag__ x);
-	  __imag__ retval = cosh_val * __sinf (__imag__ x);
+	  __sincosf (__imag__ x, &sinix, &cosix);
+
+	  __real__ retval = cosh_val * cosix;
+	  __imag__ retval = cosh_val * sinix;
 	}
       else
 	{
@@ -62,8 +65,12 @@ __ccoshf (__complex__ float x)
       else if (icls > FP_ZERO)
 	{
 	  /* Imaginary part is finite.  */
-	  __real__ retval = __copysignf (HUGE_VALF, __cosf (__imag__ x));
-	  __imag__ retval = __copysignf (HUGE_VALF, __sinf (__imag__ x));
+	  float sinix, cosix;
+
+	  __sincosf (__imag__ x, &sinix, &cosix);
+
+	  __real__ retval = __copysignf (HUGE_VALF, cosix);
+	  __imag__ retval = __copysignf (HUGE_VALF, sinix);
 	}
       else
 	{
diff --git a/sysdeps/libm-ieee754/s_ccoshl.c b/sysdeps/libm-ieee754/s_ccoshl.c
index 5e8c399fb2..9937ba1904 100644
--- a/sysdeps/libm-ieee754/s_ccoshl.c
+++ b/sysdeps/libm-ieee754/s_ccoshl.c
@@ -40,9 +40,12 @@ __ccoshl (__complex__ long double x)
 	{
 	  /* Imaginary part is finite.  */
 	  long double cosh_val = __ieee754_coshl (__real__ x);
+	  long double sinix, cosix;
 
-	  __real__ retval = cosh_val * __cosl (__imag__ x);
-	  __imag__ retval = cosh_val * __sinl (__imag__ x);
+	  __sincosl (__imag__ x, &sinix, &cosix);
+
+	  __real__ retval = cosh_val * cosix;
+	  __imag__ retval = cosh_val * sinix;
 	}
       else
 	{
@@ -62,8 +65,12 @@ __ccoshl (__complex__ long double x)
       else if (icls > FP_ZERO)
 	{
 	  /* Imaginary part is finite.  */
-	  __real__ retval = __copysignl (HUGE_VALL, __cosl (__imag__ x));
-	  __imag__ retval = __copysignl (HUGE_VALL, __sinl (__imag__ x));
+	  long double sinix, cosix;
+
+	  __sincosl (__imag__ x, &sinix, &cosix);
+
+	  __real__ retval = __copysignl (HUGE_VALL, cosix);
+	  __imag__ retval = __copysignl (HUGE_VALL, sinix);
 	}
       else
 	{
diff --git a/sysdeps/libm-ieee754/s_cexp.c b/sysdeps/libm-ieee754/s_cexp.c
index b99b042d78..5e68f585f7 100644
--- a/sysdeps/libm-ieee754/s_cexp.c
+++ b/sysdeps/libm-ieee754/s_cexp.c
@@ -1,4 +1,4 @@
-/* Return value of complex exponential function for float complex value.
+/* Return value of complex exponential function for double complex value.
    Copyright (C) 1997 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997.
@@ -21,17 +21,23 @@
 #include <complex.h>
 #include <math.h>
 
+#include "math_private.h"
+
 
 __complex__ double
 __cexp (__complex__ double x)
 {
   __complex__ double retval;
+  int rcls = fpclassify (__real__ x);
+  int icls = fpclassify (__imag__ x);
 
-  if (isfinite (__real__ x))
+  if (rcls >= FP_ZERO)
     {
-      if (isfinite (__imag__ x))
+      /* Real part is finite.  */
+      if (icls >= FP_ZERO)
 	{
-	  double exp_val = __exp (__real__ x);
+	  /* Imaginary part is finite.  */
+	  double exp_val = __ieee754_exp (__real__ x);
 
 	  if (isfinite (exp_val))
 	    {
@@ -52,14 +58,17 @@ __cexp (__complex__ double x)
 	  __imag__ retval = __nan ("");
 	}
     }
-  else if (__isinf (__real__ x))
+  else if (rcls == FP_INFINITE)
     {
-      if (isfinite (__imag__ x))
+      /* Real part is infinite.  */
+      if (icls >= FP_ZERO)
 	{
+	  /* Imaginary part is finite.  */
 	  double value = signbit (__real__ x) ? 0.0 : HUGE_VAL;
 
-	  if (__imag__ x == 0.0)
+	  if (icls == FP_ZERO)
 	    {
+	      /* Imaginary part is 0.0.  */
 	      __real__ retval = value;
 	      __imag__ retval = __imag__ x;
 	    }
diff --git a/sysdeps/libm-ieee754/s_cexpf.c b/sysdeps/libm-ieee754/s_cexpf.c
index 0d4372103b..99f33dc873 100644
--- a/sysdeps/libm-ieee754/s_cexpf.c
+++ b/sysdeps/libm-ieee754/s_cexpf.c
@@ -38,16 +38,19 @@ __cexpf (__complex__ float x)
 	{
 	  /* Imaginary part is finite.  */
 	  float exp_val = __ieee754_expf (__real__ x);
+	  float sinix, cosix;
+
+	  __sincosf (__imag__ x, &sinix, &cosix);
 
 	  if (isfinite (exp_val))
 	    {
-	      __real__ retval = exp_val * __cosf (__imag__ x);
-	      __imag__ retval = exp_val * __sinf (__imag__ x);
+	      __real__ retval = exp_val * cosix;
+	      __imag__ retval = exp_val * sinix;
 	    }
 	  else
 	    {
-	      __real__ retval = __copysignf (exp_val, __cosf (__imag__ x));
-	      __imag__ retval = __copysignf (exp_val, __sinf (__imag__ x));
+	      __real__ retval = __copysignf (exp_val, cosix);
+	      __imag__ retval = __copysignf (exp_val, sinix);
 	    }
 	}
       else
@@ -74,8 +77,12 @@ __cexpf (__complex__ float x)
 	    }
 	  else
 	    {
-	      __real__ retval = __copysignf (value, __cosf (__imag__ x));
-	      __imag__ retval = __copysignf (value, __sinf (__imag__ x));
+	      float sinix, cosix;
+
+	      __sincosf (__imag__ x, &sinix, &cosix);
+
+	      __real__ retval = __copysignf (value, cosix);
+	      __imag__ retval = __copysignf (value, sinix);
 	    }
 	}
       else if (signbit (__real__ x) == 0)
diff --git a/sysdeps/libm-ieee754/s_cexpl.c b/sysdeps/libm-ieee754/s_cexpl.c
index ac27e1eeb8..1b97dba74d 100644
--- a/sysdeps/libm-ieee754/s_cexpl.c
+++ b/sysdeps/libm-ieee754/s_cexpl.c
@@ -38,16 +38,19 @@ __cexpl (__complex__ long double x)
 	{
 	  /* Imaginary part is finite.  */
 	  long double exp_val = __ieee754_expl (__real__ x);
+	  long double sinix, cosix;
+
+	  __sincosl (__imag__ x, &sinix, &cosix);
 
 	  if (isfinite (exp_val))
 	    {
-	      __real__ retval = exp_val * __cosl (__imag__ x);
-	      __imag__ retval = exp_val * __sinl (__imag__ x);
+	      __real__ retval = exp_val * cosix;
+	      __imag__ retval = exp_val * sinix;
 	    }
 	  else
 	    {
-	      __real__ retval = __copysignl (exp_val, __cosl (__imag__ x));
-	      __imag__ retval = __copysignl (exp_val, __sinl (__imag__ x));
+	      __real__ retval = __copysignl (exp_val, cosix);
+	      __imag__ retval = __copysignl (exp_val, sinix);
 	    }
 	}
       else
@@ -74,8 +77,12 @@ __cexpl (__complex__ long double x)
 	    }
 	  else
 	    {
-	      __real__ retval = __copysignl (value, __cosl (__imag__ x));
-	      __imag__ retval = __copysignl (value, __sinl (__imag__ x));
+	      long double sinix, cosix;
+
+	      __sincosl (__imag__ x, &sinix, &cosix);
+
+	      __real__ retval = __copysignl (value, cosix);
+	      __imag__ retval = __copysignl (value, sinix);
 	    }
 	}
       else if (signbit (__real__ x) == 0)
diff --git a/sysdeps/libm-ieee754/s_cosl.c b/sysdeps/libm-ieee754/s_cosl.c
index 0e7a06d8ba..9765f7fd4e 100644
--- a/sysdeps/libm-ieee754/s_cosl.c
+++ b/sysdeps/libm-ieee754/s_cosl.c
@@ -60,14 +60,15 @@ static char rcsid[] = "$NetBSD: $";
 #endif
 {
 	long double y[2],z=0.0;
-	int32_t n, se;
+	int32_t n, se, i0, i1;
 
     /* High word of x. */
-	GET_LDOUBLE_EXP(se,x);
+	GET_LDOUBLE_WORDS(se,i0,i1,x);
 
     /* |x| ~< pi/4 */
 	se &= 0x7fff;
-	if(ix <= 0x3ffe) return __kernel_cosl(x,z);
+	if(se < 0x3ffe || (se == 0x3ffe && i0 <= 0xc90fdaa2))
+	  return __kernel_cosl(x,z);
 
     /* cos(Inf or NaN) is NaN */
 	else if (se==0x7fff) return x-x;
diff --git a/sysdeps/libm-ieee754/s_cproj.c b/sysdeps/libm-ieee754/s_cproj.c
new file mode 100644
index 0000000000..8ad27c0e5b
--- /dev/null
+++ b/sysdeps/libm-ieee754/s_cproj.c
@@ -0,0 +1,49 @@
+/* Compute projection of complex double value to Riemann sphere.
+   Copyright (C) 1997 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Library General Public License as
+   published by the Free Software Foundation; either version 2 of the
+   License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Library General Public License for more details.
+
+   You should have received a copy of the GNU Library General Public
+   License along with the GNU C Library; see the file COPYING.LIB.  If not,
+   write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+   Boston, MA 02111-1307, USA.  */
+
+#include <complex.h>
+#include <math.h>
+
+
+__complex__ double
+__cproj (__complex__ double x)
+{
+  __complex__ double res;
+
+  if (!finite (__real__ x) || !finite (__imag__ x))
+    {
+      __real__ res = INFINITY;
+      __imag__ res = __copysign (0.0, __imag__ x);
+    }
+  else
+    {
+      double den = __real__ x * __real__ x + __imag__ x * __imag__ x + 1.0;
+
+      __real__ res = (2.0 * __real__ x) / den;
+      __imag__ res = (2.0 * __imag__ x) / den;
+    }
+
+  return res;
+}
+weak_alias (__cproj, cproj)
+#ifdef NO_LONG_DOUBLE
+strong_alias (__cproj, __cprojl)
+weak_alias (__cproj, cprojl)
+#endif
diff --git a/sysdeps/libm-ieee754/s_cprojf.c b/sysdeps/libm-ieee754/s_cprojf.c
new file mode 100644
index 0000000000..8ee61c727c
--- /dev/null
+++ b/sysdeps/libm-ieee754/s_cprojf.c
@@ -0,0 +1,45 @@
+/* Compute projection of complex float value to Riemann sphere.
+   Copyright (C) 1997 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Library General Public License as
+   published by the Free Software Foundation; either version 2 of the
+   License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Library General Public License for more details.
+
+   You should have received a copy of the GNU Library General Public
+   License along with the GNU C Library; see the file COPYING.LIB.  If not,
+   write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+   Boston, MA 02111-1307, USA.  */
+
+#include <complex.h>
+#include <math.h>
+
+
+__complex__ float
+__cprojf (__complex__ float x)
+{
+  __complex__ float res;
+
+  if (!finite (__real__ x) || !finite (__imag__ x))
+    {
+      __real__ res = INFINITY;
+      __imag__ res = __copysignf (0.0, __imag__ x);
+    }
+  else
+    {
+      float den = __real__ x * __real__ x + __imag__ x * __imag__ x + 1.0;
+
+      __real__ res = (2.0 * __real__ x) / den;
+      __imag__ res = (2.0 * __imag__ x) / den;
+    }
+
+  return res;
+}
+weak_alias (__cprojf, cprojf)
diff --git a/sysdeps/libm-ieee754/s_cprojl.c b/sysdeps/libm-ieee754/s_cprojl.c
new file mode 100644
index 0000000000..34298e1f25
--- /dev/null
+++ b/sysdeps/libm-ieee754/s_cprojl.c
@@ -0,0 +1,46 @@
+/* Compute projection of complex long double value to Riemann sphere.
+   Copyright (C) 1997 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Library General Public License as
+   published by the Free Software Foundation; either version 2 of the
+   License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Library General Public License for more details.
+
+   You should have received a copy of the GNU Library General Public
+   License along with the GNU C Library; see the file COPYING.LIB.  If not,
+   write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+   Boston, MA 02111-1307, USA.  */
+
+#include <complex.h>
+#include <math.h>
+
+
+__complex__ long double
+__cprojl (__complex__ long double x)
+{
+  __complex__ long double res;
+
+  if (!finite (__real__ x) || !finite (__imag__ x))
+    {
+      __real__ res = INFINITY;
+      __imag__ res = __copysignl (0.0, __imag__ x);
+    }
+  else
+    {
+      long double den = (__real__ x * __real__ x + __imag__ x * __imag__ x
+			 + 1.0);
+
+      __real__ res = (2.0 * __real__ x) / den;
+      __imag__ res = (2.0 * __imag__ x) / den;
+    }
+
+  return res;
+}
+weak_alias (__cprojl, cprojl)
diff --git a/sysdeps/libm-ieee754/s_csinh.c b/sysdeps/libm-ieee754/s_csinh.c
index 05cec85e7c..98f06a558f 100644
--- a/sysdeps/libm-ieee754/s_csinh.c
+++ b/sysdeps/libm-ieee754/s_csinh.c
@@ -40,10 +40,13 @@ __csinh (__complex__ double x)
       if (icls >= FP_ZERO)
 	{
 	  /* Imaginary part is finite.  */
-	   double sinh_val = __ieee754_sinh (__real__ x);
+	  double sinh_val = __ieee754_sinh (__real__ x);
+	  double sinix, cosix;
 
-	  __real__ retval = sinh_val * __cos (__imag__ x);
-	  __imag__ retval = sinh_val * __sin (__imag__ x);
+	  __sincos (__imag__ x, &sinix, &cosix);
+
+	  __real__ retval = sinh_val * cosix;
+	  __imag__ retval = sinh_val * sinix;
 
 	  if (negate)
 	    __real__ retval = -__real__ retval;
@@ -75,8 +78,12 @@ __csinh (__complex__ double x)
       else if (icls > FP_ZERO)
 	{
 	  /* Imaginary part is finite.  */
-	  __real__ retval = __copysign (HUGE_VAL, __cos (__imag__ x));
-	  __imag__ retval = __copysign (HUGE_VAL, __sin (__imag__ x));
+	  double sinix, cosix;
+
+	  __sincos (__imag__ x, &sinix, &cosix);
+
+	  __real__ retval = __copysign (HUGE_VAL, cosix);
+	  __imag__ retval = __copysign (HUGE_VAL, sinix);
 
 	  if (negate)
 	    __real__ retval = -__real__ retval;
diff --git a/sysdeps/libm-ieee754/s_csinhf.c b/sysdeps/libm-ieee754/s_csinhf.c
index 93f83cf7b6..c644d3a5e8 100644
--- a/sysdeps/libm-ieee754/s_csinhf.c
+++ b/sysdeps/libm-ieee754/s_csinhf.c
@@ -40,10 +40,13 @@ __csinhf (__complex__ float x)
       if (icls >= FP_ZERO)
 	{
 	  /* Imaginary part is finite.  */
-	   float sinh_val = __ieee754_sinhf (__real__ x);
+	  float sinh_val = __ieee754_sinhf (__real__ x);
+	  float sinix, cosix;
 
-	  __real__ retval = sinh_val * __cosf (__imag__ x);
-	  __imag__ retval = sinh_val * __sinf (__imag__ x);
+	  __sincosf (__imag__ x, &sinix, &cosix);
+
+	  __real__ retval = sinh_val * cosix;
+	  __imag__ retval = sinh_val * sinix;
 
 	  if (negate)
 	    __real__ retval = -__real__ retval;
@@ -75,8 +78,12 @@ __csinhf (__complex__ float x)
       else if (icls > FP_ZERO)
 	{
 	  /* Imaginary part is finite.  */
-	  __real__ retval = __copysignf (HUGE_VALF, __cosf (__imag__ x));
-	  __imag__ retval = __copysignf (HUGE_VALF, __sinf (__imag__ x));
+	  float sinix, cosix;
+
+	  __sincosf (__imag__ x, &sinix, &cosix);
+
+	  __real__ retval = __copysignf (HUGE_VALF, cosix);
+	  __imag__ retval = __copysignf (HUGE_VALF, sinix);
 
 	  if (negate)
 	    __real__ retval = -__real__ retval;
diff --git a/sysdeps/libm-ieee754/s_csinhl.c b/sysdeps/libm-ieee754/s_csinhl.c
index 8388a40b46..4bb9e63680 100644
--- a/sysdeps/libm-ieee754/s_csinhl.c
+++ b/sysdeps/libm-ieee754/s_csinhl.c
@@ -41,9 +41,12 @@ __csinhl (__complex__ long double x)
 	{
 	  /* Imaginary part is finite.  */
 	  long double sinh_val = __ieee754_sinhl (__real__ x);
+	  long double sinix, cosix;
 
-	  __real__ retval = sinh_val * __cosl (__imag__ x);
-	  __imag__ retval = sinh_val * __sinl (__imag__ x);
+	  __sincosl (__imag__ x, &sinix, &cosix);
+
+	  __real__ retval = sinh_val * cosix;
+	  __imag__ retval = sinh_val * sinix;
 
 	  if (negate)
 	    __real__ retval = -__real__ retval;
@@ -75,8 +78,12 @@ __csinhl (__complex__ long double x)
       else if (icls > FP_ZERO)
 	{
 	  /* Imaginary part is finite.  */
-	  __real__ retval = __copysignl (HUGE_VALL, __cosl (__imag__ x));
-	  __imag__ retval = __copysignl (HUGE_VALL, __sinl (__imag__ x));
+	  long double sinix, cosix;
+
+	  __sincosl (__imag__ x, &sinix, &cosix);
+
+	  __real__ retval = __copysignl (HUGE_VALL, cosix);
+	  __imag__ retval = __copysignl (HUGE_VALL, sinix);
 
 	  if (negate)
 	    __real__ retval = -__real__ retval;
diff --git a/sysdeps/libm-ieee754/s_ctan.c b/sysdeps/libm-ieee754/s_ctan.c
index f448395c7e..069b96c1d6 100644
--- a/sysdeps/libm-ieee754/s_ctan.c
+++ b/sysdeps/libm-ieee754/s_ctan.c
@@ -48,10 +48,14 @@ __ctan (__complex__ double x)
     }
   else
     {
-      double den = (__cos (2.0 * __real__ x)
-		    + __ieee754_cosh (2.0 * __imag__ x));
+      double sin2rx, cos2rx;
+      double den;
 
-      __real__ res = __sin (2.0 * __real__ x) / den;
+      __sincos (2.0 * __real__ x, &sin2rx, &cos2rx);
+
+      den = cos2rx + __ieee754_cosh (2.0 * __imag__ x);
+
+      __real__ res = sin2rx / den;
       __imag__ res = __ieee754_sinh (2.0 * __imag__ x) / den;
     }
 
diff --git a/sysdeps/libm-ieee754/s_ctanf.c b/sysdeps/libm-ieee754/s_ctanf.c
index 99011fa41d..1c6fdca81d 100644
--- a/sysdeps/libm-ieee754/s_ctanf.c
+++ b/sysdeps/libm-ieee754/s_ctanf.c
@@ -48,10 +48,14 @@ __ctanf (__complex__ float x)
     }
   else
     {
-      float den = (__cosf (2.0 * __real__ x)
-		   + __ieee754_coshf (2.0 * __imag__ x));
+      float sin2rx, cos2rx;
+      float den;
 
-      __real__ res = __sinf (2.0 * __real__ x) / den;
+      __sincosf (2.0 * __real__ x, &sin2rx, &cos2rx);
+
+      den = cos2rx + __ieee754_coshf (2.0 * __imag__ x);
+
+      __real__ res = sin2rx / den;
       __imag__ res = __ieee754_sinhf (2.0 * __imag__ x) / den;
     }
 
diff --git a/sysdeps/libm-ieee754/s_ctanh.c b/sysdeps/libm-ieee754/s_ctanh.c
index 7c9b3197ef..a16f9c8d02 100644
--- a/sysdeps/libm-ieee754/s_ctanh.c
+++ b/sysdeps/libm-ieee754/s_ctanh.c
@@ -48,11 +48,15 @@ __ctanh (__complex__ double x)
     }
   else
     {
-      double den = (__ieee754_cosh (2.0 * __real__ x)
-		    + __cos (2.0 * __imag__ x));
+      double sin2ix, cos2ix;
+      double den;
+
+      __sincos (2.0 * __imag__ x, &sin2ix, &cos2ix);
+
+      den = (__ieee754_cosh (2.0 * __real__ x) + cos2ix);
 
       __real__ res = __ieee754_sinh (2.0 * __real__ x) / den;
-      __imag__ res = __sin (2.0 * __imag__ x) / den;
+      __imag__ res = sin2ix / den;
     }
 
   return res;
diff --git a/sysdeps/libm-ieee754/s_ctanhf.c b/sysdeps/libm-ieee754/s_ctanhf.c
index 1bdbc0fdc5..45548d518c 100644
--- a/sysdeps/libm-ieee754/s_ctanhf.c
+++ b/sysdeps/libm-ieee754/s_ctanhf.c
@@ -48,11 +48,15 @@ __ctanhf (__complex__ float x)
     }
   else
     {
-      float den = (__ieee754_coshf (2.0 * __real__ x)
-		   + __cosf (2.0 * __imag__ x));
+      float sin2ix, cos2ix;
+      float den;
+
+      __sincosf (2.0 * __imag__ x, &sin2ix, &cos2ix);
+
+      den = (__ieee754_coshf (2.0 * __real__ x) + cos2ix);
 
       __real__ res = __ieee754_sinhf (2.0 * __real__ x) / den;
-      __imag__ res = __sinf (2.0 * __imag__ x) / den;
+      __imag__ res = sin2ix / den;
     }
 
   return res;
diff --git a/sysdeps/libm-ieee754/s_ctanhl.c b/sysdeps/libm-ieee754/s_ctanhl.c
index b34aeb77dd..5c466167a6 100644
--- a/sysdeps/libm-ieee754/s_ctanhl.c
+++ b/sysdeps/libm-ieee754/s_ctanhl.c
@@ -48,11 +48,15 @@ __ctanhl (__complex__ long double x)
     }
   else
     {
-      long double den = (__ieee754_coshl (2.0 * __real__ x)
-			 + __cosl (2.0 * __imag__ x));
+      long double sin2ix, cos2ix;
+      long double den;
+
+      __sincosl (2.0 * __imag__ x, &sin2ix, &cos2ix);
+
+      den = (__ieee754_coshl (2.0 * __real__ x) + cos2ix);
 
       __real__ res = __ieee754_sinhl (2.0 * __real__ x) / den;
-      __imag__ res = __sinl (2.0 * __imag__ x) / den;
+      __imag__ res = sin2ix / den;
     }
 
   return res;
diff --git a/sysdeps/libm-ieee754/s_ctanl.c b/sysdeps/libm-ieee754/s_ctanl.c
index 82f86fc148..b4a2b4a13c 100644
--- a/sysdeps/libm-ieee754/s_ctanl.c
+++ b/sysdeps/libm-ieee754/s_ctanl.c
@@ -48,10 +48,14 @@ __ctanl (__complex__ long double x)
     }
   else
     {
-      long double den = (__cosl (2.0 * __real__ x)
-			 + __ieee754_coshl (2.0 * __imag__ x));
+      long double sin2rx, cos2rx;
+      long double den;
 
-      __real__ res = __sinl (2.0 * __real__ x) / den;
+      __sincosl (2.0 * __real__ x, &sin2rx, &cos2rx);
+
+      den = cos2rx + __ieee754_coshl (2.0 * __imag__ x);
+
+      __real__ res = sin2rx / den;
       __imag__ res = __ieee754_sinhl (2.0 * __imag__ x) / den;
     }
 
diff --git a/sysdeps/libm-ieee754/s_roundtol.c b/sysdeps/libm-ieee754/s_roundtol.c
index 6649369b06..bc0ceae0f8 100644
--- a/sysdeps/libm-ieee754/s_roundtol.c
+++ b/sysdeps/libm-ieee754/s_roundtol.c
@@ -63,7 +63,7 @@ __roundtol (long double x)
     }
   else
     {
-      i = ((u_int32_t) (0xffffffff)) >> (j0 - 20);
+      u_int32_t i = ((u_int32_t) (0xffffffff)) >> (j0 - 20);
       if ((i1 & i) != 0)
 	{
 	  /* x is not integral.  */
@@ -93,7 +93,7 @@ __roundtol (long double x)
 	{
 	  result = (long int) ((i0 & 0xfffff) | 0x100000) << (j0 - 31);
 	  if (sizeof (long int) > 4 && j0 > 31)
-	    result |= j >> (63 - j0);
+	    result |= i1 >> (63 - j0);
 	}
     }
 
diff --git a/sysdeps/libm-ieee754/s_roundtoll.c b/sysdeps/libm-ieee754/s_roundtoll.c
index 8d99130697..49167236a6 100644
--- a/sysdeps/libm-ieee754/s_roundtoll.c
+++ b/sysdeps/libm-ieee754/s_roundtoll.c
@@ -63,7 +63,7 @@ __roundtoll (long double x)
     }
   else
     {
-      i = ((u_int32_t) (0xffffffff)) >> (j0 - 20);
+      u_int32_t i = ((u_int32_t) (0xffffffff)) >> (j0 - 20);
       if ((i1 & i) != 0)
 	{
 	  /* x is not integral.  */
@@ -95,7 +95,7 @@ __roundtoll (long double x)
 	{
 	  result = (long long int) ((i0 & 0xfffff) | 0x100000) << (j0 - 31);
 	  if (sizeof (long long int) > 4 && j0 > 31)
-	    result |= j >> (63 - j0);
+	    result |= i1 >> (63 - j0);
 	}
     }
 
diff --git a/sysdeps/libm-ieee754/s_sincos.c b/sysdeps/libm-ieee754/s_sincos.c
new file mode 100644
index 0000000000..5bc564ba5b
--- /dev/null
+++ b/sysdeps/libm-ieee754/s_sincos.c
@@ -0,0 +1,78 @@
+/* Compute sine and cosine of argument.
+   Copyright (C) 1997 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Library General Public License as
+   published by the Free Software Foundation; either version 2 of the
+   License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Library General Public License for more details.
+
+   You should have received a copy of the GNU Library General Public
+   License along with the GNU C Library; see the file COPYING.LIB.  If not,
+   write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+   Boston, MA 02111-1307, USA.  */
+
+#include <math.h>
+
+#include "math_private.h"
+
+
+void
+__sincos (double x, double *sinx, double *cosx)
+{
+  int32_t ix;
+
+  /* High word of x. */
+  GET_HIGH_WORD (ix, x);
+
+  /* |x| ~< pi/4 */
+  ix &= 0x7fffffff;
+  if (ix <= 0x3fe921fb)
+    {
+      *sinx = __kernel_sin (x, 0.0, 0);
+      *cosx = __kernel_cos (x, 0.0);
+    }
+  else if (ix>=0x7ff00000)
+    {
+      /* sin(Inf or NaN) is NaN */
+      *sinx = *cosx = x - x;
+    }
+  else
+    {
+      /* Argument reduction needed.  */
+      double y[2];
+      int n;
+
+      n = __ieee754_rem_pio2 (x, y);
+      switch (n & 3)
+	{
+	case 0:
+	  *sinx = __kernel_sin (y[0], y[1], 1);
+	  *cosx = __kernel_cos (y[0], y[1]);
+	  break;
+	case 1:
+	  *sinx = __kernel_cos (y[0], y[1]);
+	  *cosx = -__kernel_sin (y[0], y[1], 1);
+	  break;
+	case 2:
+	  *sinx = -__kernel_sin (y[0], y[1], 1);
+	  *cosx = -__kernel_cos (y[0], y[1]);
+	  break;
+	default:
+	  *sinx = -__kernel_cos (y[0], y[1]);
+	  *cosx = __kernel_sin (y[0], y[1], 1);
+	  break;
+	}
+    }
+}
+weak_alias (__sincos, sincos)
+#ifdef NO_LONG_DOUBLE
+strong_alias (__sincos, __sincosl)
+weak_alias (__sincos, sincosl)
+#endif
diff --git a/sysdeps/libm-ieee754/s_sincosf.c b/sysdeps/libm-ieee754/s_sincosf.c
new file mode 100644
index 0000000000..0fd7b0ca8b
--- /dev/null
+++ b/sysdeps/libm-ieee754/s_sincosf.c
@@ -0,0 +1,74 @@
+/* Compute sine and cosine of argument.
+   Copyright (C) 1997 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Library General Public License as
+   published by the Free Software Foundation; either version 2 of the
+   License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Library General Public License for more details.
+
+   You should have received a copy of the GNU Library General Public
+   License along with the GNU C Library; see the file COPYING.LIB.  If not,
+   write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+   Boston, MA 02111-1307, USA.  */
+
+#include <math.h>
+
+#include "math_private.h"
+
+
+void
+__sincosf (float x, float *sinx, float *cosx)
+{
+  int32_t ix;
+
+  /* High word of x. */
+  GET_FLOAT_WORD (ix, x);
+
+  /* |x| ~< pi/4 */
+  ix &= 0x7fffffff;
+  if (ix <= 0x3f490fd8)
+    {
+      *sinx = __kernel_sinf (x, 0.0, 0);
+      *cosx = __kernel_cosf (x, 0.0);
+    }
+  else if (ix>=0x7ff00000)
+    {
+      /* sin(Inf or NaN) is NaN */
+      *sinx = *cosx = x - x;
+    }
+  else
+    {
+      /* Argument reduction needed.  */
+      float y[2];
+      int n;
+
+      n = __ieee754_rem_pio2f (x, y);
+      switch (n & 3)
+	{
+	case 0:
+	  *sinx = __kernel_sinf (y[0], y[1], 1);
+	  *cosx = __kernel_cosf (y[0], y[1]);
+	  break;
+	case 1:
+	  *sinx = __kernel_cosf (y[0], y[1]);
+	  *cosx = -__kernel_sinf (y[0], y[1], 1);
+	  break;
+	case 2:
+	  *sinx = -__kernel_sinf (y[0], y[1], 1);
+	  *cosx = -__kernel_cosf (y[0], y[1]);
+	  break;
+	default:
+	  *sinx = -__kernel_cosf (y[0], y[1]);
+	  *cosx = __kernel_sinf (y[0], y[1], 1);
+	  break;
+	}
+    }
+}
+weak_alias (__sincosf, sincosf)
diff --git a/sysdeps/libm-ieee754/s_sincosl.c b/sysdeps/libm-ieee754/s_sincosl.c
new file mode 100644
index 0000000000..7cadf88a40
--- /dev/null
+++ b/sysdeps/libm-ieee754/s_sincosl.c
@@ -0,0 +1,74 @@
+/* Compute sine and cosine of argument.
+   Copyright (C) 1997 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Library General Public License as
+   published by the Free Software Foundation; either version 2 of the
+   License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Library General Public License for more details.
+
+   You should have received a copy of the GNU Library General Public
+   License along with the GNU C Library; see the file COPYING.LIB.  If not,
+   write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+   Boston, MA 02111-1307, USA.  */
+
+#include <math.h>
+
+#include "math_private.h"
+
+
+void
+__sincosl (long double x, long double *sinx, long double *cosx)
+{
+  int32_t se, i0, i1;
+
+  /* High word of x. */
+  GET_LDOUBLE_WORDS (se, i0, i1, x);
+
+  /* |x| ~< pi/4 */
+  se &= 0x7fff;
+  if (se < 0x3ffe || (se == 0x3ffe && i0 <= 0xc90fdaa2))
+    {
+      *sinx = __kernel_sinl (x, 0.0, 0);
+      *cosx = __kernel_cosl (x, 0.0);
+    }
+  else if (ix == 0x7fff)
+    {
+      /* sin(Inf or NaN) is NaN */
+      *sinx = *cosx = x - x;
+    }
+  else
+    {
+      /* Argument reduction needed.  */
+      long double y[2];
+      int n;
+
+      n = __ieee754_rem_pio2l (x, y);
+      switch (n & 3)
+	{
+	case 0:
+	  *sinx = __kernel_sinl (y[0], y[1], 1);
+	  *cosx = __kernel_cosl (y[0], y[1]);
+	  break;
+	case 1:
+	  *sinx = __kernel_cosl (y[0], y[1]);
+	  *cosx = -__kernel_sinl (y[0], y[1], 1);
+	  break;
+	case 2:
+	  *sinx = -__kernel_sinl (y[0], y[1], 1);
+	  *cosx = -__kernel_cosl (y[0], y[1]);
+	  break;
+	default:
+	  *sinx = -__kernel_cosl (y[0], y[1]);
+	  *cosx = __kernel_sinl (y[0], y[1], 1);
+	  break;
+	}
+    }
+}
+weak_alias (__sincosl, sincosl)
diff --git a/sysdeps/libm-ieee754/s_sinl.c b/sysdeps/libm-ieee754/s_sinl.c
index ade86dfa66..4fd48805b4 100644
--- a/sysdeps/libm-ieee754/s_sinl.c
+++ b/sysdeps/libm-ieee754/s_sinl.c
@@ -60,14 +60,15 @@ static char rcsid[] = "$NetBSD: $";
 #endif
 {
 	long double y[2],z=0.0;
-	int32_t n, se;
+	int32_t n, se, i0, i1;
 
     /* High word of x. */
-	GET_LDOUBLE_EXP(se,x);
+	GET_LDOUBLE_WORDS(se,i0,i1,x);
 
     /* |x| ~< pi/4 */
 	se &= 0x7fff;
-	if(se <= 0x3ffe) return __kernel_sinl(x,z,0);
+	if(se < 0x3ffe || (se == 0x3ffe && i0 <= 0xc90fdaa2))
+	  return __kernel_sinl(x,z,0);
 
     /* sin(Inf or NaN) is NaN */
 	else if (se==0x7fff) return x-x;