Refactor some libm type-generic macros.

This patch refactors some type-generic libm macros, in both math.h and
math_private.h, to be based on a common __MATH_TG macro rather than
all replicating similar logic to choose a function to call based on
the type of the argument.

This should serve to illustrate what I think float128 support for such
macros should look like: common macros such as __MATH_TG may need
different definitions depending on whether float128 is supported in
glibc, so that the individual macros themselves do not need
conditionals on float128 support.

Tested for x86_64, x86, mips64 and powerpc.

	* math/math.h (__MATH_TG): New macro.
	[__USE_ISOC99] (fpclassify): Define using __MATH_TG.
	[__USE_ISOC99] (signbit): Likewise.
	[__USE_ISOC99] (isfinite): Likewise.
	[__USE_ISOC99] (isnan): Likewise.
	[__USE_ISOC99] (isinf): Likewise.
	[__GLIBC_USE (IEC_60559_BFP_EXT)] (issignaling): Likewise.
	[__GLIBC_USE (IEC_60559_BFP_EXT)] (__MATH_EVAL_FMT2): New macro.
	[__GLIBC_USE (IEC_60559_BFP_EXT)] (iseqsig): Define using
	__MATH_TG and __MATH_EVAL_FMT2.
	* sysdeps/generic/math_private.h (fabs_tg): Define using
	__MATH_TG.
	* sysdeps/ieee754/ldbl-128ibm/bits/iscanonical.h
	[!__NO_LONG_DOUBLE_MATH] (__iscanonicalf): New macro.
	[!__NO_LONG_DOUBLE_MATH] (__iscanonical): Likewise.
	[!__NO_LONG_DOUBLE_MATH] (iscanonical): Define using __MATH_TG.
	* sysdeps/ieee754/ldbl-96/bits/iscanonical.h (__iscanonicalf): New
	macro.
	(__iscanonical): Likewise.
	(iscanonical): Define using __MATH_TG.
This commit is contained in:
Joseph Myers 2016-11-10 21:41:56 +00:00
parent 0a557c105c
commit b4e75104b4
5 changed files with 70 additions and 99 deletions

View File

@ -1,3 +1,26 @@
2016-11-10 Joseph Myers <joseph@codesourcery.com>
* math/math.h (__MATH_TG): New macro.
[__USE_ISOC99] (fpclassify): Define using __MATH_TG.
[__USE_ISOC99] (signbit): Likewise.
[__USE_ISOC99] (isfinite): Likewise.
[__USE_ISOC99] (isnan): Likewise.
[__USE_ISOC99] (isinf): Likewise.
[__GLIBC_USE (IEC_60559_BFP_EXT)] (issignaling): Likewise.
[__GLIBC_USE (IEC_60559_BFP_EXT)] (__MATH_EVAL_FMT2): New macro.
[__GLIBC_USE (IEC_60559_BFP_EXT)] (iseqsig): Define using
__MATH_TG and __MATH_EVAL_FMT2.
* sysdeps/generic/math_private.h (fabs_tg): Define using
__MATH_TG.
* sysdeps/ieee754/ldbl-128ibm/bits/iscanonical.h
[!__NO_LONG_DOUBLE_MATH] (__iscanonicalf): New macro.
[!__NO_LONG_DOUBLE_MATH] (__iscanonical): Likewise.
[!__NO_LONG_DOUBLE_MATH] (iscanonical): Define using __MATH_TG.
* sysdeps/ieee754/ldbl-96/bits/iscanonical.h (__iscanonicalf): New
macro.
(__iscanonical): Likewise.
(iscanonical): Define using __MATH_TG.
2016-11-10 Adhemerval Zanella <adhemerval.zanella@linaro.org>
* sysdeps/unix/sysv/linux/sh/kernel-features.h: Add include

View File

@ -199,6 +199,27 @@ extern int signgam;
#endif
/* Depending on the type of TG_ARG, call an appropriately suffixed
version of FUNC with arguments (including parentheses) ARGS.
Suffixed functions may not exist for long double if it has the same
format as double, or for other types with the same format as float,
double or long double. The behavior is undefined if the argument
does not have a real floating type. The definition may use a
conditional expression, so all suffixed versions of FUNC must
return the same type (FUNC may include a cast if necessary rather
than being a single identifier). */
#ifdef __NO_LONG_DOUBLE_MATH
# define __MATH_TG(TG_ARG, FUNC, ARGS) \
(sizeof (TG_ARG) == sizeof (float) ? FUNC ## f ARGS : FUNC ARGS)
#else
# define __MATH_TG(TG_ARG, FUNC, ARGS) \
(sizeof (TG_ARG) == sizeof (float) \
? FUNC ## f ARGS \
: sizeof (TG_ARG) == sizeof (double) \
? FUNC ARGS \
: FUNC ## l ARGS)
#endif
/* ISO C99 defines some generic macros which work on any data type. */
#ifdef __USE_ISOC99
@ -231,49 +252,22 @@ enum
&& !defined __OPTIMIZE_SIZE__
# define fpclassify(x) __builtin_fpclassify (FP_NAN, FP_INFINITE, \
FP_NORMAL, FP_SUBNORMAL, FP_ZERO, x)
# elif defined __NO_LONG_DOUBLE_MATH
# define fpclassify(x) \
(sizeof (x) == sizeof (float) ? __fpclassifyf (x) : __fpclassify (x))
# else
# define fpclassify(x) \
(sizeof (x) == sizeof (float) \
? __fpclassifyf (x) \
: sizeof (x) == sizeof (double) \
? __fpclassify (x) : __fpclassifyl (x))
# define fpclassify(x) __MATH_TG ((x), __fpclassify, (x))
# endif
/* Return nonzero value if sign of X is negative. */
# if __GNUC_PREREQ (4,0)
# define signbit(x) \
(sizeof (x) == sizeof (float) \
? __builtin_signbitf (x) \
: sizeof (x) == sizeof (double) \
? __builtin_signbit (x) : __builtin_signbitl (x))
# define signbit(x) __MATH_TG ((x), __builtin_signbit, (x))
# else
# ifdef __NO_LONG_DOUBLE_MATH
# define signbit(x) \
(sizeof (x) == sizeof (float) ? __signbitf (x) : __signbit (x))
# else
# define signbit(x) \
(sizeof (x) == sizeof (float) \
? __signbitf (x) \
: sizeof (x) == sizeof (double) \
? __signbit (x) : __signbitl (x))
# endif
# define signbit(x) __MATH_TG ((x), __signbit, (x))
# endif
/* Return nonzero value if X is not +-Inf or NaN. */
# if __GNUC_PREREQ (4,4) && !defined __SUPPORT_SNAN__
# define isfinite(x) __builtin_isfinite (x)
# elif defined __NO_LONG_DOUBLE_MATH
# define isfinite(x) \
(sizeof (x) == sizeof (float) ? __finitef (x) : __finite (x))
# else
# define isfinite(x) \
(sizeof (x) == sizeof (float) \
? __finitef (x) \
: sizeof (x) == sizeof (double) \
? __finite (x) : __finitel (x))
# define isfinite(x) __MATH_TG ((x), __finite, (x))
# endif
/* Return nonzero value if X is neither zero, subnormal, Inf, nor NaN. */
@ -287,29 +281,15 @@ enum
we already have this functions `__isnan' and it is faster. */
# if __GNUC_PREREQ (4,4) && !defined __SUPPORT_SNAN__
# define isnan(x) __builtin_isnan (x)
# elif defined __NO_LONG_DOUBLE_MATH
# define isnan(x) \
(sizeof (x) == sizeof (float) ? __isnanf (x) : __isnan (x))
# else
# define isnan(x) \
(sizeof (x) == sizeof (float) \
? __isnanf (x) \
: sizeof (x) == sizeof (double) \
? __isnan (x) : __isnanl (x))
# define isnan(x) __MATH_TG ((x), __isnan, (x))
# endif
/* Return nonzero value if X is positive or negative infinity. */
# if __GNUC_PREREQ (4,4) && !defined __SUPPORT_SNAN__
# define isinf(x) __builtin_isinf_sign (x)
# elif defined __NO_LONG_DOUBLE_MATH
# define isinf(x) \
(sizeof (x) == sizeof (float) ? __isinff (x) : __isinf (x))
# else
# define isinf(x) \
(sizeof (x) == sizeof (float) \
? __isinff (x) \
: sizeof (x) == sizeof (double) \
? __isinf (x) : __isinfl (x))
# define isinf(x) __MATH_TG ((x), __isinf, (x))
# endif
/* Bitmasks for the math_errhandling macro. */
@ -329,16 +309,7 @@ enum
# include <bits/iscanonical.h>
/* Return nonzero value if X is a signaling NaN. */
# ifdef __NO_LONG_DOUBLE_MATH
# define issignaling(x) \
(sizeof (x) == sizeof (float) ? __issignalingf (x) : __issignaling (x))
# else
# define issignaling(x) \
(sizeof (x) == sizeof (float) \
? __issignalingf (x) \
: sizeof (x) == sizeof (double) \
? __issignaling (x) : __issignalingl (x))
# endif
# define issignaling(x) __MATH_TG ((x), __issignaling, (x))
/* Return nonzero value if X is subnormal. */
# define issubnormal(x) (fpclassify (x) == FP_SUBNORMAL)
@ -555,36 +526,20 @@ extern int matherr (struct exception *__exc);
#endif
#if __GLIBC_USE (IEC_60559_BFP_EXT)
/* An expression whose type has the widest of the evaluation formats
of X and Y (which are of floating-point types). */
# if __FLT_EVAL_METHOD__ == 2 || __FLT_EVAL_METHOD__ > 64
# define __MATH_EVAL_FMT2(x, y) ((x) + (y) + 0.0L)
# elif __FLT_EVAL_METHOD__ == 1 || __FLT_EVAL_METHOD__ > 32
# define __MATH_EVAL_FMT2(x, y) ((x) + (y) + 0.0)
# else
# define __MATH_EVAL_FMT2(x, y) ((x) + (y))
# endif
/* Return X == Y but raising "invalid" and setting errno if X or Y is
a NaN. */
# ifdef __NO_LONG_DOUBLE_MATH
# if (__FLT_EVAL_METHOD__ == 1 \
|| __FLT_EVAL_METHOD__ == 2 \
|| __FLT_EVAL_METHOD__ > 32)
# define iseqsig(x, y) __iseqsig ((x), (y))
# else
# define iseqsig(x, y) \
(sizeof ((x) + (y)) == sizeof (float) \
? __iseqsigf ((x), (y)) \
: __iseqsig ((x), (y)))
# endif
# else
# if __FLT_EVAL_METHOD__ == 2 || __FLT_EVAL_METHOD__ > 64
# define iseqsig(x, y) __iseqsigl ((x), (y))
# elif __FLT_EVAL_METHOD__ == 1 || __FLT_EVAL_METHOD__ > 32
# define iseqsig(x, y) \
(sizeof ((x) + (y)) <= sizeof (double) \
? __iseqsig ((x), (y)) \
: __iseqsigl ((x), (y)))
# else
# define iseqsig(x, y) \
(sizeof ((x) + (y)) == sizeof (float) \
? __iseqsigf ((x), (y)) \
: sizeof ((x) + (y)) == sizeof (double) \
? __iseqsig ((x), (y)) \
: __iseqsigl ((x), (y)))
# endif
# endif
# define iseqsig(x, y) \
__MATH_TG (__MATH_EVAL_FMT2 (x, y), __iseqsig, ((x), (y)))
#endif
__END_DECLS

View File

@ -427,12 +427,7 @@ extern long double __lgamma_productl (long double t, long double x,
})
#endif
#define fabs_tg(x) __builtin_choose_expr \
(__builtin_types_compatible_p (__typeof (x), float), \
__builtin_fabsf (x), \
__builtin_choose_expr \
(__builtin_types_compatible_p (__typeof (x), double), \
__builtin_fabs (x), __builtin_fabsl (x)))
#define fabs_tg(x) __MATH_TG ((x), (__typeof (x)) __builtin_fabs, (x))
#define min_of_type(type) __builtin_choose_expr \
(__builtin_types_compatible_p (type, float), \
FLT_MIN, \

View File

@ -25,6 +25,8 @@
#else
extern int __iscanonicall (long double __x)
__THROW __attribute__ ((__const__));
# define __iscanonicalf(x) ((void) (__typeof (x)) (x), 1)
# define __iscanonical(x) ((void) (__typeof (x)) (x), 1)
/* Return nonzero value if X is canonical. In IEEE interchange binary
formats, all values are canonical, but the argument must still be
@ -32,8 +34,5 @@ extern int __iscanonicall (long double __x)
conversion, before being discarded; in IBM long double, there are
encodings that are not consistently handled as corresponding to any
particular value of the type, and we return 0 for those. */
# define iscanonical(x) \
(sizeof (x) == sizeof (long double) \
? __iscanonicall (x) \
: ((void) (__typeof (x)) (x), 1))
# define iscanonical(x) __MATH_TG ((x), __iscanonical, (x))
#endif

View File

@ -22,6 +22,8 @@
extern int __iscanonicall (long double __x)
__THROW __attribute__ ((__const__));
#define __iscanonicalf(x) ((void) (__typeof (x)) (x), 1)
#define __iscanonical(x) ((void) (__typeof (x)) (x), 1)
/* Return nonzero value if X is canonical. In IEEE interchange binary
formats, all values are canonical, but the argument must still be
@ -29,7 +31,4 @@ extern int __iscanonicall (long double __x)
conversion, before being discarded; in extended precision, there
are encodings that are not consistently handled as corresponding to
any particular value of the type, and we return 0 for those. */
#define iscanonical(x) \
(sizeof (x) == sizeof (long double) \
? __iscanonicall (x) \
: ((void) (__typeof (x)) (x), 1))
#define iscanonical(x) __MATH_TG ((x), __iscanonical, (x))