[committed] libstdc++: Add std::numeric_limits<__float128> specialization [PR104772]
Checks
Commit Message
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
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(""); }
^
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
@@ -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
new file mode 100644
@@ -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