glibc/math/s_catan_template.c
Joseph Myers 620ff9eea6 Define and use libm_alias_double.
Continuing the process of setting up common macros for libm function
aliases, with a view to using them to define _FloatN / _FloatNx
aliases in future, this patch adds a libm_alias_double macro and uses
it in the type-generic templates.

This macro handles defining aliases for double, and for long double in
the NO_LONG_DOUBLE case.  It also handles defining compat symbols for
long double = double for architectures that changed their long double
format.  By so doing, it eliminates the need for the
M_LIBM_NEED_COMPAT and declare_mgen_libm_compat macros; the single
declare_mgen_alias call in each template now suffices to define all
required compat symbols.  When used for more double functions (not
based on type-generic templates), I expect it will eliminate the need
for most ldbl-opt wrappers for such functions.

A few special cases are needed.  __clog10l is a public symbol (for
historical reasons) so needs to be given appropriate compat versions
for architectures that changed their long double format, but is not
defined as an alias using the normal macros since __clog10* are *not*
public symbols for _FloatN / _FloatNx types.  For scalbn, scalbln and
log1p, the changes adding errno setting support for those functions
left compat symbols pointing directly to the non-errno-setting
implementations.  There is no requirement for the compat symbols not
to set errno; that just made for the simplest patches at that time.
Now, with these common macros, it's natural to redirect the compat
symbols to the errno-setting wrappers, which I intend to do in a
separate patch.

Tested for x86_64, and with build-many-glibcs.py.  For ldbl-opt
platforms the stripped libm.so binaries are changed (disassembly
unchanged) because the details of how the clog10l compat symbol is
created mean it ceases to be weak as it was before; for other
platforms, stripped libm.so binaries are unchanged.

2017-09-13  Joseph Myers  <joseph@codesourcery.com>

	* sysdeps/generic/libm-alias-double.h: New file.
	* sysdeps/ieee754/ldbl-opt/libm-alias-double.h: Likewise.
	* sysdeps/generic/math-type-macros-double.h: Include
	<libm-alias-double.h>.
	[declare_mgen_alias] (declare_mgen_alias): Define to use
	libm_alias_double.
	* sysdeps/generic/math-type-macros.h [!M_LIBM_NEED_COMPAT]
	(M_LIBM_NEED_COMPAT): Remove macro.
	[!M_LIBM_NEED_COMPAT] (declare_mgen_libm_compat): Likewise.
	* sysdeps/ieee754/ldbl-opt/math-type-macros-double.h: Remove.
	* math/cabs_template.c [M_LIBM_NEED_COMPAT]: Remove conditional
	code.
	* math/carg_template.c [M_LIBM_NEED_COMPAT]: Likewise.
	* math/cimag_template.c [M_LIBM_NEED_COMPAT]: Likewise.
	* math/conj_template.c [M_LIBM_NEED_COMPAT]: Likewise.
	* math/creal_template.c [M_LIBM_NEED_COMPAT]: Likewise.
	* math/s_cacos_template.c [M_LIBM_NEED_COMPAT]: Likewise.
	* math/s_cacosh_template.c [M_LIBM_NEED_COMPAT]: Likewise.
	* math/s_casin_template.c [M_LIBM_NEED_COMPAT]: Likewise.
	* math/s_casinh_template.c [M_LIBM_NEED_COMPAT]: Likewise.
	* math/s_catan_template.c [M_LIBM_NEED_COMPAT]: Likewise.
	* math/s_catanh_template.c [M_LIBM_NEED_COMPAT]: Likewise.
	* math/s_ccos_template.c [M_LIBM_NEED_COMPAT]: Likewise.
	* math/s_ccosh_template.c [M_LIBM_NEED_COMPAT]: Likewise.
	* math/s_cexp_template.c [M_LIBM_NEED_COMPAT]: Likewise.
	* math/s_clog10_template.c [M_LIBM_NEED_COMPAT]: Likewise.
	* math/s_clog_template.c [M_LIBM_NEED_COMPAT]: Likewise.
	* math/s_cpow_template.c [M_LIBM_NEED_COMPAT]: Likewise.
	* math/s_cproj_template.c [M_LIBM_NEED_COMPAT]: Likewise.
	* math/s_csin_template.c [M_LIBM_NEED_COMPAT]: Likewise.
	* math/s_csinh_template.c [M_LIBM_NEED_COMPAT]: Likewise.
	* math/s_csqrt_template.c [M_LIBM_NEED_COMPAT]: Likewise.
	* math/s_ctan_template.c [M_LIBM_NEED_COMPAT]: Likewise.
	* math/s_ctanh_template.c [M_LIBM_NEED_COMPAT]: Likewise.
	* math/s_fdim_template.c [M_LIBM_NEED_COMPAT]: Likewise.
	* math/s_fmax_template.c [M_LIBM_NEED_COMPAT]: Likewise.
	* math/s_fmin_template.c [M_LIBM_NEED_COMPAT]: Likewise.
	* math/s_nan_template.c [M_LIBM_NEED_COMPAT]: Likewise.
	* math/w_ilogb_template.c [M_LIBM_NEED_COMPAT]: Likewise.
	* sysdeps/ieee754/ldbl-opt/s_clog10.c: New file.
	* sysdeps/ieee754/ldbl-opt/s_ldexp.c (M_LIBM_NEED_COMPAT): Remove
	macro.
	(declare_mgen_alias): New macro.
	* sysdeps/ieee754/ldbl-opt/w_log1p.c: New file.
	* sysdeps/ieee754/ldbl-opt/w_scalbln.c: Likewise.
	* sysdeps/sparc/sparc32/sparcv9/fpu/multiarch/s_fdim-vis3.c
	(M_LIBM_NEED_COMPAT): Remove macro.
	* sysdeps/sparc/sparc32/sparcv9/fpu/multiarch/s_fdim.c
	[HAVE_AS_VIS3_SUPPORT]: Include <math_ldbl_opt.h> and
	<first-versions.h>.
	[HAVE_AS_VIS3_SUPPORT && LONG_DOUBLE_COMPAT (libm,
	FIRST_VERSION_libm_fdiml)]: Define fdiml as compat symbol.
2017-09-13 01:13:30 +00:00

142 lines
3.6 KiB
C

/* Return arc tangent of complex float type.
Copyright (C) 1997-2017 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>
#include <float.h>
CFLOAT
M_DECL_FUNC (__catan) (CFLOAT x)
{
CFLOAT res;
int rcls = fpclassify (__real__ x);
int icls = fpclassify (__imag__ x);
if (__glibc_unlikely (rcls <= FP_INFINITE || icls <= FP_INFINITE))
{
if (rcls == FP_INFINITE)
{
__real__ res = M_COPYSIGN (M_MLIT (M_PI_2), __real__ x);
__imag__ res = M_COPYSIGN (0, __imag__ x);
}
else if (icls == FP_INFINITE)
{
if (rcls >= FP_ZERO)
__real__ res = M_COPYSIGN (M_MLIT (M_PI_2), __real__ x);
else
__real__ res = M_NAN;
__imag__ res = M_COPYSIGN (0, __imag__ x);
}
else if (icls == FP_ZERO || icls == FP_INFINITE)
{
__real__ res = M_NAN;
__imag__ res = M_COPYSIGN (0, __imag__ x);
}
else
{
__real__ res = M_NAN;
__imag__ res = M_NAN;
}
}
else if (__glibc_unlikely (rcls == FP_ZERO && icls == FP_ZERO))
{
res = x;
}
else
{
if (M_FABS (__real__ x) >= 16 / M_EPSILON
|| M_FABS (__imag__ x) >= 16 / M_EPSILON)
{
__real__ res = M_COPYSIGN (M_MLIT (M_PI_2), __real__ x);
if (M_FABS (__real__ x) <= 1)
__imag__ res = 1 / __imag__ x;
else if (M_FABS (__imag__ x) <= 1)
__imag__ res = __imag__ x / __real__ x / __real__ x;
else
{
FLOAT h = M_HYPOT (__real__ x / 2, __imag__ x / 2);
__imag__ res = __imag__ x / h / h / 4;
}
}
else
{
FLOAT den, absx, absy;
absx = M_FABS (__real__ x);
absy = M_FABS (__imag__ x);
if (absx < absy)
{
FLOAT t = absx;
absx = absy;
absy = t;
}
if (absy < M_EPSILON / 2)
{
den = (1 - absx) * (1 + absx);
if (den == 0)
den = 0;
}
else if (absx >= 1)
den = (1 - absx) * (1 + absx) - absy * absy;
else if (absx >= M_LIT (0.75) || absy >= M_LIT (0.5))
den = -M_SUF (__x2y2m1) (absx, absy);
else
den = (1 - absx) * (1 + absx) - absy * absy;
__real__ res = M_LIT (0.5) * M_ATAN2 (2 * __real__ x, den);
if (M_FABS (__imag__ x) == 1
&& M_FABS (__real__ x) < M_EPSILON * M_EPSILON)
__imag__ res = (M_COPYSIGN (M_LIT (0.5), __imag__ x)
* ((FLOAT) M_MLIT (M_LN2)
- M_LOG (M_FABS (__real__ x))));
else
{
FLOAT r2 = 0, num, f;
if (M_FABS (__real__ x) >= M_EPSILON * M_EPSILON)
r2 = __real__ x * __real__ x;
num = __imag__ x + 1;
num = r2 + num * num;
den = __imag__ x - 1;
den = r2 + den * den;
f = num / den;
if (f < M_LIT (0.5))
__imag__ res = M_LIT (0.25) * M_LOG (f);
else
{
num = 4 * __imag__ x;
__imag__ res = M_LIT (0.25) * M_LOG1P (num / den);
}
}
}
math_check_force_underflow_complex (res);
}
return res;
}
declare_mgen_alias (__catan, catan)