mirror of
https://sourceware.org/git/glibc.git
synced 2025-08-10 05:03:06 +03:00
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.
This commit is contained in:
15
ChangeLog
15
ChangeLog
@@ -1,3 +1,18 @@
|
|||||||
|
2017-10-03 Gabriel F. T. Gomes <gabriel@inconstante.eti.br>
|
||||||
|
|
||||||
|
[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 <joseph@codesourcery.com>
|
2017-10-03 Joseph Myers <joseph@codesourcery.com>
|
||||||
|
|
||||||
* sysdeps/ieee754/dbl-64/s_ceil.c: Include <libm-alias-double.h>.
|
* sysdeps/ieee754/dbl-64/s_ceil.c: Include <libm-alias-double.h>.
|
||||||
|
@@ -208,7 +208,8 @@ tests-internal = test-matherr test-matherr-2
|
|||||||
tests-static += atest-exp atest-sincos atest-exp2
|
tests-static += atest-exp atest-sincos atest-exp2
|
||||||
|
|
||||||
ifneq (,$(CXX))
|
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
|
endif
|
||||||
|
|
||||||
ifneq (no,$(PERL))
|
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-isinff.cc = -std=gnu++11
|
||||||
CFLAGS-test-math-iszero.cc = -std=gnu++11
|
CFLAGS-test-math-iszero.cc = -std=gnu++11
|
||||||
CFLAGS-test-math-issignaling.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-iszero-excess-precision.c = -fexcess-precision=standard
|
||||||
CFLAGS-test-iseqsig-excess-precision.c = -fexcess-precision=standard
|
CFLAGS-test-iseqsig-excess-precision.c = -fexcess-precision=standard
|
||||||
|
@@ -518,7 +518,7 @@ enum
|
|||||||
other hand, overloading provides the means to distinguish between
|
other hand, overloading provides the means to distinguish between
|
||||||
the floating-point types. The overloading resolution will match
|
the floating-point types. The overloading resolution will match
|
||||||
the correct parameter (regardless of type qualifiers (i.e.: const
|
the correct parameter (regardless of type qualifiers (i.e.: const
|
||||||
and volatile). */
|
and volatile)). */
|
||||||
extern "C++" {
|
extern "C++" {
|
||||||
inline int issignaling (float __val) { return __issignalingf (__val); }
|
inline int issignaling (float __val) { return __issignalingf (__val); }
|
||||||
inline int issignaling (double __val) { return __issignaling (__val); }
|
inline int issignaling (double __val) { return __issignaling (__val); }
|
||||||
|
48
math/test-math-iscanonical.cc
Normal file
48
math/test-math-iscanonical.cc
Normal file
@@ -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
|
||||||
|
<http://www.gnu.org/licenses/>. */
|
||||||
|
|
||||||
|
#define _GNU_SOURCE 1
|
||||||
|
#include <math.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
static bool errors;
|
||||||
|
|
||||||
|
template <class T>
|
||||||
|
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<float> ();
|
||||||
|
check_type<double> ();
|
||||||
|
check_type<long double> ();
|
||||||
|
#if __HAVE_DISTINCT_FLOAT128
|
||||||
|
check_type<_Float128> ();
|
||||||
|
#endif
|
||||||
|
return errors;
|
||||||
|
}
|
||||||
|
|
||||||
|
#include <support/test-driver.c>
|
@@ -37,5 +37,22 @@ extern int __iscanonicall (long double __x)
|
|||||||
conversion, before being discarded; in IBM long double, there are
|
conversion, before being discarded; in IBM long double, there are
|
||||||
encodings that are not consistently handled as corresponding to any
|
encodings that are not consistently handled as corresponding to any
|
||||||
particular value of the type, and we return 0 for those. */
|
particular value of the type, and we return 0 for those. */
|
||||||
# define iscanonical(x) __MATH_TG ((x), __iscanonical, (x))
|
# ifndef __cplusplus
|
||||||
#endif
|
# 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 */
|
||||||
|
@@ -34,4 +34,21 @@ extern int __iscanonicall (long double __x)
|
|||||||
conversion, before being discarded; in extended precision, there
|
conversion, before being discarded; in extended precision, there
|
||||||
are encodings that are not consistently handled as corresponding to
|
are encodings that are not consistently handled as corresponding to
|
||||||
any particular value of the type, and we return 0 for those. */
|
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 */
|
||||||
|
@@ -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-float128%$(suf)): CFLAGS += -mfloat128
|
||||||
$(foreach suf,$(all-object-suffixes),$(objpfx)test-ifloat128%$(suf)): CFLAGS += -mfloat128
|
$(foreach suf,$(all-object-suffixes),$(objpfx)test-ifloat128%$(suf)): CFLAGS += -mfloat128
|
||||||
CFLAGS-libm-test-support-float128.c += -mfloat128
|
CFLAGS-libm-test-support-float128.c += -mfloat128
|
||||||
|
CFLAGS-test-math-iscanonical.cc += -mfloat128
|
||||||
CFLAGS-test-math-issignaling.cc += -mfloat128
|
CFLAGS-test-math-issignaling.cc += -mfloat128
|
||||||
CFLAGS-test-math-iszero.cc += -mfloat128
|
CFLAGS-test-math-iszero.cc += -mfloat128
|
||||||
$(objpfx)test-float128% $(objpfx)test-ifloat128% $(objpfx)test-math-iszero: \
|
$(objpfx)test-float128% $(objpfx)test-ifloat128% $(objpfx)test-math-iszero: \
|
||||||
|
Reference in New Issue
Block a user