From aa0235dfdebffe9b338deba51f3ba563ee9b433d Mon Sep 17 00:00:00 2001 From: "Gabriel F. T. Gomes" Date: Mon, 2 Oct 2017 14:46:35 -0300 Subject: Add C++ versions of iscanonical for ldbl-96 and ldbl-128ibm (bug 22235) All representations of floating-point numbers in types with IEC 60559 binary exchange format are canonical. On the other hand, types with IEC 60559 extended formats, such as those implemented under ldbl-96 and ldbl-128ibm, contain representations that are not canonical. TS 18661-1 introduced the type-generic macro iscanonical, which returns whether a floating-point value is canonical or not. In Glibc, this type-generic macro is implemented using the macro __MATH_TG, which, when support for float128 is enabled, relies on __builtin_types_compatible_p to select between floating-point types. However, this use of iscanonical breaks C++ applications, because the builtin is only available in C mode. This patch provides a C++ implementation of iscanonical that relies on function overloading, rather than builtins, to select between floating-point types. Unlike the C++ implementations for iszero and issignaling, this implementation ignores __NO_LONG_DOUBLE_MATH. The double type always matches IEC 60559 double format, which is always canonical. Thus, when double and long double are the same (__NO_LONG_DOUBLE_MATH), iscanonical always returns 1 and is not implemented with __MATH_TG. Tested for powerpc64, powerpc64le and x86_64. [BZ #22235] * math/math.h: Trivial fix for unbalanced parentheses in comment. * math/Makefile [CXX] (tests): Add test-math-iscanonical.cc. (CFLAGS-test-math-iscanonical.cc): New variable. * math/test-math-iscanonical.cc: New file. * sysdeps/ieee754/ldbl-96/bits/iscanonical.h (iscanonical): Provide a C++ implementation based on function overloading, rather than using __MATH_TG, which uses C-only builtins. * sysdeps/ieee754/ldbl-128ibm/bits/iscanonical.h (iscanonical): Likewise. * sysdeps/powerpc/powerpc64le/Makefile (CFLAGS-test-math-iscanonical.cc): New variable. --- ChangeLog | 15 ++++++++ math/Makefile | 4 ++- math/math.h | 2 +- math/test-math-iscanonical.cc | 48 ++++++++++++++++++++++++++ sysdeps/ieee754/ldbl-128ibm/bits/iscanonical.h | 21 +++++++++-- sysdeps/ieee754/ldbl-96/bits/iscanonical.h | 19 +++++++++- sysdeps/powerpc/powerpc64le/Makefile | 1 + 7 files changed, 105 insertions(+), 5 deletions(-) create mode 100644 math/test-math-iscanonical.cc diff --git a/ChangeLog b/ChangeLog index 3958723d6f..6a028845c4 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,18 @@ +2017-10-03 Gabriel F. T. Gomes + + [BZ #22235] + * math/math.h: Trivial fix for unbalanced parentheses in comment. + * math/Makefile [CXX] (tests): Add test-math-iscanonical.cc. + (CFLAGS-test-math-iscanonical.cc): New variable. + * math/test-math-iscanonical.cc: New file. + * sysdeps/ieee754/ldbl-96/bits/iscanonical.h (iscanonical): + Provide a C++ implementation based on function overloading, + rather than using __MATH_TG, which uses C-only builtins. + * sysdeps/ieee754/ldbl-128ibm/bits/iscanonical.h (iscanonical): + Likewise. + * sysdeps/powerpc/powerpc64le/Makefile + (CFLAGS-test-math-iscanonical.cc): New variable. + 2017-10-03 Joseph Myers * sysdeps/ieee754/dbl-64/s_ceil.c: Include . diff --git a/math/Makefile b/math/Makefile index 6c8aa3e413..008eeb2d18 100644 --- a/math/Makefile +++ b/math/Makefile @@ -208,7 +208,8 @@ tests-internal = test-matherr test-matherr-2 tests-static += atest-exp atest-sincos atest-exp2 ifneq (,$(CXX)) -tests += test-math-isinff test-math-iszero test-math-issignaling +tests += test-math-isinff test-math-iszero test-math-issignaling \ + test-math-iscanonical endif ifneq (no,$(PERL)) @@ -356,6 +357,7 @@ CFLAGS-test-signgam-ullong-init-static.c = -std=c99 CFLAGS-test-math-isinff.cc = -std=gnu++11 CFLAGS-test-math-iszero.cc = -std=gnu++11 CFLAGS-test-math-issignaling.cc = -std=gnu++11 +CFLAGS-test-math-iscanonical.cc = -std=gnu++11 CFLAGS-test-iszero-excess-precision.c = -fexcess-precision=standard CFLAGS-test-iseqsig-excess-precision.c = -fexcess-precision=standard diff --git a/math/math.h b/math/math.h index e72c12f67e..faa2481731 100644 --- a/math/math.h +++ b/math/math.h @@ -518,7 +518,7 @@ enum other hand, overloading provides the means to distinguish between the floating-point types. The overloading resolution will match the correct parameter (regardless of type qualifiers (i.e.: const - and volatile). */ + and volatile)). */ extern "C++" { inline int issignaling (float __val) { return __issignalingf (__val); } inline int issignaling (double __val) { return __issignaling (__val); } diff --git a/math/test-math-iscanonical.cc b/math/test-math-iscanonical.cc new file mode 100644 index 0000000000..aba68acb4f --- /dev/null +++ b/math/test-math-iscanonical.cc @@ -0,0 +1,48 @@ +/* Test for the C++ implementation of iscanonical. + Copyright (C) 2017 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 + . */ + +#define _GNU_SOURCE 1 +#include +#include + +static bool errors; + +template +static void +check_type () +{ + T val = 0; + + /* Check if iscanonical is available in C++ mode (bug 22235). */ + if (iscanonical (val) == 0) + errors++; +} + +static int +do_test (void) +{ + check_type (); + check_type (); + check_type (); +#if __HAVE_DISTINCT_FLOAT128 + check_type<_Float128> (); +#endif + return errors; +} + +#include diff --git a/sysdeps/ieee754/ldbl-128ibm/bits/iscanonical.h b/sysdeps/ieee754/ldbl-128ibm/bits/iscanonical.h index 7ddb368d26..f756857c03 100644 --- a/sysdeps/ieee754/ldbl-128ibm/bits/iscanonical.h +++ b/sysdeps/ieee754/ldbl-128ibm/bits/iscanonical.h @@ -37,5 +37,22 @@ 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) __MATH_TG ((x), __iscanonical, (x)) -#endif +# ifndef __cplusplus +# define iscanonical(x) __MATH_TG ((x), __iscanonical, (x)) +# else +/* In C++ mode, __MATH_TG cannot be used, because it relies on + __builtin_types_compatible_p, which is a C-only builtin. On the + other hand, overloading provides the means to distinguish between + the floating-point types. The overloading resolution will match + the correct parameter (regardless of type qualifiers (i.e.: const + and volatile)). */ +extern "C++" { +inline int iscanonical (float __val) { return __iscanonicalf (__val); } +inline int iscanonical (double __val) { return __iscanonical (__val); } +inline int iscanonical (long double __val) { return __iscanonicall (__val); } +# if __HAVE_DISTINCT_FLOAT128 +inline int iscanonical (_Float128 __val) { return __iscanonicalf128 (__val); } +# endif +} +# endif /* __cplusplus */ +#endif /* __NO_LONG_DOUBLE_MATH */ diff --git a/sysdeps/ieee754/ldbl-96/bits/iscanonical.h b/sysdeps/ieee754/ldbl-96/bits/iscanonical.h index 4a4f4ad024..cfa36a0c2a 100644 --- a/sysdeps/ieee754/ldbl-96/bits/iscanonical.h +++ b/sysdeps/ieee754/ldbl-96/bits/iscanonical.h @@ -34,4 +34,21 @@ 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) __MATH_TG ((x), __iscanonical, (x)) +#ifndef __cplusplus +# define iscanonical(x) __MATH_TG ((x), __iscanonical, (x)) +#else +/* In C++ mode, __MATH_TG cannot be used, because it relies on + __builtin_types_compatible_p, which is a C-only builtin. On the + other hand, overloading provides the means to distinguish between + the floating-point types. The overloading resolution will match + the correct parameter (regardless of type qualifiers (i.e.: const + and volatile)). */ +extern "C++" { +inline int iscanonical (float __val) { return __iscanonicalf (__val); } +inline int iscanonical (double __val) { return __iscanonical (__val); } +inline int iscanonical (long double __val) { return __iscanonicall (__val); } +# if __HAVE_DISTINCT_FLOAT128 +inline int iscanonical (_Float128 __val) { return __iscanonicalf128 (__val); } +# endif +} +#endif /* __cplusplus */ diff --git a/sysdeps/powerpc/powerpc64le/Makefile b/sysdeps/powerpc/powerpc64le/Makefile index 3fd9d9a715..f554a791b7 100644 --- a/sysdeps/powerpc/powerpc64le/Makefile +++ b/sysdeps/powerpc/powerpc64le/Makefile @@ -16,6 +16,7 @@ $(foreach suf,$(all-object-suffixes),%f128_r$(suf)): CFLAGS += -mfloat128 $(foreach suf,$(all-object-suffixes),$(objpfx)test-float128%$(suf)): CFLAGS += -mfloat128 $(foreach suf,$(all-object-suffixes),$(objpfx)test-ifloat128%$(suf)): CFLAGS += -mfloat128 CFLAGS-libm-test-support-float128.c += -mfloat128 +CFLAGS-test-math-iscanonical.cc += -mfloat128 CFLAGS-test-math-issignaling.cc += -mfloat128 CFLAGS-test-math-iszero.cc += -mfloat128 $(objpfx)test-float128% $(objpfx)test-ifloat128% $(objpfx)test-math-iszero: \ -- cgit 1.4.1