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.
This commit is contained in:
Paul E. Murphy 2016-07-01 10:55:27 -05:00
parent a6f20b6763
commit ffb84f5e19
6 changed files with 694 additions and 0 deletions

View File

@ -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).

210
math/k_casinh_template.c Normal file
View File

@ -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;
}

66
math/s_casin_template.c Normal file
View File

@ -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

73
math/s_casinh_template.c Normal file
View File

@ -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

171
math/s_csin_template.c Normal file
View File

@ -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

166
math/s_csinh_template.c Normal file
View File

@ -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