diff options
author | Gabriel F. T. Gomes <gabriel@inconstante.eti.br> | 2017-10-02 14:46:35 -0300 |
---|---|---|
committer | Gabriel F. T. Gomes <gabriel@inconstante.eti.br> | 2017-10-03 16:01:37 -0300 |
commit | aa0235dfdebffe9b338deba51f3ba563ee9b433d (patch) | |
tree | 7ed57f11a759ad2c670a34b99207cb720030ef6a /sysdeps/ieee754/ldbl-128ibm | |
parent | a1132b5e56fe8aaa148ebd249034181863857d60 (diff) | |
download | glibc-aa0235dfdebffe9b338deba51f3ba563ee9b433d.tar.gz |
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.
Diffstat (limited to 'sysdeps/ieee754/ldbl-128ibm')
-rw-r--r-- | sysdeps/ieee754/ldbl-128ibm/bits/iscanonical.h | 21 |
1 files changed, 19 insertions, 2 deletions
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 */ |