1
0
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:
Gabriel F. T. Gomes
2017-10-02 14:46:35 -03:00
parent a1132b5e56
commit aa0235dfde
7 changed files with 105 additions and 5 deletions

View File

@@ -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>.

View File

@@ -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

View File

@@ -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); }

View 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>

View File

@@ -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 */

View File

@@ -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 */

View File

@@ -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: \