about summary refs log tree commit diff
diff options
context:
space:
mode:
authorPaul E. Murphy <murphyp@linux.vnet.ibm.com>2016-07-01 10:55:27 -0500
committerPaul E. Murphy <murphyp@linux.vnet.ibm.com>2016-08-19 16:12:36 -0500
commitffb84f5e197aaa9d46a35df84689c75d689d73cb (patch)
treebf042c5c45738def34881b33863ba78f0ae901d2
parenta6f20b6763c972c05c497c6028d412d6d1717971 (diff)
downloadglibc-ffb84f5e197aaa9d46a35df84689c75d689d73cb.tar.gz
glibc-ffb84f5e197aaa9d46a35df84689c75d689d73cb.tar.xz
glibc-ffb84f5e197aaa9d46a35df84689c75d689d73cb.zip
Prepare to convert _Complex sine functions
This patch has no function changes, except to
ensure the git history correctly tracks the
changes to convert the double version of these
functions into a templated version.
-rw-r--r--ChangeLog8
-rw-r--r--math/k_casinh_template.c210
-rw-r--r--math/s_casin_template.c66
-rw-r--r--math/s_casinh_template.c73
-rw-r--r--math/s_csin_template.c171
-rw-r--r--math/s_csinh_template.c166
6 files changed, 694 insertions, 0 deletions
diff --git a/ChangeLog b/ChangeLog
index 64c4701a88..b097cd4205 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,11 @@
+2016-08-19  Paul E. Murphy  <murphyp@linux.vnet.ibm.com>
+
+	* s_casin_template.c: Copy of s_casin.c.
+	* s_casinh_template.c: Copy of s_casinh.c.
+	* s_csin_template.c: Copy of s_csin.c.
+	* s_csinh_template.c: Copy of s_csinh.c.
+	* k_casinh_template.c: Copy of k_casinh.c.
+
 2016-08-19  H.J. Lu  <hongjiu.lu@intel.com>
 
 	* sysdeps/x86/cpu-features.h (bit_YMM_state): Set to (1 << 2).
diff --git a/math/k_casinh_template.c b/math/k_casinh_template.c
new file mode 100644
index 0000000000..354dde1f3e
--- /dev/null
+++ b/math/k_casinh_template.c
@@ -0,0 +1,210 @@
+/* Return arc hyperbole sine for double value, with the imaginary part
+   of the result possibly adjusted for use in computing other
+   functions.
+   Copyright (C) 1997-2016 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 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
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include <complex.h>
+#include <math.h>
+#include <math_private.h>
+#include <float.h>
+
+/* Return the complex inverse hyperbolic sine of finite nonzero Z,
+   with the imaginary part of the result subtracted from pi/2 if ADJ
+   is nonzero.  */
+
+__complex__ double
+__kernel_casinh (__complex__ double x, int adj)
+{
+  __complex__ double res;
+  double rx, ix;
+  __complex__ double y;
+
+  /* Avoid cancellation by reducing to the first quadrant.  */
+  rx = fabs (__real__ x);
+  ix = fabs (__imag__ x);
+
+  if (rx >= 1.0 / DBL_EPSILON || ix >= 1.0 / DBL_EPSILON)
+    {
+      /* For large x in the first quadrant, x + csqrt (1 + x * x)
+	 is sufficiently close to 2 * x to make no significant
+	 difference to the result; avoid possible overflow from
+	 the squaring and addition.  */
+      __real__ y = rx;
+      __imag__ y = ix;
+
+      if (adj)
+	{
+	  double t = __real__ y;
+	  __real__ y = __copysign (__imag__ y, __imag__ x);
+	  __imag__ y = t;
+	}
+
+      res = __clog (y);
+      __real__ res += M_LN2;
+    }
+  else if (rx >= 0.5 && ix < DBL_EPSILON / 8.0)
+    {
+      double s = __ieee754_hypot (1.0, rx);
+
+      __real__ res = __ieee754_log (rx + s);
+      if (adj)
+	__imag__ res = __ieee754_atan2 (s, __imag__ x);
+      else
+	__imag__ res = __ieee754_atan2 (ix, s);
+    }
+  else if (rx < DBL_EPSILON / 8.0 && ix >= 1.5)
+    {
+      double s = __ieee754_sqrt ((ix + 1.0) * (ix - 1.0));
+
+      __real__ res = __ieee754_log (ix + s);
+      if (adj)
+	__imag__ res = __ieee754_atan2 (rx, __copysign (s, __imag__ x));
+      else
+	__imag__ res = __ieee754_atan2 (s, rx);
+    }
+  else if (ix > 1.0 && ix < 1.5 && rx < 0.5)
+    {
+      if (rx < DBL_EPSILON * DBL_EPSILON)
+	{
+	  double ix2m1 = (ix + 1.0) * (ix - 1.0);
+	  double s = __ieee754_sqrt (ix2m1);
+
+	  __real__ res = __log1p (2.0 * (ix2m1 + ix * s)) / 2.0;
+	  if (adj)
+	    __imag__ res = __ieee754_atan2 (rx, __copysign (s, __imag__ x));
+	  else
+	    __imag__ res = __ieee754_atan2 (s, rx);
+	}
+      else
+	{
+	  double ix2m1 = (ix + 1.0) * (ix - 1.0);
+	  double rx2 = rx * rx;
+	  double f = rx2 * (2.0 + rx2 + 2.0 * ix * ix);
+	  double d = __ieee754_sqrt (ix2m1 * ix2m1 + f);
+	  double dp = d + ix2m1;
+	  double dm = f / dp;
+	  double r1 = __ieee754_sqrt ((dm + rx2) / 2.0);
+	  double r2 = rx * ix / r1;
+
+	  __real__ res = __log1p (rx2 + dp + 2.0 * (rx * r1 + ix * r2)) / 2.0;
+	  if (adj)
+	    __imag__ res = __ieee754_atan2 (rx + r1, __copysign (ix + r2,
+								 __imag__ x));
+	  else
+	    __imag__ res = __ieee754_atan2 (ix + r2, rx + r1);
+	}
+    }
+  else if (ix == 1.0 && rx < 0.5)
+    {
+      if (rx < DBL_EPSILON / 8.0)
+	{
+	  __real__ res = __log1p (2.0 * (rx + __ieee754_sqrt (rx))) / 2.0;
+	  if (adj)
+	    __imag__ res = __ieee754_atan2 (__ieee754_sqrt (rx),
+					    __copysign (1.0, __imag__ x));
+	  else
+	    __imag__ res = __ieee754_atan2 (1.0, __ieee754_sqrt (rx));
+	}
+      else
+	{
+	  double d = rx * __ieee754_sqrt (4.0 + rx * rx);
+	  double s1 = __ieee754_sqrt ((d + rx * rx) / 2.0);
+	  double s2 = __ieee754_sqrt ((d - rx * rx) / 2.0);
+
+	  __real__ res = __log1p (rx * rx + d + 2.0 * (rx * s1 + s2)) / 2.0;
+	  if (adj)
+	    __imag__ res = __ieee754_atan2 (rx + s1, __copysign (1.0 + s2,
+								 __imag__ x));
+	  else
+	    __imag__ res = __ieee754_atan2 (1.0 + s2, rx + s1);
+	}
+    }
+  else if (ix < 1.0 && rx < 0.5)
+    {
+      if (ix >= DBL_EPSILON)
+	{
+	  if (rx < DBL_EPSILON * DBL_EPSILON)
+	    {
+	      double onemix2 = (1.0 + ix) * (1.0 - ix);
+	      double s = __ieee754_sqrt (onemix2);
+
+	      __real__ res = __log1p (2.0 * rx / s) / 2.0;
+	      if (adj)
+		__imag__ res = __ieee754_atan2 (s, __imag__ x);
+	      else
+		__imag__ res = __ieee754_atan2 (ix, s);
+	    }
+	  else
+	    {
+	      double onemix2 = (1.0 + ix) * (1.0 - ix);
+	      double rx2 = rx * rx;
+	      double f = rx2 * (2.0 + rx2 + 2.0 * ix * ix);
+	      double d = __ieee754_sqrt (onemix2 * onemix2 + f);
+	      double dp = d + onemix2;
+	      double dm = f / dp;
+	      double r1 = __ieee754_sqrt ((dp + rx2) / 2.0);
+	      double r2 = rx * ix / r1;
+
+	      __real__ res
+		= __log1p (rx2 + dm + 2.0 * (rx * r1 + ix * r2)) / 2.0;
+	      if (adj)
+		__imag__ res = __ieee754_atan2 (rx + r1,
+						__copysign (ix + r2,
+							    __imag__ x));
+	      else
+		__imag__ res = __ieee754_atan2 (ix + r2, rx + r1);
+	    }
+	}
+      else
+	{
+	  double s = __ieee754_hypot (1.0, rx);
+
+	  __real__ res = __log1p (2.0 * rx * (rx + s)) / 2.0;
+	  if (adj)
+	    __imag__ res = __ieee754_atan2 (s, __imag__ x);
+	  else
+	    __imag__ res = __ieee754_atan2 (ix, s);
+	}
+      math_check_force_underflow_nonneg (__real__ res);
+    }
+  else
+    {
+      __real__ y = (rx - ix) * (rx + ix) + 1.0;
+      __imag__ y = 2.0 * rx * ix;
+
+      y = __csqrt (y);
+
+      __real__ y += rx;
+      __imag__ y += ix;
+
+      if (adj)
+	{
+	  double t = __real__ y;
+	  __real__ y = __copysign (__imag__ y, __imag__ x);
+	  __imag__ y = t;
+	}
+
+      res = __clog (y);
+    }
+
+  /* Give results the correct sign for the original argument.  */
+  __real__ res = __copysign (__real__ res, __real__ x);
+  __imag__ res = __copysign (__imag__ res, (adj ? 1.0 : __imag__ x));
+
+  return res;
+}
diff --git a/math/s_casin_template.c b/math/s_casin_template.c
new file mode 100644
index 0000000000..a37933b597
--- /dev/null
+++ b/math/s_casin_template.c
@@ -0,0 +1,66 @@
+/* Return arc sine of complex double value.
+   Copyright (C) 1997-2016 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 Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 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
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include <complex.h>
+#include <math.h>
+#include <math_private.h>
+
+
+__complex__ double
+__casin (__complex__ double x)
+{
+  __complex__ double res;
+
+  if (isnan (__real__ x) || isnan (__imag__ x))
+    {
+      if (__real__ x == 0.0)
+	{
+	  res = x;
+	}
+      else if (isinf (__real__ x) || isinf (__imag__ x))
+	{
+	  __real__ res = __nan ("");
+	  __imag__ res = __copysign (HUGE_VAL, __imag__ x);
+	}
+      else
+	{
+	  __real__ res = __nan ("");
+	  __imag__ res = __nan ("");
+	}
+    }
+  else
+    {
+      __complex__ double y;
+
+      __real__ y = -__imag__ x;
+      __imag__ y = __real__ x;
+
+      y = __casinh (y);
+
+      __real__ res = __imag__ y;
+      __imag__ res = -__real__ y;
+    }
+
+  return res;
+}
+weak_alias (__casin, casin)
+#ifdef NO_LONG_DOUBLE
+strong_alias (__casin, __casinl)
+weak_alias (__casin, casinl)
+#endif
diff --git a/math/s_casinh_template.c b/math/s_casinh_template.c
new file mode 100644
index 0000000000..32cbc13991
--- /dev/null
+++ b/math/s_casinh_template.c
@@ -0,0 +1,73 @@
+/* Return arc hyperbole sine for double value.
+   Copyright (C) 1997-2016 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 Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 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
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include <complex.h>
+#include <math.h>
+#include <math_private.h>
+
+__complex__ double
+__casinh (__complex__ double x)
+{
+  __complex__ double res;
+  int rcls = fpclassify (__real__ x);
+  int icls = fpclassify (__imag__ x);
+
+  if (rcls <= FP_INFINITE || icls <= FP_INFINITE)
+    {
+      if (icls == FP_INFINITE)
+	{
+	  __real__ res = __copysign (HUGE_VAL, __real__ x);
+
+	  if (rcls == FP_NAN)
+	    __imag__ res = __nan ("");
+	  else
+	    __imag__ res = __copysign (rcls >= FP_ZERO ? M_PI_2 : M_PI_4,
+				       __imag__ x);
+	}
+      else if (rcls <= FP_INFINITE)
+	{
+	  __real__ res = __real__ x;
+	  if ((rcls == FP_INFINITE && icls >= FP_ZERO)
+	      || (rcls == FP_NAN && icls == FP_ZERO))
+	    __imag__ res = __copysign (0.0, __imag__ x);
+	  else
+	    __imag__ res = __nan ("");
+	}
+      else
+	{
+	  __real__ res = __nan ("");
+	  __imag__ res = __nan ("");
+	}
+    }
+  else if (rcls == FP_ZERO && icls == FP_ZERO)
+    {
+      res = x;
+    }
+  else
+    {
+      res = __kernel_casinh (x, 0);
+    }
+
+  return res;
+}
+weak_alias (__casinh, casinh)
+#ifdef NO_LONG_DOUBLE
+strong_alias (__casinh, __casinhl)
+weak_alias (__casinh, casinhl)
+#endif
diff --git a/math/s_csin_template.c b/math/s_csin_template.c
new file mode 100644
index 0000000000..e071aa650e
--- /dev/null
+++ b/math/s_csin_template.c
@@ -0,0 +1,171 @@
+/* Complex sine function for double.
+   Copyright (C) 1997-2016 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 Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 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
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include <complex.h>
+#include <fenv.h>
+#include <math.h>
+#include <math_private.h>
+#include <float.h>
+
+__complex__ double
+__csin (__complex__ double x)
+{
+  __complex__ double retval;
+  int negate = signbit (__real__ x);
+  int rcls = fpclassify (__real__ x);
+  int icls = fpclassify (__imag__ x);
+
+  __real__ x = fabs (__real__ x);
+
+  if (__glibc_likely (icls >= FP_ZERO))
+    {
+      /* Imaginary part is finite.  */
+      if (__glibc_likely (rcls >= FP_ZERO))
+	{
+	  /* Real part is finite.  */
+	  const int t = (int) ((DBL_MAX_EXP - 1) * M_LN2);
+	  double sinix, cosix;
+
+	  if (__glibc_likely (__real__ x > DBL_MIN))
+	    {
+	      __sincos (__real__ x, &sinix, &cosix);
+	    }
+	  else
+	    {
+	      sinix = __real__ x;
+	      cosix = 1.0;
+	    }
+
+	  if (negate)
+	    sinix = -sinix;
+
+	  if (fabs (__imag__ x) > t)
+	    {
+	      double exp_t = __ieee754_exp (t);
+	      double ix = fabs (__imag__ x);
+	      if (signbit (__imag__ x))
+		cosix = -cosix;
+	      ix -= t;
+	      sinix *= exp_t / 2.0;
+	      cosix *= exp_t / 2.0;
+	      if (ix > t)
+		{
+		  ix -= t;
+		  sinix *= exp_t;
+		  cosix *= exp_t;
+		}
+	      if (ix > t)
+		{
+		  /* Overflow (original imaginary part of x > 3t).  */
+		  __real__ retval = DBL_MAX * sinix;
+		  __imag__ retval = DBL_MAX * cosix;
+		}
+	      else
+		{
+		  double exp_val = __ieee754_exp (ix);
+		  __real__ retval = exp_val * sinix;
+		  __imag__ retval = exp_val * cosix;
+		}
+	    }
+	  else
+	    {
+	      __real__ retval = __ieee754_cosh (__imag__ x) * sinix;
+	      __imag__ retval = __ieee754_sinh (__imag__ x) * cosix;
+	    }
+
+	  math_check_force_underflow_complex (retval);
+	}
+      else
+	{
+	  if (icls == FP_ZERO)
+	    {
+	      /* Imaginary part is 0.0.  */
+	      __real__ retval = __nan ("");
+	      __imag__ retval = __imag__ x;
+
+	      if (rcls == FP_INFINITE)
+		feraiseexcept (FE_INVALID);
+	    }
+	  else
+	    {
+	      __real__ retval = __nan ("");
+	      __imag__ retval = __nan ("");
+
+	      feraiseexcept (FE_INVALID);
+	    }
+	}
+    }
+  else if (icls == FP_INFINITE)
+    {
+      /* Imaginary part is infinite.  */
+      if (rcls == FP_ZERO)
+	{
+	  /* Real part is 0.0.  */
+	  __real__ retval = __copysign (0.0, negate ? -1.0 : 1.0);
+	  __imag__ retval = __imag__ x;
+	}
+      else if (rcls > FP_ZERO)
+	{
+	  /* Real part is finite.  */
+	  double sinix, cosix;
+
+	  if (__glibc_likely (__real__ x > DBL_MIN))
+	    {
+	      __sincos (__real__ x, &sinix, &cosix);
+	    }
+	  else
+	    {
+	      sinix = __real__ x;
+	      cosix = 1.0;
+	    }
+
+	  __real__ retval = __copysign (HUGE_VAL, sinix);
+	  __imag__ retval = __copysign (HUGE_VAL, cosix);
+
+	  if (negate)
+	    __real__ retval = -__real__ retval;
+	  if (signbit (__imag__ x))
+	    __imag__ retval = -__imag__ retval;
+	}
+      else
+	{
+	  /* The addition raises the invalid exception.  */
+	  __real__ retval = __nan ("");
+	  __imag__ retval = HUGE_VAL;
+
+	  if (rcls == FP_INFINITE)
+	    feraiseexcept (FE_INVALID);
+	}
+    }
+  else
+    {
+      if (rcls == FP_ZERO)
+	__real__ retval = __copysign (0.0, negate ? -1.0 : 1.0);
+      else
+	__real__ retval = __nan ("");
+      __imag__ retval = __nan ("");
+    }
+
+  return retval;
+}
+weak_alias (__csin, csin)
+#ifdef NO_LONG_DOUBLE
+strong_alias (__csin, __csinl)
+weak_alias (__csin, csinl)
+#endif
diff --git a/math/s_csinh_template.c b/math/s_csinh_template.c
new file mode 100644
index 0000000000..5fb60ed0cb
--- /dev/null
+++ b/math/s_csinh_template.c
@@ -0,0 +1,166 @@
+/* Complex sine hyperbole function for double.
+   Copyright (C) 1997-2016 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 Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 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
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include <complex.h>
+#include <fenv.h>
+#include <math.h>
+#include <math_private.h>
+#include <float.h>
+
+__complex__ double
+__csinh (__complex__ double x)
+{
+  __complex__ double retval;
+  int negate = signbit (__real__ x);
+  int rcls = fpclassify (__real__ x);
+  int icls = fpclassify (__imag__ x);
+
+  __real__ x = fabs (__real__ x);
+
+  if (__glibc_likely (rcls >= FP_ZERO))
+    {
+      /* Real part is finite.  */
+      if (__glibc_likely (icls >= FP_ZERO))
+	{
+	  /* Imaginary part is finite.  */
+	  const int t = (int) ((DBL_MAX_EXP - 1) * M_LN2);
+	  double sinix, cosix;
+
+	  if (__glibc_likely (fabs (__imag__ x) > DBL_MIN))
+	    {
+	      __sincos (__imag__ x, &sinix, &cosix);
+	    }
+	  else
+	    {
+	      sinix = __imag__ x;
+	      cosix = 1.0;
+	    }
+
+	  if (negate)
+	    cosix = -cosix;
+
+	  if (fabs (__real__ x) > t)
+	    {
+	      double exp_t = __ieee754_exp (t);
+	      double rx = fabs (__real__ x);
+	      if (signbit (__real__ x))
+		cosix = -cosix;
+	      rx -= t;
+	      sinix *= exp_t / 2.0;
+	      cosix *= exp_t / 2.0;
+	      if (rx > t)
+		{
+		  rx -= t;
+		  sinix *= exp_t;
+		  cosix *= exp_t;
+		}
+	      if (rx > t)
+		{
+		  /* Overflow (original real part of x > 3t).  */
+		  __real__ retval = DBL_MAX * cosix;
+		  __imag__ retval = DBL_MAX * sinix;
+		}
+	      else
+		{
+		  double exp_val = __ieee754_exp (rx);
+		  __real__ retval = exp_val * cosix;
+		  __imag__ retval = exp_val * sinix;
+		}
+	    }
+	  else
+	    {
+	      __real__ retval = __ieee754_sinh (__real__ x) * cosix;
+	      __imag__ retval = __ieee754_cosh (__real__ x) * sinix;
+	    }
+
+	  math_check_force_underflow_complex (retval);
+	}
+      else
+	{
+	  if (rcls == FP_ZERO)
+	    {
+	      /* Real part is 0.0.  */
+	      __real__ retval = __copysign (0.0, negate ? -1.0 : 1.0);
+	      __imag__ retval = __nan ("") + __nan ("");
+
+	      if (icls == FP_INFINITE)
+		feraiseexcept (FE_INVALID);
+	    }
+	  else
+	    {
+	      __real__ retval = __nan ("");
+	      __imag__ retval = __nan ("");
+
+	      feraiseexcept (FE_INVALID);
+	    }
+	}
+    }
+  else if (rcls == FP_INFINITE)
+    {
+      /* Real part is infinite.  */
+      if (__glibc_likely (icls > FP_ZERO))
+	{
+	  /* Imaginary part is finite.  */
+	  double sinix, cosix;
+
+	  if (__glibc_likely (fabs (__imag__ x) > DBL_MIN))
+	    {
+	      __sincos (__imag__ x, &sinix, &cosix);
+	    }
+	  else
+	    {
+	      sinix = __imag__ x;
+	      cosix = 1.0;
+	    }
+
+	  __real__ retval = __copysign (HUGE_VAL, cosix);
+	  __imag__ retval = __copysign (HUGE_VAL, sinix);
+
+	  if (negate)
+	    __real__ retval = -__real__ retval;
+	}
+      else if (icls == FP_ZERO)
+	{
+	  /* Imaginary part is 0.0.  */
+	  __real__ retval = negate ? -HUGE_VAL : HUGE_VAL;
+	  __imag__ retval = __imag__ x;
+	}
+      else
+	{
+	  /* The addition raises the invalid exception.  */
+	  __real__ retval = HUGE_VAL;
+	  __imag__ retval = __nan ("") + __nan ("");
+
+	  if (icls == FP_INFINITE)
+	    feraiseexcept (FE_INVALID);
+	}
+    }
+  else
+    {
+      __real__ retval = __nan ("");
+      __imag__ retval = __imag__ x == 0.0 ? __imag__ x : __nan ("");
+    }
+
+  return retval;
+}
+weak_alias (__csinh, csinh)
+#ifdef NO_LONG_DOUBLE
+strong_alias (__csinh, __csinhl)
+weak_alias (__csinh, csinhl)
+#endif