251 lines
10 KiB
Diff
251 lines
10 KiB
Diff
|
From 3b10c5d2abb0392d5ecfd865e2eb911ac109e36f Mon Sep 17 00:00:00 2001
|
|||
|
From: "Gabriel F. T. Gomes" <gabriel@inconstante.eti.br>
|
|||
|
Date: Mon, 2 Oct 2017 14:46:35 -0300
|
|||
|
Subject: [PATCH 45] 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.
|
|||
|
|
|||
|
(cherry picked from commit aa0235dfdebffe9b338deba51f3ba563ee9b433d)
|
|||
|
---
|
|||
|
ChangeLog | 15 ++++++++
|
|||
|
NEWS | 1 +
|
|||
|
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 +
|
|||
|
8 files changed, 106 insertions(+), 5 deletions(-)
|
|||
|
create mode 100644 math/test-math-iscanonical.cc
|
|||
|
|
|||
|
diff --git a/ChangeLog b/ChangeLog
|
|||
|
index cc763ac065..fea4fd0cd6 100644
|
|||
|
--- a/ChangeLog
|
|||
|
+++ b/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-08-22 Joseph Myers <joseph@codesourcery.com>
|
|||
|
|
|||
|
[BZ #21987]
|
|||
|
diff --git a/NEWS b/NEWS
|
|||
|
index 8e468c0369..5b05edeb4f 100644
|
|||
|
--- a/NEWS
|
|||
|
+++ b/NEWS
|
|||
|
@@ -35,6 +35,7 @@ The following bugs are resolved with this release:
|
|||
|
[22096] resolv: __resolv_conf_attach must not free passed conf object
|
|||
|
[22146] Let fpclassify use the builtin when optimizing for size in C++ mode
|
|||
|
[22225] math: nearbyint arithmetic moved before feholdexcept
|
|||
|
+ [22235] Add C++ versions of iscanonical for ldbl-96 and ldbl-128ibm
|
|||
|
|
|||
|
Version 2.26
|
|||
|
|
|||
|
diff --git a/math/Makefile b/math/Makefile
|
|||
|
index 0130fcf38b..2c17c68eda 100644
|
|||
|
--- a/math/Makefile
|
|||
|
+++ b/math/Makefile
|
|||
|
@@ -203,7 +203,8 @@ tests-static = test-fpucw-static test-fpucw-ieee-static \
|
|||
|
test-signgam-ullong-static test-signgam-ullong-init-static
|
|||
|
|
|||
|
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))
|
|||
|
@@ -351,6 +352,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 f9348ec3ea..2b216c6da1 100644
|
|||
|
--- a/math/math.h
|
|||
|
+++ b/math/math.h
|
|||
|
@@ -488,7 +488,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
|
|||
|
+ <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>
|
|||
|
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 dea2290736..cf2dbfb673 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: \
|
|||
|
|