public inbox for libstdc++-cvs@sourceware.org
help / color / mirror / Atom feed
From: Jonathan Wakely <redi@gcc.gnu.org>
To: gcc-cvs@gcc.gnu.org, libstdc++-cvs@gcc.gnu.org
Subject: [gcc r14-1582] libstdc++: Make std::numeric_limits<__float128> more portable [PR104772]
Date: Tue,  6 Jun 2023 15:59:15 +0000 (GMT)	[thread overview]
Message-ID: <20230606155915.60B653858D33@sourceware.org> (raw)

https://gcc.gnu.org/g:6261d10521f9fdc2a43d54b4dc365025288aa8e9

commit r14-1582-g6261d10521f9fdc2a43d54b4dc365025288aa8e9
Author: Jonathan Wakely <jwakely@redhat.com>
Date:   Mon Jun 5 16:14:29 2023 +0100

    libstdc++: Make std::numeric_limits<__float128> more portable [PR104772]
    
    This redefines std::numeric_limits<__float128> so that it works with
    non-GCC compilers. The previous definition didn't work with Clang, due
    to it not supporting __builtin_high_valq, __builtin_nanq, and
    __builtin_nansq. It also didn't work in strict modes, due to using Q
    literal suffixes.
    
    The new definition uses the Q suffixes when supported, or calculates the
    correct values using __float128 arithmetic from double values. Ideally
    the values would be defined as hexadecimal-floating-point-literals, but
    that won't work for C++14 and older.
    
    The only member that can't be defined this way is signaling_NaN() which
    still requires a built-in. If __builtin_nansq is not supported, try to
    use __builtin_nansf128 (with a possibly-redundant bit_cast) and if that
    isn't supported, return a quiet NaN and define has_signaling_NaN and
    is_iec754 to be false.
    
    libstdc++-v3/ChangeLog:
    
            PR libstdc++/104772
            * include/std/limits: (numeric_limits<__float128>): Define
            for __STRICT_ANSI__ as well.
            * testsuite/18_support/numeric_limits/128bit.cc: Remove
            check for __STRICT_ANSI__.
    
    Co-authored-by: Jakub Jelinek <jakub@redhat.com>

Diff:
---
 libstdc++-v3/include/std/limits                    | 95 ++++++++++++++++++----
 .../testsuite/18_support/numeric_limits/128bit.cc  |  2 +-
 2 files changed, 80 insertions(+), 17 deletions(-)

diff --git a/libstdc++-v3/include/std/limits b/libstdc++-v3/include/std/limits
index 5f341e63b93..52b19ef8264 100644
--- a/libstdc++-v3/include/std/limits
+++ b/libstdc++-v3/include/std/limits
@@ -2071,9 +2071,11 @@ __glibcxx_float_n(128)
     };
 #endif
 
-#endif
+#endif // C++23
 
-#if defined(_GLIBCXX_USE_FLOAT128) && !defined(__STRICT_ANSI__)
+#if defined(_GLIBCXX_USE_FLOAT128)
+// We either need Q literal suffixes, or IEEE double.
+#if ! defined(__STRICT_ANSI__) || defined(_GLIBCXX_DOUBLE_IS_IEEE_BINARY64)
   __extension__
   template<>
     struct numeric_limits<__float128>
@@ -2082,11 +2084,28 @@ __glibcxx_float_n(128)
 
       static _GLIBCXX_CONSTEXPR __float128
       min() _GLIBCXX_USE_NOEXCEPT
-      { return __extension__ 3.36210314311209350626267781732175260e-4932Q; }
+      {
+#ifdef __STRICT_ANSI__
+	// 0x1.0p-30 * 0x1.0p-16352
+	return double(9.3132257461547852e-10) * _S_1pm16352();
+#else
+	return __extension__ 0x1.0p-16382Q;
+#endif
+      }
 
       static _GLIBCXX_CONSTEXPR __float128
       max() _GLIBCXX_USE_NOEXCEPT
-      { return __extension__ 1.18973149535723176508575932662800702e+4932Q; }
+      {
+#ifdef __STRICT_ANSI__
+	// (0x1.fffffffffffffp+127 + 0x0.fffffffffffffp+75 + 0x0.ffp+23)
+	// * 0x1.0p16256
+	return (__float128(double(3.4028236692093843e+38))
+		  + double(3.7778931862957153e+22) + double(8.35584e+6))
+		 * _S_1p16256();
+#else
+	return __extension__ 0x1.ffffffffffffffffffffffffffffp+16383Q;
+#endif
+      }
 
       static _GLIBCXX_CONSTEXPR __float128
       lowest() _GLIBCXX_USE_NOEXCEPT
@@ -2094,8 +2113,9 @@ __glibcxx_float_n(128)
 
       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);
+#if __cplusplus >= 201103L
+      static constexpr int max_digits10 = 35;
+#endif
       static _GLIBCXX_USE_CONSTEXPR bool is_signed = true;
       static _GLIBCXX_USE_CONSTEXPR bool is_integer = false;
       static _GLIBCXX_USE_CONSTEXPR bool is_exact = false;
@@ -2103,10 +2123,10 @@ __glibcxx_float_n(128)
 
       static _GLIBCXX_CONSTEXPR __float128
       epsilon() _GLIBCXX_USE_NOEXCEPT
-      { return __extension__ 1.92592994438723585305597794258492732e-34Q; }
+      { return double(1.9259299443872359e-34); }
 
       static _GLIBCXX_CONSTEXPR __float128
-      round_error() _GLIBCXX_USE_NOEXCEPT { return __extension__ 0.5Q; }
+      round_error() _GLIBCXX_USE_NOEXCEPT { return 0.5; }
 
       static _GLIBCXX_USE_CONSTEXPR int min_exponent = -16381;
       static _GLIBCXX_USE_CONSTEXPR int min_exponent10 = -4931;
@@ -2115,29 +2135,48 @@ __glibcxx_float_n(128)
 
       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;
+#if __has_builtin(__builtin_nansq) \
+    || (__has_builtin(__builtin_bit_cast) && __has_builtin(__builtin_nansf128))
+      static _GLIBCXX_USE_CONSTEXPR bool has_signaling_NaN = true;
+#else
+      static _GLIBCXX_USE_CONSTEXPR bool has_signaling_NaN = false;
+#endif
       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(); }
+      { return __builtin_huge_val(); }
 
       static _GLIBCXX_CONSTEXPR __float128
       quiet_NaN() _GLIBCXX_USE_NOEXCEPT
-      { return __builtin_nanq(""); }
+      { return __builtin_nan(""); }
 
       static _GLIBCXX_CONSTEXPR __float128
       signaling_NaN() _GLIBCXX_USE_NOEXCEPT
-      { return __builtin_nansq(""); }
+      {
+#if __has_builtin(__builtin_nansq)
+	return __builtin_nansq("");
+#elif __has_builtin(__builtin_bit_cast) && __has_builtin(__builtin_nansf128)
+	return __builtin_bit_cast(__float128, __builtin_nansf128(""));
+#else
+	return quiet_NaN();
+#endif
+      }
 
       static _GLIBCXX_CONSTEXPR __float128
       denorm_min() _GLIBCXX_USE_NOEXCEPT
-      { return __extension__ 6.47517511943802511092443895822764655e-4966Q; }
+      {
+#if defined(__STRICT_ANSI__) || defined(__INTEL_COMPILER)
+	// 0x1.0p-142 * 0x1.0p-16352
+	return double(1.7936620343357659e-43) * _S_1pm16352();
+#else
+	return __extension__ 0x1.0p-16494Q;
+#endif
+      }
 
-      static _GLIBCXX_USE_CONSTEXPR bool is_iec559
-	= has_infinity && has_quiet_NaN && has_denorm == denorm_present;
+      static _GLIBCXX_USE_CONSTEXPR bool is_iec559 = has_signaling_NaN;
       static _GLIBCXX_USE_CONSTEXPR bool is_bounded = true;
       static _GLIBCXX_USE_CONSTEXPR bool is_modulo = false;
 
@@ -2145,8 +2184,32 @@ __glibcxx_float_n(128)
       static _GLIBCXX_USE_CONSTEXPR bool tinyness_before = false;
       static _GLIBCXX_USE_CONSTEXPR float_round_style round_style
 	= round_to_nearest;
+
+#if defined(__STRICT_ANSI__) || defined(__INTEL_COMPILER)
+    private:
+      static _GLIBCXX_CONSTEXPR __float128
+      _S_4p(__float128 __v) _GLIBCXX_USE_NOEXCEPT
+      { return __v * __v * __v * __v; }
+
+      static _GLIBCXX_CONSTEXPR __float128
+      _S_1pm4088() _GLIBCXX_USE_NOEXCEPT
+      { return _S_4p(/* 0x1.0p-1022 */ double(2.2250738585072014e-308)); }
+
+      static _GLIBCXX_CONSTEXPR __float128
+      _S_1pm16352() _GLIBCXX_USE_NOEXCEPT
+      { return _S_4p(_S_1pm4088()); }
+
+      static _GLIBCXX_CONSTEXPR __float128
+      _S_1p4064() _GLIBCXX_USE_NOEXCEPT
+      { return _S_4p(/* 0x1.0p+1016 */ double(7.0222388080559215e+305)); }
+
+      static _GLIBCXX_CONSTEXPR __float128
+      _S_1p16256() _GLIBCXX_USE_NOEXCEPT
+      { return _S_4p(_S_1p4064()); }
+#endif
     };
-#endif // _GLIBCXX_USE_FLOAT128 && ! __STRICT_ANSI__
+#endif // !__STRICT_ANSI__ || DOUBLE_IS_IEEE_BINARY64
+#endif // _GLIBCXX_USE_FLOAT128
 
 _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
index e8ea568df94..b13d83776ba 100644
--- a/libstdc++-v3/testsuite/18_support/numeric_limits/128bit.cc
+++ b/libstdc++-v3/testsuite/18_support/numeric_limits/128bit.cc
@@ -2,7 +2,7 @@
 
 #include <limits>
 
-#if __SIZEOF_FLOAT128__ && !defined __STRICT_ANSI__
+#if __SIZEOF_FLOAT128__
 __extension__ template class std::numeric_limits<__float128>;
 #endif

                 reply	other threads:[~2023-06-06 15:59 UTC|newest]

Thread overview: [no followups] expand[flat|nested]  mbox.gz  Atom feed

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20230606155915.60B653858D33@sourceware.org \
    --to=redi@gcc.gnu.org \
    --cc=gcc-cvs@gcc.gnu.org \
    --cc=libstdc++-cvs@gcc.gnu.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).