summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog84
-rw-r--r--math/Makefile71
-rw-r--r--math/README.libm-test1
-rw-r--r--math/gen-auto-libm-tests.c160
-rwxr-xr-xmath/gen-libm-test.pl34
-rw-r--r--math/libm-test-driver.c50
-rw-r--r--math/libm-test-support.c25
-rw-r--r--math/libm-test-support.h27
-rw-r--r--math/test-arg-double.h25
-rw-r--r--math/test-arg-float128.h32
-rw-r--r--math/test-arg-float32x.h28
-rw-r--r--math/test-arg-float64.h28
-rw-r--r--math/test-arg-float64x.h32
-rw-r--r--math/test-arg-ldouble.h31
-rw-r--r--math/test-double.h1
-rw-r--r--math/test-float.h1
-rw-r--r--math/test-float128.h1
-rw-r--r--math/test-float32.h1
-rw-r--r--math/test-float32x.h1
-rw-r--r--math/test-float64.h1
-rw-r--r--math/test-float64x.h1
-rw-r--r--math/test-math-narrow.h26
-rw-r--r--math/test-math-scalar.h3
-rw-r--r--math/test-math-vector.h1
-rw-r--r--math/test-narrow-macros.c56
-rw-r--r--sysdeps/ieee754/ldbl-opt/Makefile3
-rw-r--r--sysdeps/ieee754/ldbl-opt/test-narrow-macros-ldbl-64.c1
27 files changed, 668 insertions, 57 deletions
diff --git a/ChangeLog b/ChangeLog
index 7aeb699cc3..4fe83a6b7f 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,89 @@
2018-02-09 Joseph Myers <joseph@codesourcery.com>
+ * math/Makefile (test-type-pairs): New variable.
+ (test-type-pairs-f64xf128-yes): Likewise.
+ (tests): Add test-narrow-macros.
+ (libm-test-funcs-narrow): New variable.
+ (libm-test-c-narrow): Likewise.
+ (generated): Add $(libm-test-c-narrow).
+ (libm-tests-base-narrow): New variable.
+ (libm-tests-narrow): Likewise.
+ (libm-tests): Add $(libm-tests-narrow).
+ (libm-tests-for-type): Handle $(libm-tests-narrow).
+ (libm-test-c-narrow-obj): New variable.
+ ($(libm-test-c-narrow-obj)): New rule.
+ ($(foreach t,$(libm-tests-narrow),$(objpfx)$(t).c)): Likewise.
+ ($(foreach f,$(libm-test-funcs-narrow),$(objpfx)$(o)-$(f).o)): Use
+ $(o-iterator) to set dependencies and CFLAGS.
+ * math/gen-auto-libm-tests.c: Document use for narrowing
+ functions.
+ (output_for_one_input_case): Take argument NARROW.
+ (generate_output): Likewise. Update call to
+ output_for_one_input_case.
+ (main): Take --narrow option. Update call to generate_output.
+ * math/gen-libm-test.pl (_apply_lit): Take macro name as argument.
+ (apply_lit): Update call to _apply_lit.
+ (apply_arglit): New function.
+ (parse_args): Handle "a" arguments.
+ (parse_auto_input): Handle format names using ":".
+ * math/README.libm-test: Document "a" parameter type.
+ * math/libm-test-support.h (ARG_TYPE_MIN): New macro.
+ (ARG_TYPE_TRUE_MIN): Likewise.
+ (ARG_TYPE_MAX): Likwise.
+ (ARG_MIN_EXP): Likewise.
+ (ARG_MAX_EXP): Likewise.
+ (ARG_MANT_DIG): Likewise.
+ (TEST_COND_arg_ibm128): Likewise.
+ (TEST_COND_ibm128_libgcc): Define conditional on [ARG_FLOAT].
+ (TEST_COND_arg_fmt): New macro.
+ (init_max_error): Update prototype.
+ * math/libm-test-support.c (test_ibm128): New variable.
+ (init_max_error): Take argument testing_ibm128 and set test_ibm128
+ instead of using [TEST_COND_ibm128] conditional.
+ (test_exceptions): Use test_ibm128 instead of TEST_COND_ibm128.
+ * math/libm-test-driver.c (STR_ARG_FLOAT): New macro.
+ [TEST_NARROW] (TEST_MSG): New definition.
+ (arg_plus_zero): New macro.
+ (arg_minus_zero): Likewise.
+ (arg_plus_infty): Likewise.
+ (arg_minus_infty): Likewise.
+ (arg_qnan_value_pl): Likewise.
+ (arg_qnan_value): Likewise.
+ (arg_snan_value_pl): Likewise.
+ (arg_snan_value): Likewise.
+ (arg_max_value): Likewise.
+ (arg_min_value): Likewise.
+ (arg_min_subnorm_value): Likewise.
+ [ARG_FLOAT] (struct test_aa_f_data): New struct type.
+ (RUN_TEST_LOOP_aa_f): New macro.
+ (TEST_SUFF): New macro.
+ (TEST_SUFF_STR): Likewise.
+ [!TEST_MATHVEC] (VEC_SUFF): Don't define.
+ (TEST_COND_any_ibm128): New macro.
+ (START): Use TEST_SUFF and TEST_SUFF_STR in initializer for
+ this_func. Update call to init_max_error.
+ * math/test-double.h (FUNC_NARROW_PREFIX): New macro.
+ * math/test-float.h (FUNC_NARROW_PREFIX): Likewise.
+ * math/test-float128.h (FUNC_NARROW_PREFIX): Likewise.
+ * math/test-float32.h (FUNC_NARROW_PREFIX): Likewise.
+ * math/test-float32x.h (FUNC_NARROW_PREFIX): Likewise.
+ * math/test-float64.h (FUNC_NARROW_PREFIX): Likewise.
+ * math/test-float64x.h (FUNC_NARROW_PREFIX): Likewise.
+ * math/test-math-scalar.h (TEST_NARROW): Likewise.
+ * math/test-math-vector.h (TEST_NARROW): Likewise.
+ * math/test-arg-double.h: New file.
+ * math/test-arg-float128.h: Likewise.
+ * math/test-arg-float32x.h: Likewise.
+ * math/test-arg-float64.h: Likewise.
+ * math/test-arg-float64x.h: Likewise.
+ * math/test-arg-ldouble.h: Likewise.
+ * math/test-math-narrow.h: Likewise.
+ * math/test-narrow-macros.c: Likewise.
+ * sysdeps/ieee754/ldbl-opt/test-narrow-macros-ldbl-64.c: Likewise.
+ * sysdeps/ieee754/ldbl-opt/Makefile (tests): Add
+ test-narrow-macros-ldbl-64.
+ (CFLAGS-test-narrow-macros-ldbl-64.c): New variable.
+
* math/bits/mathcalls-narrow.h: New file.
* include/bits/mathcalls-narrow.h: Likewise.
* math/math-narrow.h: Likewise.
diff --git a/math/Makefile b/math/Makefile
index ee0cd6fce1..42e540cf0e 100644
--- a/math/Makefile
+++ b/math/Makefile
@@ -145,6 +145,21 @@ test-types = $(test-types-basic) $(type-float128-$(float128-fcts)) \
float32 float64 $(type-float128-$(float128-alias-fcts)) \
float32x $(type-float64x-$(float64x-alias-fcts))
+# Pairs of types for which narrowing functions should be tested (this
+# variable has more entries than libm-narrow-types because it includes
+# pairs for which the functions sometimes or always alias functions
+# for other types). This definition embeds the assumption that if
+# _Float64x is supported, so is _Float128, and vice versa (they may or
+# may not have the same format).
+test-type-pairs = float-double float-ldouble double-ldouble \
+ float32-float64 float32-float32x float32x-float64 \
+ $(test-type-pairs-f64xf128-$(float128-fcts)) \
+ $(test-type-pairs-f64xf128-$(float128-alias-fcts))
+test-type-pairs-f64xf128-yes = float32-float64x float32-float128 \
+ float64-float64x float64-float128 \
+ float32x-float64x float32x-float128 \
+ float64x-float128
+
# For each of the basic types (float, double, long double), replace the
# occurrences of 'F' in arg 1 with the appropriate suffix for the type.
type-basic-foreach = $(foreach t, $(types-basic), \
@@ -219,7 +234,8 @@ tests = test-matherr-3 test-fenv basic-test \
test-femode-traps test-iszero-excess-precision \
test-iseqsig-excess-precision test-flt-eval-method \
test-fp-ilogb-constants test-fp-llogb-constants \
- test-fe-snans-always-signal test-finite-macros $(tests-static)
+ test-fe-snans-always-signal test-finite-macros test-narrow-macros \
+ $(tests-static)
tests-static = test-fpucw-static test-fpucw-ieee-static \
test-signgam-uchar-static test-signgam-uchar-init-static \
test-signgam-uint-static test-signgam-uint-init-static \
@@ -268,14 +284,19 @@ libm-test-funcs-noauto = canonicalize ceil cimag conj copysign cproj creal \
scalbln scalbn setpayload setpayloadsig signbit \
significand totalorder totalordermag trunc ufromfp \
ufromfpx
+libm-test-funcs-narrow =
libm-test-funcs-all = $(libm-test-funcs-auto) $(libm-test-funcs-noauto)
libm-test-c-auto = $(foreach f,$(libm-test-funcs-auto),libm-test-$(f).c)
libm-test-c-noauto = $(foreach f,$(libm-test-funcs-noauto),libm-test-$(f).c)
-generated += libm-test-ulps.h $(libm-test-c-auto) $(libm-test-c-noauto)
+libm-test-c-narrow = $(foreach f,$(libm-test-funcs-narrow),\
+ libm-test-narrow-$(f).c)
+generated += libm-test-ulps.h $(libm-test-c-auto) $(libm-test-c-noauto) \
+ $(libm-test-c-narrow)
libm-tests-base-normal = $(foreach t,$(test-types),test-$(t))
libm-tests-base-finite = $(foreach t,$(test-types),test-$(t)-finite)
libm-tests-base-inline = $(foreach t,$(test-types),test-i$(t))
+libm-tests-base-narrow = $(foreach t,$(test-type-pairs),test-$(t))
libm-tests-base = $(libm-tests-base-normal) $(libm-tests-base-finite) \
$(libm-tests-base-inline) $(libm-vec-tests)
libm-tests-normal = $(foreach t,$(libm-tests-base-normal),\
@@ -287,14 +308,18 @@ libm-tests-finite = $(foreach t,$(libm-tests-base-finite),\
libm-tests-inline = $(foreach t,$(libm-tests-base-inline),\
$(foreach f,$(libm-test-funcs-all),\
$(t)-$(f)))
+libm-tests-narrow = $(foreach t,$(libm-tests-base-narrow),\
+ $(foreach f,$(libm-test-funcs-narrow),\
+ $(t)-$(f)))
libm-tests-vector = $(foreach t,$(libmvec-tests),\
$(foreach f,$($(t)-funcs),test-$(t)-$(f)))
libm-tests = $(libm-tests-normal) $(libm-tests-finite) $(libm-tests-inline) \
- $(libm-tests-vector)
+ $(libm-tests-narrow) $(libm-tests-vector)
libm-tests-for-type = $(foreach f,$(libm-test-funcs-all),\
test-$(1)-$(f) test-$(1)-finite-$(f) \
test-i$(1)-$(f)) \
- $(filter test-$(1)-%,$(libm-tests-vector))
+ $(filter test-$(1)-%,$(libm-tests-vector) \
+ $(libm-tests-narrow))
libm-tests.o = $(addsuffix .o,$(libm-tests))
@@ -304,6 +329,7 @@ generated += $(addsuffix .c,$(libm-tests)) \
libm-test-c-auto-obj = $(addprefix $(objpfx),$(libm-test-c-auto))
libm-test-c-noauto-obj = $(addprefix $(objpfx),$(libm-test-c-noauto))
+libm-test-c-narrow-obj = $(addprefix $(objpfx),$(libm-test-c-narrow))
$(libm-test-c-noauto-obj): $(objpfx)libm-test%.c: libm-test%.inc \
gen-libm-test.pl
@@ -315,6 +341,12 @@ $(libm-test-c-auto-obj): $(objpfx)libm-test%.c: libm-test%.inc \
auto-libm-test-out%
$(make-target-directory)
$(PERL) gen-libm-test.pl -c $< -a auto-libm-test-out$* -C $@
+
+$(libm-test-c-narrow-obj): $(objpfx)libm-test%.c: libm-test%.inc \
+ gen-libm-test.pl \
+ auto-libm-test-out%
+ $(make-target-directory)
+ $(PERL) gen-libm-test.pl -c $< -a auto-libm-test-out$* -C $@
endif
ifdef PYTHON
@@ -457,6 +489,22 @@ $(foreach t,$(libm-tests-inline),$(objpfx)$(t).c): $(objpfx)test-i%.c:
echo "#include <libm-test-$$func.c>"; \
) > $@
+$(foreach t,$(libm-tests-narrow),$(objpfx)$(t).c): $(objpfx)test-%.c:
+ type_pair_func=$*; \
+ type_pair=$${type_pair_func%-*}; \
+ func=$${type_pair_func##*-}; \
+ ret_type=$${type_pair%%-*}; \
+ arg_type=$${type_pair#*-}; \
+ ( \
+ echo "#include <test-$$ret_type.h>"; \
+ echo "#include <test-arg-$$arg_type.h>"; \
+ echo "#include <test-math-no-finite.h>"; \
+ echo "#include <test-math-no-inline.h>"; \
+ echo "#include <test-math-errno.h>"; \
+ echo "#include <test-math-narrow.h>"; \
+ echo "#include <libm-test-narrow-$$func.c>"; \
+ ) > $@
+
$(foreach t,$(libm-tests-vector),$(objpfx)$(t).c): $(objpfx)test-%.c:
type_func=$*; \
type=$${type_func%-*}; \
@@ -486,6 +534,14 @@ object-suffixes-left := $(libm-tests-base)
include $(o-iterator)
define o-iterator-doit
+$(foreach f,$(libm-test-funcs-narrow),\
+ $(objpfx)$(o)-$(f).o): $(objpfx)$(o)%.o: \
+ $(objpfx)libm-test-narrow%.c
+endef
+object-suffixes-left := $(libm-tests-base-narrow)
+include $(o-iterator)
+
+define o-iterator-doit
$(foreach f,$(libm-test-funcs-all),\
$(objpfx)$(o)-$(f).o): CFLAGS += $(libm-test-no-inline-cflags)
endef
@@ -507,6 +563,13 @@ object-suffixes-left := $(libm-tests-base-inline)
include $(o-iterator)
define o-iterator-doit
+$(foreach f,$(libm-test-funcs-narrow),\
+ $(objpfx)$(o)-$(f).o): CFLAGS += $(libm-test-no-inline-cflags)
+endef
+object-suffixes-left := $(libm-tests-base-narrow)
+include $(o-iterator)
+
+define o-iterator-doit
$(foreach f,$($(o)-funcs),\
$(objpfx)test-$(o)-$(f).o): CFLAGS += $(libm-test-vec-cflags)
endef
diff --git a/math/README.libm-test b/math/README.libm-test
index 0271f83f3b..41702c6537 100644
--- a/math/README.libm-test
+++ b/math/README.libm-test
@@ -120,6 +120,7 @@ parameter.
The accepted parameter types are:
- "f" for FLOAT
- "j" for long double.
+- "a" for ARG_FLOAT, the argument type for narrowing functions.
- "b" for boolean - just tests if the output parameter evaluates to 0
or 1 (only for output).
- "c" for complex. This parameter needs two values, first the real,
diff --git a/math/gen-auto-libm-tests.c b/math/gen-auto-libm-tests.c
index 934c64bc76..442a10d5e6 100644
--- a/math/gen-auto-libm-tests.c
+++ b/math/gen-auto-libm-tests.c
@@ -25,6 +25,15 @@
gen-auto-libm-tests auto-libm-test-in <func> auto-libm-test-out-<func>
+ to generate results for normal libm functions, or
+
+ gen-auto-libm-tests --narrow auto-libm-test-in <func> \
+ auto-libm-test-out-narrow-<func>
+
+ to generate results for a function rounding results to a narrower
+ type (in the case of fma and sqrt, both output files are generated
+ from the same test inputs).
+
The input file auto-libm-test-in contains three kinds of lines:
Lines beginning with "#" are comments, and are ignored, as are
@@ -120,7 +129,22 @@
missing or spurious, or because the calculation of correct results
indicated it was optional). Conditions "before-rounding" and
"after-rounding" indicate tests where expectations for underflow
- exceptions depend on how the architecture detects tininess. */
+ exceptions depend on how the architecture detects tininess.
+
+ For functions rounding their results to a narrower type, the format
+ given on an output test line is the result format followed by
+ information about the requirements on the argument format to be
+ able to represent the argument values, in the form
+ "format:arg_fmt(MAX_EXP,NUM_ONES,MIN_EXP,MAX_PREC)". Instead of
+ separate lines for separate argument formats, an output test line
+ relates to all argument formats that can represent the values.
+ MAX_EXP is the maximum exponent of a nonzero bit in any argument,
+ or 0 if all arguments are zero; NUM_ONES is the maximum number of
+ leading bits with value 1 in an argument with exponent MAX_EXP, or
+ 0 if all arguments are zero; MIN_EXP is the minimum exponent of a
+ nonzero bit in any argument, or 0 if all arguments are zero;
+ MAX_PREC is the maximum precision required to represent all
+ arguments, or 0 if all arguments are zero. */
#define _GNU_SOURCE
@@ -1718,12 +1742,13 @@ output_generic_value (FILE *fp, const char *filename, const generic_value *v,
}
}
-/* Generate test output to FP (name FILENAME) for test function TF,
- input test IT, choice of input values INPUTS. */
+/* Generate test output to FP (name FILENAME) for test function TF
+ (rounding results to a narrower type if NARROW), input test IT,
+ choice of input values INPUTS. */
static void
output_for_one_input_case (FILE *fp, const char *filename, test_function *tf,
- input_test *it, generic_value *inputs)
+ bool narrow, input_test *it, generic_value *inputs)
{
bool long_bits_matters = false;
bool fits_long32 = true;
@@ -1794,24 +1819,81 @@ output_for_one_input_case (FILE *fp, const char *filename, test_function *tf,
mpfr_t res[rm_num_modes];
unsigned int exc_before[rm_num_modes];
unsigned int exc_after[rm_num_modes];
+ bool have_fp_arg = false;
+ int max_exp = 0;
+ int num_ones = 0;
+ int min_exp = 0;
+ int max_prec = 0;
for (size_t i = 0; i < tf->num_args; i++)
{
if (inputs[i].type == gtype_fp)
{
- round_real (res, exc_before, exc_after, inputs[i].value.f,
- f);
- if (!mpfr_equal_p (res[rm_tonearest], inputs[i].value.f))
- fits = false;
- for (rounding_mode m = rm_first_mode; m < rm_num_modes; m++)
- mpfr_clear (res[m]);
- if (!fits)
- break;
+ if (narrow)
+ {
+ if (mpfr_zero_p (inputs[i].value.f))
+ continue;
+ assert (mpfr_regular_p (inputs[i].value.f));
+ int this_exp, this_num_ones, this_min_exp, this_prec;
+ mpz_t tmp;
+ mpz_init (tmp);
+ mpfr_exp_t e = mpfr_get_z_2exp (tmp, inputs[i].value.f);
+ if (mpz_sgn (tmp) < 0)
+ mpz_neg (tmp, tmp);
+ size_t bits = mpz_sizeinbase (tmp, 2);
+ mp_bitcnt_t tz = mpz_scan1 (tmp, 0);
+ this_min_exp = e + tz;
+ this_prec = bits - tz;
+ assert (this_prec > 0);
+ this_exp = this_min_exp + this_prec - 1;
+ assert (this_exp
+ == mpfr_get_exp (inputs[i].value.f) - 1);
+ this_num_ones = 1;
+ while ((size_t) this_num_ones < bits
+ && mpz_tstbit (tmp, bits - 1 - this_num_ones))
+ this_num_ones++;
+ mpz_clear (tmp);
+ if (have_fp_arg)
+ {
+ if (this_exp > max_exp
+ || (this_exp == max_exp
+ && this_num_ones > num_ones))
+ {
+ max_exp = this_exp;
+ num_ones = this_num_ones;
+ }
+ if (this_min_exp < min_exp)
+ min_exp = this_min_exp;
+ if (this_prec > max_prec)
+ max_prec = this_prec;
+ }
+ else
+ {
+ max_exp = this_exp;
+ num_ones = this_num_ones;
+ min_exp = this_min_exp;
+ max_prec = this_prec;
+ }
+ have_fp_arg = true;
+ }
+ else
+ {
+ round_real (res, exc_before, exc_after,
+ inputs[i].value.f, f);
+ if (!mpfr_equal_p (res[rm_tonearest], inputs[i].value.f))
+ fits = false;
+ for (rounding_mode m = rm_first_mode;
+ m < rm_num_modes;
+ m++)
+ mpfr_clear (res[m]);
+ if (!fits)
+ break;
+ }
}
}
if (!fits)
continue;
- /* The inputs fit this type, so compute the ideal outputs
- and exceptions. */
+ /* The inputs fit this type if required to do so, so compute
+ the ideal outputs and exceptions. */
mpfr_t all_res[MAX_NRET][rm_num_modes];
unsigned int all_exc_before[MAX_NRET][rm_num_modes];
unsigned int all_exc_after[MAX_NRET][rm_num_modes];
@@ -1895,10 +1977,21 @@ output_for_one_input_case (FILE *fp, const char *filename, test_function *tf,
assert ((merged_exc_before[m] & (1U << exc_underflow)) != 0);
}
unsigned int merged_exc = merged_exc_before[m];
- if (fprintf (fp, "= %s %s %s%s", tf->name,
- rounding_modes[m].name, fp_formats[f].name,
- long_cond) < 0)
- error (EXIT_FAILURE, errno, "write to '%s'", filename);
+ if (narrow)
+ {
+ if (fprintf (fp, "= %s %s %s%s:arg_fmt(%d,%d,%d,%d)",
+ tf->name, rounding_modes[m].name,
+ fp_formats[f].name, long_cond, max_exp,
+ num_ones, min_exp, max_prec) < 0)
+ error (EXIT_FAILURE, errno, "write to '%s'", filename);
+ }
+ else
+ {
+ if (fprintf (fp, "= %s %s %s%s", tf->name,
+ rounding_modes[m].name, fp_formats[f].name,
+ long_cond) < 0)
+ error (EXIT_FAILURE, errno, "write to '%s'", filename);
+ }
/* Print inputs. */
for (size_t i = 0; i < tf->num_args; i++)
output_generic_value (fp, filename, &inputs[i], false,
@@ -2158,10 +2251,12 @@ output_for_one_input_case (FILE *fp, const char *filename, test_function *tf,
generic_value_free (&generic_outputs[i]);
}
-/* Generate test output data for FUNCTION to FILENAME. */
+/* Generate test output data for FUNCTION to FILENAME. The function
+ is interpreted as rounding its results to a narrower type if
+ NARROW. */
static void
-generate_output (const char *function, const char *filename)
+generate_output (const char *function, bool narrow, const char *filename)
{
FILE *fp = fopen (filename, "w");
if (fp == NULL)
@@ -2177,7 +2272,8 @@ generate_output (const char *function, const char *filename)
if (fputs (it->line, fp) < 0)
error (EXIT_FAILURE, errno, "write to '%s'", filename);
for (size_t k = 0; k < it->num_input_cases; k++)
- output_for_one_input_case (fp, filename, tf, it, it->inputs[k]);
+ output_for_one_input_case (fp, filename, tf, narrow,
+ it, it->inputs[k]);
}
}
if (fclose (fp) != 0)
@@ -2187,14 +2283,30 @@ generate_output (const char *function, const char *filename)
int
main (int argc, char **argv)
{
- if (argc != 4)
+ if (argc != 4
+ && !(argc == 5 && strcmp (argv[1], "--narrow") == 0))
error (EXIT_FAILURE, 0,
- "usage: gen-auto-libm-tests <input> <func> <output>");
+ "usage: gen-auto-libm-tests [--narrow] <input> <func> <output>");
+ bool narrow;
const char *input_filename = argv[1];
const char *function = argv[2];
const char *output_filename = argv[3];
+ if (argc == 4)
+ {
+ narrow = false;
+ input_filename = argv[1];
+ function = argv[2];
+ output_filename = argv[3];
+ }
+ else
+ {
+ narrow = true;
+ input_filename = argv[2];
+ function = argv[3];
+ output_filename = argv[4];
+ }
init_fp_formats ();
read_input (input_filename);
- generate_output (function, output_filename);
+ generate_output (function, narrow, output_filename);
exit (EXIT_SUCCESS);
}
diff --git a/math/gen-libm-test.pl b/math/gen-libm-test.pl
index 3556817c1d..664fba5909 100755
--- a/math/gen-libm-test.pl
+++ b/math/gen-libm-test.pl
@@ -165,10 +165,10 @@ sub show_exceptions {
}
}
-# Apply the LIT(x) macro to a literal floating point constant
+# Apply the LIT(x) or ARG_LIT(x) macro to a literal floating point constant
# and strip any existing suffix.
sub _apply_lit {
- my ($lit) = @_;
+ my ($macro, $lit) = @_;
my $exp_re = "([+-])?[[:digit:]]+";
# Don't wrap something that does not look like a:
# * Hexadecimal FP value
@@ -181,7 +181,7 @@ sub _apply_lit {
# Strip any existing literal suffix.
$lit =~ s/[lLfF]$//;
- return "LIT (${lit})";
+ return "$macro (${lit})";
}
# Apply LIT macro to individual tokens within an expression.
@@ -194,7 +194,17 @@ sub apply_lit {
my ($lit) = @_;
my @toks = split (/ /, $lit);
foreach (@toks) {
- $_ = _apply_lit ($_);
+ $_ = _apply_lit ("LIT", $_);
+ }
+ return join (' ', @toks);
+}
+
+# Likewise, but apply ARG_LIT for arguments to narrowing functions.
+sub apply_arglit {
+ my ($lit) = @_;
+ my @toks = split (/ /, $lit);
+ foreach (@toks) {
+ $_ = _apply_lit ("ARG_LIT", $_);
}
return join (' ', @toks);
}
@@ -228,8 +238,8 @@ sub parse_args {
if ($current_arg > 1) {
$comma = ', ';
}
- # FLOAT, long double, int, unsigned int, long int, long long int
- if ($descr[$i] =~ /f|j|i|u|l|L/) {
+ # FLOAT, ARG_FLOAT, long double, int, unsigned int, long int, long long int
+ if ($descr[$i] =~ /f|a|j|i|u|l|L/) {
$call_args .= $comma . &beautify ($args[$current_arg]);
++$current_arg;
next;
@@ -293,10 +303,12 @@ sub parse_args {
$cline = "{ \"$call_args\"";
@descr = split //,$descr_args;
for ($i=0; $i <= $#descr; $i++) {
- # FLOAT, int, long int, long long int
- if ($descr[$i] =~ /f|j|i|u|l|L/) {
+ # FLOAT, ARG_FLOAT, long double, int, unsigned int, long int, long long int
+ if ($descr[$i] =~ /f|a|j|i|u|l|L/) {
if ($descr[$i] eq "f") {
$cline .= ", " . &apply_lit ($args[$current_arg]);
+ } elsif ($descr[$i] eq "a") {
+ $cline .= ", " . &apply_arglit ($args[$current_arg]);
} else {
$cline .= ", $args[$current_arg]";
}
@@ -420,7 +432,9 @@ sub convert_condition {
my (@conds, $ret);
@conds = split /:/, $cond;
foreach (@conds) {
- s/-/_/g;
+ if ($_ !~ /^arg_fmt\(/) {
+ s/-/_/g;
+ }
s/^/TEST_COND_/;
}
$ret = join " && ", @conds;
@@ -822,7 +836,7 @@ sub parse_auto_input {
chop;
next if !/^= /;
s/^= //;
- if (/^(\S+) (\S+) ([^:]*) : (.*)$/) {
+ if (/^(\S+) (\S+) ([^: ][^ ]* [^:]*) : (.*)$/) {
$auto_tests{$1}{$2}{$3} = $4;
} else {
die ("bad automatic test line: $_\n");
diff --git a/math/libm-test-driver.c b/math/libm-test-driver.c
index b7c0343062..3713e7074f 100644
--- a/math/libm-test-driver.c
+++ b/math/libm-test-driver.c
@@ -30,6 +30,7 @@ const int flag_test_mathvec = TEST_MATHVEC;
#define STRX(x) #x
#define STR(x) STRX (x)
#define STR_FLOAT STR (FLOAT)
+#define STR_ARG_FLOAT STR (ARG_FLOAT)
#define STR_VEC_LEN STR (VEC_LEN)
/* Informal description of the functions being tested. */
@@ -39,6 +40,8 @@ const int flag_test_mathvec = TEST_MATHVEC;
# define TEST_MSG "testing " STR_FLOAT " (inline functions)\n"
#elif TEST_FINITE
# define TEST_MSG "testing " STR_FLOAT " (finite-math-only)\n"
+#elif TEST_NARROW
+# define TEST_MSG "testing " STR_FLOAT " (argument " STR_ARG_FLOAT ")\n"
#else
# define TEST_MSG "testing " STR_FLOAT " (without inline functions)\n"
#endif
@@ -108,6 +111,18 @@ const char qtype_str[] = TYPE_STR;
#define min_value TYPE_MIN
#define min_subnorm_value TYPE_TRUE_MIN
+#define arg_plus_zero ARG_LIT (0.0)
+#define arg_minus_zero ARG_LIT (-0.0)
+#define arg_plus_infty ARG_FUNC (__builtin_inf) ()
+#define arg_minus_infty -(ARG_FUNC (__builtin_inf) ())
+#define arg_qnan_value_pl(S) ARG_FUNC (__builtin_nan) (S)
+#define arg_qnan_value arg_qnan_value_pl ("")
+#define arg_snan_value_pl(S) ARG_FUNC (__builtin_nans) (S)
+#define arg_snan_value arg_snan_value_pl ("")
+#define arg_max_value ARG_TYPE_MAX
+#define arg_min_value ARG_TYPE_MIN
+#define arg_min_subnorm_value ARG_TYPE_TRUE_MIN
+
/* For nexttoward tests. */
#define snan_value_ld __builtin_nansl ("")
@@ -147,6 +162,18 @@ struct test_fj_f_data
int exceptions;
} rd, rn, rz, ru;
};
+#ifdef ARG_FLOAT
+struct test_aa_f_data
+{
+ const char *arg_str;
+ ARG_FLOAT arg1, arg2;
+ struct
+ {
+ FLOAT expected;
+ int exceptions;
+ } rd, rn, rz, ru;
+};
+#endif
struct test_fi_f_data
{
const char *arg_str;
@@ -467,6 +494,7 @@ struct test_Ff_b1_data
#define RUN_TEST_ff_f RUN_TEST_2_f
#define RUN_TEST_LOOP_ff_f RUN_TEST_LOOP_2_f
#define RUN_TEST_LOOP_fj_f RUN_TEST_LOOP_2_f
+#define RUN_TEST_LOOP_aa_f RUN_TEST_LOOP_2_f
#define RUN_TEST_fi_f RUN_TEST_2_f
#define RUN_TEST_LOOP_fi_f RUN_TEST_LOOP_2_f
#define RUN_TEST_fl_f RUN_TEST_2_f
@@ -945,18 +973,32 @@ struct test_Ff_b1_data
(ARRAY)[i].RM_##ROUNDING_MODE.extra2_expected); \
ROUND_RESTORE_ ## ROUNDING_MODE
-#if !TEST_MATHVEC
-# define VEC_SUFF
+#if TEST_MATHVEC
+# define TEST_SUFF VEC_SUFF
+# define TEST_SUFF_STR
+#elif TEST_NARROW
+# define TEST_SUFF
+# define TEST_SUFF_STR "_" ARG_TYPE_STR
+#else
+# define TEST_SUFF
+# define TEST_SUFF_STR
#endif
#define STR_CONCAT(a, b, c) __STRING (a##b##c)
#define STR_CON3(a, b, c) STR_CONCAT (a, b, c)
+#if TEST_NARROW
+# define TEST_COND_any_ibm128 (TEST_COND_ibm128 || TEST_COND_arg_ibm128)
+#else
+# define TEST_COND_any_ibm128 TEST_COND_ibm128
+#endif
+
/* Start and end the tests for a given function. */
#define START(FUN, SUFF, EXACT) \
CHECK_ARCH_EXT; \
- const char *this_func = STR_CON3 (FUN, SUFF, VEC_SUFF); \
- init_max_error (this_func, EXACT)
+ const char *this_func \
+ = STR_CON3 (FUN, SUFF, TEST_SUFF) TEST_SUFF_STR; \
+ init_max_error (this_func, EXACT, TEST_COND_any_ibm128)
#define END \
print_max_error (this_func)
#define END_COMPLEX \
diff --git a/math/libm-test-support.c b/math/libm-test-support.c
index 2e4f9ef926..e59f15b4d9 100644
--- a/math/libm-test-support.c
+++ b/math/libm-test-support.c
@@ -135,6 +135,7 @@ static int verbose;
static int output_max_error; /* Should the maximal errors printed? */
static int output_points; /* Should the single function results printed? */
static int ignore_max_ulp; /* Should we ignore max_ulp? */
+static int test_ibm128; /* Is argument or result IBM long double? */
static FLOAT max_error, real_max_error, imag_max_error;
@@ -212,11 +213,12 @@ find_ulps (const char *name, const struct ulp_data *data, size_t nmemb)
}
void
-init_max_error (const char *name, int exact)
+init_max_error (const char *name, int exact, int testing_ibm128)
{
max_error = 0;
real_max_error = 0;
imag_max_error = 0;
+ test_ibm128 = testing_ibm128;
prev_max_error = find_ulps (name, func_ulps,
sizeof (func_ulps) / sizeof (func_ulps[0]));
prev_real_max_error = find_ulps (name, func_real_ulps,
@@ -225,15 +227,14 @@ init_max_error (const char *name, int exact)
prev_imag_max_error = find_ulps (name, func_imag_ulps,
(sizeof (func_imag_ulps)
/ sizeof (func_imag_ulps[0])));
-#if TEST_COND_ibm128
- /* The documented accuracy of IBM long double division is 3ulp (see
- libgcc/config/rs6000/ibm-ldouble-format), so do not require
- better accuracy for libm functions that are exactly defined for
- other formats. */
- max_valid_error = exact ? 3 : 16;
-#else
- max_valid_error = exact ? 0 : 9;
-#endif
+ if (testing_ibm128)
+ /* The documented accuracy of IBM long double division is 3ulp
+ (see libgcc/config/rs6000/ibm-ldouble-format), so do not
+ require better accuracy for libm functions that are exactly
+ defined for other formats. */
+ max_valid_error = exact ? 3 : 16;
+ else
+ max_valid_error = exact ? 0 : 9;
prev_max_error = (prev_max_error <= max_valid_error
? prev_max_error
: max_valid_error);
@@ -518,14 +519,14 @@ test_exceptions (const char *test_name, int exception)
arithmetic. */
#ifdef FE_UNDERFLOW
if ((exception & UNDERFLOW_EXCEPTION_OK) == 0
- && !(TEST_COND_ibm128
+ && !(test_ibm128
&& (exception & UNDERFLOW_EXCEPTION) == 0))
test_single_exception (test_name, exception, UNDERFLOW_EXCEPTION,
FE_UNDERFLOW, "Underflow");
#endif
#ifdef FE_INEXACT
if ((exception & (INEXACT_EXCEPTION | NO_INEXACT_EXCEPTION)) != 0
- && !(TEST_COND_ibm128
+ && !(test_ibm128
&& (exception & NO_INEXACT_EXCEPTION) != 0))
test_single_exception (test_name, exception, INEXACT_EXCEPTION,
FE_INEXACT, "Inexact");
diff --git a/math/libm-test-support.h b/math/libm-test-support.h
index b86c22796a..64206ab7fa 100644
--- a/math/libm-test-support.h
+++ b/math/libm-test-support.h
@@ -81,6 +81,13 @@ extern const char doc[];
#define MAX_EXP __CONCATX (PREFIX, _MAX_EXP)
#define MANT_DIG __CONCATX (PREFIX, _MANT_DIG)
+#define ARG_TYPE_MIN __CONCATX (ARG_PREFIX, _MIN)
+#define ARG_TYPE_TRUE_MIN __CONCATX (ARG_PREFIX, _TRUE_MIN)
+#define ARG_TYPE_MAX __CONCATX (ARG_PREFIX, _MAX)
+#define ARG_MIN_EXP __CONCATX (ARG_PREFIX, _MIN_EXP)
+#define ARG_MAX_EXP __CONCATX (ARG_PREFIX, _MAX_EXP)
+#define ARG_MANT_DIG __CONCATX (ARG_PREFIX, _MANT_DIG)
+
/* Format specific test macros. */
#define TEST_COND_binary32 (MANT_DIG == 24 \
&& MIN_EXP == -125 \
@@ -96,6 +103,8 @@ extern const char doc[];
#define TEST_COND_ibm128 (MANT_DIG == 106)
+#define TEST_COND_arg_ibm128 (ARG_MANT_DIG == 106)
+
#define TEST_COND_intel96 (MANT_DIG == 64 \
&& MIN_EXP == -16381 \
&& MAX_EXP == 16384)
@@ -108,7 +117,11 @@ extern const char doc[];
where in principle the glibc code is OK but the tests fail because
of limitations of the libgcc support for that format (e.g. GCC bug
59666, in non-default rounding modes). */
-#define TEST_COND_ibm128_libgcc TEST_COND_ibm128
+#ifdef ARG_FLOAT
+# define TEST_COND_ibm128_libgcc (TEST_COND_ibm128 || TEST_COND_arg_ibm128)
+#else
+# define TEST_COND_ibm128_libgcc TEST_COND_ibm128
+#endif
/* Mark a test as expected to fail for ibm128-libgcc. This is used
via XFAIL_ROUNDING_IBM128_LIBGCC, which gen-libm-test.pl transforms
@@ -132,6 +145,16 @@ extern const char doc[];
# define PAYLOAD_DIG (MANT_DIG - 2)
#endif
+/* For narrowing functions, whether the argument format can represent
+ all the given argument values. */
+#define TEST_COND_arg_fmt(MAX_EXP, NUM_ONES, MIN_EXP, MAX_PREC) \
+ (((MAX_EXP) < ARG_MAX_EXP) \
+ && (!TEST_COND_arg_ibm128 \
+ || (MAX_EXP) < ARG_MAX_EXP - 1 \
+ || (NUM_ONES) <= 53) \
+ && (MIN_EXP) >= ARG_MIN_EXP - ARG_MANT_DIG \
+ && (MAX_PREC) <= ARG_MANT_DIG)
+
/* Values underflowing on architectures detecting tininess before
rounding, but not on those detecting tininess after rounding. */
#define UNDERFLOW_EXCEPTION_BEFORE_ROUNDING (TININESS_AFTER_ROUNDING \
@@ -149,7 +172,7 @@ extern const char doc[];
#define TEST_COND_after_rounding TININESS_AFTER_ROUNDING
int enable_test (int);
-void init_max_error (const char *, int);
+void init_max_error (const char *, int, int);
void print_max_error (const char *);
void print_complex_max_error (const char *);
void check_float (const char *, FLOAT, FLOAT, int);
diff --git a/math/test-arg-double.h b/math/test-arg-double.h
new file mode 100644
index 0000000000..4eec144944
--- /dev/null
+++ b/math/test-arg-double.h
@@ -0,0 +1,25 @@
+/* Common definitions for libm tests for double arguments to narrowing
+ functions.
+ Copyright (C) 2018 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/>. */
+
+#define ARG_FUNC(function) function
+#define ARG_FLOAT double
+#define ARG_PREFIX DBL
+#define ARG_LIT(x) (x)
+#define ARG_TYPE_STR "double"
+#define FUNC_NARROW_SUFFIX
diff --git a/math/test-arg-float128.h b/math/test-arg-float128.h
new file mode 100644
index 0000000000..d2a7ef8e70
--- /dev/null
+++ b/math/test-arg-float128.h
@@ -0,0 +1,32 @@
+/* Common definitions for libm tests for _Float128 arguments to
+ narrowing functions.
+ Copyright (C) 2018 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 <bits/floatn.h>
+#include <float.h>
+
+#define ARG_FUNC(function) function ## f128
+#define ARG_FLOAT _Float128
+#define ARG_PREFIX FLT128
+#define ARG_LIT(x) __f128 (x)
+#if FLT128_MANT_DIG == LDBL_MANT_DIG
+# define ARG_TYPE_STR "ldouble"
+#else
+# define ARG_TYPE_STR "float128"
+#endif
+#define FUNC_NARROW_SUFFIX f128
diff --git a/math/test-arg-float32x.h b/math/test-arg-float32x.h
new file mode 100644
index 0000000000..d036f9cce5
--- /dev/null
+++ b/math/test-arg-float32x.h
@@ -0,0 +1,28 @@
+/* Common definitions for libm tests for _Float32x arguments to
+ narrowing functions.
+ Copyright (C) 2018 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 <bits/floatn.h>
+#include <float.h>
+
+#define ARG_FUNC(function) function ## f32x
+#define ARG_FLOAT _Float32x
+#define ARG_PREFIX FLT32X
+#define ARG_LIT(x) __f32x (x)
+#define ARG_TYPE_STR "double"
+#define FUNC_NARROW_SUFFIX f32x
diff --git a/math/test-arg-float64.h b/math/test-arg-float64.h
new file mode 100644
index 0000000000..346711917c
--- /dev/null
+++ b/math/test-arg-float64.h
@@ -0,0 +1,28 @@
+/* Common definitions for libm tests for _Float64 arguments to
+ narrowing functions.
+ Copyright (C) 2018 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 <bits/floatn.h>
+#include <float.h>
+
+#define ARG_FUNC(function) function ## f64
+#define ARG_FLOAT _Float64
+#define ARG_PREFIX FLT64
+#define ARG_LIT(x) __f64 (x)
+#define ARG_TYPE_STR "double"
+#define FUNC_NARROW_SUFFIX f64
diff --git a/math/test-arg-float64x.h b/math/test-arg-float64x.h
new file mode 100644
index 0000000000..c07d908b54
--- /dev/null
+++ b/math/test-arg-float64x.h
@@ -0,0 +1,32 @@
+/* Common definitions for libm tests for _Float64x arguments to
+ narrowing functions.
+ Copyright (C) 2018 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 <bits/floatn.h>
+#include <float.h>
+
+#define ARG_FUNC(function) function ## f64x
+#define ARG_FLOAT _Float64x
+#define ARG_PREFIX FLT64X
+#define ARG_LIT(x) __f64x (x)
+#if FLT64X_MANT_DIG == LDBL_MANT_DIG
+# define ARG_TYPE_STR "ldouble"
+#else
+# define ARG_TYPE_STR "float128"
+#endif
+#define FUNC_NARROW_SUFFIX f64x
diff --git a/math/test-arg-ldouble.h b/math/test-arg-ldouble.h
new file mode 100644
index 0000000000..41b475eae3
--- /dev/null
+++ b/math/test-arg-ldouble.h
@@ -0,0 +1,31 @@
+/* Common definitions for libm tests for long double arguments to
+ narrowing functions.
+ Copyright (C) 2018 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 <float.h>
+
+#define ARG_FUNC(function) function ## l
+#define ARG_FLOAT long double
+#define ARG_PREFIX LDBL
+#define ARG_LIT(x) (x ## L)
+#if LDBL_MANT_DIG == DBL_MANT_DIG
+# define ARG_TYPE_STR "double"
+#else
+# define ARG_TYPE_STR "ldouble"
+#endif
+#define FUNC_NARROW_SUFFIX l
diff --git a/math/test-double.h b/math/test-double.h
index 238b086496..0b0fc96bf1 100644
--- a/math/test-double.h
+++ b/math/test-double.h
@@ -29,3 +29,4 @@
#define FTOSTR strfromd
#define snan_value_MACRO SNAN
#define TEST_FLOATN 0
+#define FUNC_NARROW_PREFIX d
diff --git a/math/test-float.h b/math/test-float.h
index 7e301c3c74..dc3646d008 100644
--- a/math/test-float.h
+++ b/math/test-float.h
@@ -30,3 +30,4 @@
#define FTOSTR strfromf
#define snan_value_MACRO SNANF
#define TEST_FLOATN 0
+#define FUNC_NARROW_PREFIX f
diff --git a/math/test-float128.h b/math/test-float128.h
index 7678913ca9..376d3da11e 100644
--- a/math/test-float128.h
+++ b/math/test-float128.h
@@ -41,3 +41,4 @@
#define LITM(x) x ## f128
#define FTOSTR strfromf128
#define snan_value_MACRO SNANF128
+#define FUNC_NARROW_PREFIX f128
diff --git a/math/test-float32.h b/math/test-float32.h
index 2df9909724..f319fe6268 100644
--- a/math/test-float32.h
+++ b/math/test-float32.h
@@ -35,3 +35,4 @@
#define LITM(x) x ## f32
#define FTOSTR strfromf32
#define snan_value_MACRO SNANF32
+#define FUNC_NARROW_PREFIX f32
diff --git a/math/test-float32x.h b/math/test-float32x.h
index ce02e28809..2aadc4a674 100644
--- a/math/test-float32x.h
+++ b/math/test-float32x.h
@@ -35,3 +35,4 @@
#define LITM(x) x ## f32x
#define FTOSTR strfromf32x
#define snan_value_MACRO SNANF32X
+#define FUNC_NARROW_PREFIX f32x
diff --git a/math/test-float64.h b/math/test-float64.h
index d5c7c84e7d..debdf5aaf6 100644
--- a/math/test-float64.h
+++ b/math/test-float64.h
@@ -35,3 +35,4 @@
#define LITM(x) x ## f64
#define FTOSTR strfromf64
#define snan_value_MACRO SNANF64
+#define FUNC_NARROW_PREFIX f64
diff --git a/math/test-float64x.h b/math/test-float64x.h
index 54c931f2bb..bf1b934311 100644
--- a/math/test-float64x.h
+++ b/math/test-float64x.h
@@ -41,3 +41,4 @@
#define LITM(x) x ## f64x
#define FTOSTR strfromf64x
#define snan_value_MACRO SNANF64X
+#define FUNC_NARROW_PREFIX f64x
diff --git a/math/test-math-narrow.h b/math/test-math-narrow.h
new file mode 100644
index 0000000000..1c7fa30e98
--- /dev/null
+++ b/math/test-math-narrow.h
@@ -0,0 +1,26 @@
+/* Common definitions for libm tests for narrowing scalar functions.
+ Copyright (C) 2018 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/>. */
+
+#define FUNC_TEST(function) \
+ FUNC_TEST_CONCAT (FUNC_NARROW_PREFIX, function, FUNC_NARROW_SUFFIX)
+#define FUNC_TEST_CONCAT(prefix, function, suffix) \
+ _FUNC_TEST_CONCAT (prefix, function, suffix)
+#define _FUNC_TEST_CONCAT(prefix, function, suffix) \
+ prefix ## function ## suffix
+#define TEST_MATHVEC 0
+#define TEST_NARROW 1
diff --git a/math/test-math-scalar.h b/math/test-math-scalar.h
index 764db89f35..8df0d5ddc5 100644
--- a/math/test-math-scalar.h
+++ b/math/test-math-scalar.h
@@ -1,4 +1,4 @@
-/* Common definitions for libm tests for scalar functions.
+/* Common definitions for libm tests for scalar (non-narrowing) functions.
Copyright (C) 1997-2018 Free Software Foundation, Inc.
This file is part of the GNU C Library.
@@ -18,3 +18,4 @@
#define FUNC_TEST(function) FUNC (function)
#define TEST_MATHVEC 0
+#define TEST_NARROW 0
diff --git a/math/test-math-vector.h b/math/test-math-vector.h
index 1592c4a9c3..43d01d064a 100644
--- a/math/test-math-vector.h
+++ b/math/test-math-vector.h
@@ -17,6 +17,7 @@
<http://www.gnu.org/licenses/>. */
#define TEST_MATHVEC 1
+#define TEST_NARROW 0
#define TEST_FINITE 0
#define TEST_ERRNO 0
#define TEST_EXCEPTIONS 0
diff --git a/math/test-narrow-macros.c b/math/test-narrow-macros.c
new file mode 100644
index 0000000000..f53c86ae16
--- /dev/null
+++ b/math/test-narrow-macros.c
@@ -0,0 +1,56 @@
+/* Test code declaring narrowing functions does not conflict with user macros.
+ Copyright (C) 2018 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/>. */
+
+/* The code generating declarations of narrowing functions involves
+ concatenations of fragments of function names that are not
+ themselves reserved; thus, it needs to be arranged so that those
+ fragments are not subject to macro expansion. Verify that
+ inclusion of <math.h> compiles with such fragments defined as
+ macros. */
+
+#define f test macro
+#define d test macro
+#define l test macro
+#define f16 test macro
+#define f32 test macro
+#define f64 test macro
+#define f128 test macro
+#define f32x test macro
+#define f64x test macro
+#define f128x test macro
+#define add test macro
+#define sub test macro
+#define mul test macro
+#define div test macro
+#define dadd test macro
+#define dsub test macro
+#define dmul test macro
+#define ddiv test macro
+#define dsqrt test macro
+#define dfma test macro
+
+#include <math.h>
+
+static int
+do_test (void)
+{
+ /* This is a compilation test. */
+ return 0;
+}
+
+#include <support/test-driver.c>
diff --git a/sysdeps/ieee754/ldbl-opt/Makefile b/sysdeps/ieee754/ldbl-opt/Makefile
index ffc55d1d9a..38afe38ab8 100644
--- a/sysdeps/ieee754/ldbl-opt/Makefile
+++ b/sysdeps/ieee754/ldbl-opt/Makefile
@@ -163,4 +163,7 @@ CFLAGS-nldbl-y0.c = -fno-builtin-y0l
CFLAGS-nldbl-y1.c = -fno-builtin-y1l
CFLAGS-nldbl-yn.c = -fno-builtin-ynl
+tests += test-narrow-macros-ldbl-64
+CFLAGS-test-narrow-macros-ldbl-64.c += -mlong-double-64
+
endif
diff --git a/sysdeps/ieee754/ldbl-opt/test-narrow-macros-ldbl-64.c b/sysdeps/ieee754/ldbl-opt/test-narrow-macros-ldbl-64.c
new file mode 100644
index 0000000000..be92325403
--- /dev/null
+++ b/sysdeps/ieee754/ldbl-opt/test-narrow-macros-ldbl-64.c
@@ -0,0 +1 @@
+#include <math/test-narrow-macros.c>