diff mbox series

[committed] libstdc++: Add std::numeric_limits<__float128> specialization [PR104772]

Message ID 20230531122239.4116906-1-jwakely@redhat.com
State New
Headers show
Series [committed] libstdc++: Add std::numeric_limits<__float128> specialization [PR104772] | expand

Commit Message

Jonathan Wakely May 31, 2023, 12:22 p.m. UTC
Tested powerpc64le-linux. Pushed to trunk.

-- >8 --

As suggested by Jakub in the PR, this just hardcodes the constants with
a Q suffix, since the properties of __float128 are not going to change.

We can only define it for non-strict modes because the suffix gives an
error otherwise, even in system headers:

limits:2085: error: unable to find numeric literal operator 'operator""Q'

libstdc++-v3/ChangeLog:

	PR libstdc++/104772
	* include/std/limits (numeric_limits<__float128>): Define.
	* testsuite/18_support/numeric_limits/128bit.cc: New test.
---
 libstdc++-v3/include/std/limits               | 75 +++++++++++++++++++
 .../18_support/numeric_limits/128bit.cc       | 12 +++
 2 files changed, 87 insertions(+)
 create mode 100644 libstdc++-v3/testsuite/18_support/numeric_limits/128bit.cc

Comments

Jonathan Wakely May 31, 2023, 2:04 p.m. UTC | #1
On Wed, 31 May 2023 at 13:23, Jonathan Wakely via Libstdc++ <
libstdc++@gcc.gnu.org> wrote:

> Tested powerpc64le-linux. Pushed to trunk.
>
> -- >8 --
>
> As suggested by Jakub in the PR, this just hardcodes the constants with
> a Q suffix, since the properties of __float128 are not going to change.
>
> We can only define it for non-strict modes because the suffix gives an
> error otherwise, even in system headers:
>
> limits:2085: error: unable to find numeric literal operator 'operator""Q'
>
> libstdc++-v3/ChangeLog:
>
>         PR libstdc++/104772
>         * include/std/limits (numeric_limits<__float128>): Define.
>         * testsuite/18_support/numeric_limits/128bit.cc: New test.
>

I should have tested this with clang before pushing:

/home/jwakely/gcc/latest/lib/gcc/x86_64-pc-linux-gnu/14.0.0/../../../../include/c++/14.0.0/limits:2125:
16: error: use of undeclared identifier '__builtin_huge_valq'
     { return __builtin_huge_valq(); }
              ^
/home/jwakely/gcc/latest/lib/gcc/x86_64-pc-linux-gnu/14.0.0/../../../../include/c++/14.0.0/limits:2129:
16: error: use of undeclared identifier '__builtin_nanq'
     { return __builtin_nanq(""); }
              ^
/home/jwakely/gcc/latest/lib/gcc/x86_64-pc-linux-gnu/14.0.0/../../../../include/c++/14.0.0/limits:2133:
16: error: use of undeclared identifier '__builtin_nansq'
     { return __builtin_nansq(""); }
              ^
Jakub Jelinek May 31, 2023, 2:15 p.m. UTC | #2
On Wed, May 31, 2023 at 03:04:03PM +0100, Jonathan Wakely via Gcc-patches wrote:
> On Wed, 31 May 2023 at 13:23, Jonathan Wakely via Libstdc++ <
> libstdc++@gcc.gnu.org> wrote:
> 
> > Tested powerpc64le-linux. Pushed to trunk.
> >
> > -- >8 --
> >
> > As suggested by Jakub in the PR, this just hardcodes the constants with
> > a Q suffix, since the properties of __float128 are not going to change.
> >
> > We can only define it for non-strict modes because the suffix gives an
> > error otherwise, even in system headers:
> >
> > limits:2085: error: unable to find numeric literal operator 'operator""Q'
> >
> > libstdc++-v3/ChangeLog:
> >
> >         PR libstdc++/104772
> >         * include/std/limits (numeric_limits<__float128>): Define.
> >         * testsuite/18_support/numeric_limits/128bit.cc: New test.
> >
> 
> I should have tested this with clang before pushing:
> 
> /home/jwakely/gcc/latest/lib/gcc/x86_64-pc-linux-gnu/14.0.0/../../../../include/c++/14.0.0/limits:2125:
> 16: error: use of undeclared identifier '__builtin_huge_valq'
>      { return __builtin_huge_valq(); }
>               ^
> /home/jwakely/gcc/latest/lib/gcc/x86_64-pc-linux-gnu/14.0.0/../../../../include/c++/14.0.0/limits:2129:
> 16: error: use of undeclared identifier '__builtin_nanq'
>      { return __builtin_nanq(""); }
>               ^
> /home/jwakely/gcc/latest/lib/gcc/x86_64-pc-linux-gnu/14.0.0/../../../../include/c++/14.0.0/limits:2133:
> 16: error: use of undeclared identifier '__builtin_nansq'
>      { return __builtin_nansq(""); }
>               ^

See my comments in bugzilla how to support this stuff even without
being able to use Q suffixes.
As for the builtins, no reason not to use __float128(__builtin_huge_val())
for the first case or __float128(__builtin_nan("")) for the second case.
I'm afraid there is nothing that can be done about signalling NaN
of neither __builtin_nansq nor __builtin_nansf128 is supported.

	Jakub
diff mbox series

Patch

diff --git a/libstdc++-v3/include/std/limits b/libstdc++-v3/include/std/limits
index 8bafd6fb972..5f341e63b93 100644
--- a/libstdc++-v3/include/std/limits
+++ b/libstdc++-v3/include/std/limits
@@ -2073,6 +2073,81 @@  __glibcxx_float_n(128)
 
 #endif
 
+#if defined(_GLIBCXX_USE_FLOAT128) && !defined(__STRICT_ANSI__)
+  __extension__
+  template<>
+    struct numeric_limits<__float128>
+    {
+      static _GLIBCXX_USE_CONSTEXPR bool is_specialized = true;
+
+      static _GLIBCXX_CONSTEXPR __float128
+      min() _GLIBCXX_USE_NOEXCEPT
+      { return __extension__ 3.36210314311209350626267781732175260e-4932Q; }
+
+      static _GLIBCXX_CONSTEXPR __float128
+      max() _GLIBCXX_USE_NOEXCEPT
+      { return __extension__ 1.18973149535723176508575932662800702e+4932Q; }
+
+      static _GLIBCXX_CONSTEXPR __float128
+      lowest() _GLIBCXX_USE_NOEXCEPT
+      { return -max(); }
+
+      static _GLIBCXX_USE_CONSTEXPR int digits = 113;
+      static _GLIBCXX_USE_CONSTEXPR int digits10 = 33;
+      static _GLIBCXX_USE_CONSTEXPR int max_digits10
+	= __glibcxx_max_digits10 (112);
+      static _GLIBCXX_USE_CONSTEXPR bool is_signed = true;
+      static _GLIBCXX_USE_CONSTEXPR bool is_integer = false;
+      static _GLIBCXX_USE_CONSTEXPR bool is_exact = false;
+      static _GLIBCXX_USE_CONSTEXPR int radix = __FLT_RADIX__;
+
+      static _GLIBCXX_CONSTEXPR __float128
+      epsilon() _GLIBCXX_USE_NOEXCEPT
+      { return __extension__ 1.92592994438723585305597794258492732e-34Q; }
+
+      static _GLIBCXX_CONSTEXPR __float128
+      round_error() _GLIBCXX_USE_NOEXCEPT { return __extension__ 0.5Q; }
+
+      static _GLIBCXX_USE_CONSTEXPR int min_exponent = -16381;
+      static _GLIBCXX_USE_CONSTEXPR int min_exponent10 = -4931;
+      static _GLIBCXX_USE_CONSTEXPR int max_exponent = 16384;
+      static _GLIBCXX_USE_CONSTEXPR int max_exponent10 = 4932;
+
+      static _GLIBCXX_USE_CONSTEXPR bool has_infinity = 1;
+      static _GLIBCXX_USE_CONSTEXPR bool has_quiet_NaN = 1;
+      static _GLIBCXX_USE_CONSTEXPR bool has_signaling_NaN = has_quiet_NaN;
+      static _GLIBCXX_USE_CONSTEXPR float_denorm_style has_denorm
+	= denorm_present;
+      static _GLIBCXX_USE_CONSTEXPR bool has_denorm_loss = false;
+
+      static _GLIBCXX_CONSTEXPR __float128
+      infinity() _GLIBCXX_USE_NOEXCEPT
+      { return __builtin_huge_valq(); }
+
+      static _GLIBCXX_CONSTEXPR __float128
+      quiet_NaN() _GLIBCXX_USE_NOEXCEPT
+      { return __builtin_nanq(""); }
+
+      static _GLIBCXX_CONSTEXPR __float128
+      signaling_NaN() _GLIBCXX_USE_NOEXCEPT
+      { return __builtin_nansq(""); }
+
+      static _GLIBCXX_CONSTEXPR __float128
+      denorm_min() _GLIBCXX_USE_NOEXCEPT
+      { return __extension__ 6.47517511943802511092443895822764655e-4966Q; }
+
+      static _GLIBCXX_USE_CONSTEXPR bool is_iec559
+	= has_infinity && has_quiet_NaN && has_denorm == denorm_present;
+      static _GLIBCXX_USE_CONSTEXPR bool is_bounded = true;
+      static _GLIBCXX_USE_CONSTEXPR bool is_modulo = false;
+
+      static _GLIBCXX_USE_CONSTEXPR bool traps = false;
+      static _GLIBCXX_USE_CONSTEXPR bool tinyness_before = false;
+      static _GLIBCXX_USE_CONSTEXPR float_round_style round_style
+	= round_to_nearest;
+    };
+#endif // _GLIBCXX_USE_FLOAT128 && ! __STRICT_ANSI__
+
 _GLIBCXX_END_NAMESPACE_VERSION
 } // namespace
 
diff --git a/libstdc++-v3/testsuite/18_support/numeric_limits/128bit.cc b/libstdc++-v3/testsuite/18_support/numeric_limits/128bit.cc
new file mode 100644
index 00000000000..e8ea568df94
--- /dev/null
+++ b/libstdc++-v3/testsuite/18_support/numeric_limits/128bit.cc
@@ -0,0 +1,12 @@ 
+// { dg-do compile }
+
+#include <limits>
+
+#if __SIZEOF_FLOAT128__ && !defined __STRICT_ANSI__
+__extension__ template class std::numeric_limits<__float128>;
+#endif
+
+#if __SIZEOF_INT128__
+__extension__ template class std::numeric_limits<__int128>;
+__extension__ template class std::numeric_limits<unsigned __int128>;
+#endif