Greetings,

I know people are mostly looking at release branch work but I'd like to post this.  Other projects like mppp and boost use our __float128 with C++.  I use it for specfun testing and various other projects. I'd like to offer a series of patches to enable this support straight from libstdc++.  This is the first patch. Next will be <cmath> and then <complex> a bit later.

It's pretty straightforward but others might have tips on configuration (and anything else ;-)).  Built and tested of x86_64-linux.

Ok?

Ed


2019-05-11  Ed Smith-Rowland  <3dw...@verizon.net>

        Implement numeric_limits<__float128>.
        * include/std/limits: Copy limit macros from quadmath.h;
        (__glibcxx_float128_has_denorm_loss, __glibcxx_float128_traps,
        __glibcxx_float128_tinyness_before): New macros (set to false);
        (numeric_limits<__float128>): New specialization.
        * : Add __float128 test guarded by _GLIBCXX_USE_FLOAT128.
        * : testsuite/18_support/numeric_limits/denorm_min.cc: Add __float128
        test guarded by _GLIBCXX_USE_FLOAT128.
        * : testsuite/18_support/numeric_limits/dr559.cc: Same.
        * : testsuite/18_support/numeric_limits/epsilon.cc: Same.
        * : testsuite/18_support/numeric_limits/infinity.cc: Same.
        * : testsuite/18_support/numeric_limits/is_iec559.cc: Same.
        * : testsuite/18_support/numeric_limits/lowest.cc: Same.
        * : testsuite/18_support/numeric_limits/max_digits10.cc: Same.
        * : testsuite/18_support/numeric_limits/min_max.cc: Same.
        * : testsuite/18_support/numeric_limits/quiet_NaN.cc: Same.

Index: include/std/limits
===================================================================
--- include/std/limits  (revision 271076)
+++ include/std/limits  (working copy)
@@ -41,6 +41,19 @@
 
 #include <bits/c++config.h>
 
+#if defined(_GLIBCXX_USE_FLOAT128) && !defined(__STRICT_ANSI__)
+#  define FLT128_MAX 1.18973149535723176508575932662800702e4932Q
+#  define FLT128_MIN 3.36210314311209350626267781732175260e-4932Q
+#  define FLT128_EPSILON 1.92592994438723585305597794258492732e-34Q
+#  define FLT128_DENORM_MIN 6.475175119438025110924438958227646552e-4966Q
+#  define FLT128_MANT_DIG 113
+#  define FLT128_MIN_EXP (-16381)
+#  define FLT128_MAX_EXP 16384
+#  define FLT128_DIG 33
+#  define FLT128_MIN_10_EXP (-4931)
+#  define FLT128_MAX_10_EXP 4932
+#endif
+
 //
 // The numeric_limits<> traits document implementation-defined aspects
 // of fundamental arithmetic data types (integers and floating points).
@@ -123,6 +136,24 @@
 #  define __glibcxx_long_double_tinyness_before false
 #endif
 
+#if defined(_GLIBCXX_USE_FLOAT128) && !defined(__STRICT_ANSI__)
+
+// __float128
+
+// Default values.  Should be overridden in configuration files if necessary.
+
+#  ifndef __glibcxx_float128_has_denorm_loss
+#    define __glibcxx_float128_has_denorm_loss false
+#  endif
+#  ifndef __glibcxx_float128_traps
+#    define __glibcxx_float128_traps false
+#  endif
+#  ifndef __glibcxx_float128_tinyness_before
+#    define __glibcxx_float128_tinyness_before false
+#  endif
+
+#  endif // _GLIBCXX_USE_FLOAT128
+
 // You should not need to define any macros below this point.
 
 #define __glibcxx_signed_b(T,B)        ((T)(-1) < 0)
@@ -1880,6 +1911,85 @@
 #undef __glibcxx_long_double_traps
 #undef __glibcxx_long_double_tinyness_before
 
+#if defined(_GLIBCXX_USE_FLOAT128) && !defined(__STRICT_ANSI__)
+
+  /// numeric_limits<__float128> specialization.
+  template<>
+    struct numeric_limits<__float128>
+    {
+      static _GLIBCXX_USE_CONSTEXPR bool is_specialized = true;
+
+      static _GLIBCXX_CONSTEXPR __float128
+      min() _GLIBCXX_USE_NOEXCEPT { return FLT128_MIN; }
+
+      static _GLIBCXX_CONSTEXPR __float128
+      max() _GLIBCXX_USE_NOEXCEPT { return FLT128_MAX; }
+
+#if __cplusplus >= 201103L
+      static _GLIBCXX_CONSTEXPR __float128
+      lowest() _GLIBCXX_USE_NOEXCEPT { return -FLT128_MAX; }
+#endif
+
+      static _GLIBCXX_USE_CONSTEXPR int digits = FLT128_MANT_DIG;
+      static _GLIBCXX_USE_CONSTEXPR int digits10 = FLT128_DIG;
+#if __cplusplus >= 201103L
+      static _GLIBCXX_USE_CONSTEXPR int max_digits10
+        = __glibcxx_max_digits10 (FLT128_MANT_DIG);
+#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;
+      static _GLIBCXX_USE_CONSTEXPR int radix = __FLT_RADIX__;
+
+      static _GLIBCXX_CONSTEXPR __float128
+      epsilon() _GLIBCXX_USE_NOEXCEPT { return FLT128_EPSILON; }
+
+      static _GLIBCXX_CONSTEXPR __float128
+      round_error() _GLIBCXX_USE_NOEXCEPT { return 0.5Q; }
+
+      static _GLIBCXX_USE_CONSTEXPR int min_exponent = FLT128_MIN_EXP;
+      static _GLIBCXX_USE_CONSTEXPR int min_exponent10 = FLT128_MIN_10_EXP;
+      static _GLIBCXX_USE_CONSTEXPR int max_exponent = FLT128_MAX_EXP;
+      static _GLIBCXX_USE_CONSTEXPR int max_exponent10 = FLT128_MAX_10_EXP;
+
+      static _GLIBCXX_USE_CONSTEXPR bool has_infinity = true;
+      static _GLIBCXX_USE_CONSTEXPR bool has_quiet_NaN = true;
+      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
+       = __glibcxx_float128_has_denorm_loss;
+
+      static _GLIBCXX_CONSTEXPR __float128
+      infinity() _GLIBCXX_USE_NOEXCEPT { return __builtin_infq(); }
+
+      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 FLT128_DENORM_MIN; }
+
+      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 = __glibcxx_float128_traps;
+      static _GLIBCXX_USE_CONSTEXPR bool tinyness_before
+       = __glibcxx_float128_tinyness_before;
+      static _GLIBCXX_USE_CONSTEXPR float_round_style round_style
+       = round_to_nearest;
+    };
+
+#  undef __glibcxx_float128_has_denorm_loss
+#  undef __glibcxx_float128_traps
+#  undef __glibcxx_float128_tinyness_before
+
+#endif // _GLIBCXX_USE_FLOAT128
+
 _GLIBCXX_END_NAMESPACE_VERSION
 } // namespace
 
Index: testsuite/18_support/numeric_limits/denorm_min.cc
===================================================================
--- testsuite/18_support/numeric_limits/denorm_min.cc   (revision 271076)
+++ testsuite/18_support/numeric_limits/denorm_min.cc   (working copy)
@@ -49,6 +49,9 @@
   test_denorm_min<float>();
   test_denorm_min<double>();
   test_denorm_min<long double>();
+#if _GLIBCXX_USE_FLOAT128
+  test_denorm_min<__float128>();
+#endif // _GLIBCXX_USE_FLOAT128
 
   return 0;
 }
Index: testsuite/18_support/numeric_limits/dr559.cc
===================================================================
--- testsuite/18_support/numeric_limits/dr559.cc        (revision 271076)
+++ testsuite/18_support/numeric_limits/dr559.cc        (working copy)
@@ -105,5 +105,8 @@
   do_test<float>();
   do_test<double>();
   do_test<long double>();
+#if _GLIBCXX_USE_FLOAT128
+  do_test<__float128>();
+#endif // _GLIBCXX_USE_FLOAT128
   return 0;
 }
Index: testsuite/18_support/numeric_limits/epsilon.cc
===================================================================
--- testsuite/18_support/numeric_limits/epsilon.cc      (revision 271076)
+++ testsuite/18_support/numeric_limits/epsilon.cc      (working copy)
@@ -41,6 +41,9 @@
   test_epsilon<float>();
   test_epsilon<double>();
   test_epsilon<long double>();
+#if _GLIBCXX_USE_FLOAT128
+  test_epsilon<__float128>();
+#endif // _GLIBCXX_USE_FLOAT128
 
   return 0;
 }
Index: testsuite/18_support/numeric_limits/infinity.cc
===================================================================
--- testsuite/18_support/numeric_limits/infinity.cc     (revision 271076)
+++ testsuite/18_support/numeric_limits/infinity.cc     (working copy)
@@ -49,6 +49,9 @@
   test_infinity<float>();
   test_infinity<double>();
   test_infinity<long double>();
+#if _GLIBCXX_USE_FLOAT128
+  test_infinity<__float128>();
+#endif // _GLIBCXX_USE_FLOAT128
 
   return 0;
 }
Index: testsuite/18_support/numeric_limits/is_iec559.cc
===================================================================
--- testsuite/18_support/numeric_limits/is_iec559.cc    (revision 271076)
+++ testsuite/18_support/numeric_limits/is_iec559.cc    (working copy)
@@ -69,6 +69,9 @@
   test_is_iec559<float>();
   test_is_iec559<double>();
   test_is_iec559<long double>();
+#if _GLIBCXX_USE_FLOAT128
+  test_is_iec559<__float128>();
+#endif // _GLIBCXX_USE_FLOAT128
 
   test04();
 
Index: testsuite/18_support/numeric_limits/lowest.cc
===================================================================
--- testsuite/18_support/numeric_limits/lowest.cc       (revision 271076)
+++ testsuite/18_support/numeric_limits/lowest.cc       (working copy)
@@ -82,6 +82,9 @@
   do_test<float>();
   do_test<double>();
   do_test<long double>();
+#if _GLIBCXX_USE_FLOAT128
+  do_test<__float128>();
+#endif // _GLIBCXX_USE_FLOAT128
 }
 
 int main()
Index: testsuite/18_support/numeric_limits/max_digits10.cc
===================================================================
--- testsuite/18_support/numeric_limits/max_digits10.cc (revision 271076)
+++ testsuite/18_support/numeric_limits/max_digits10.cc (working copy)
@@ -65,6 +65,12 @@
   const int ld_max_digits10 = (2 + std::numeric_limits<long double>::digits
                               * 643 / 2136);
   VERIFY( std::numeric_limits<long double>::max_digits10 == ld_max_digits10 );
+
+#if _GLIBCXX_USE_FLOAT128
+  const int q_max_digits10 = (2 + std::numeric_limits<__float128>::digits
+                              * 643 / 2136);
+  VERIFY( std::numeric_limits<__float128>::max_digits10 == q_max_digits10 );
+#endif // _GLIBCXX_USE_FLOAT128
 }
 
 int main()
Index: testsuite/18_support/numeric_limits/min_max.cc
===================================================================
--- testsuite/18_support/numeric_limits/min_max.cc      (revision 271076)
+++ testsuite/18_support/numeric_limits/min_max.cc      (working copy)
@@ -55,6 +55,9 @@
 DEFINE_EXTREMA(float, FLT_MIN, FLT_MAX);
 DEFINE_EXTREMA(double, DBL_MIN, DBL_MAX);
 DEFINE_EXTREMA(long double, LDBL_MIN, LDBL_MAX);
+#if _GLIBCXX_USE_FLOAT128
+DEFINE_EXTREMA(__float128, FLT128_MIN, FLT128_MAX);
+#endif // _GLIBCXX_USE_FLOAT128
 
 #undef DEFINE_EXTREMA
 
@@ -87,6 +90,9 @@
   test_extrema<float>();
   test_extrema<double>();
   test_extrema<long double>();
+#if _GLIBCXX_USE_FLOAT128
+  test_extrema<__float128>();
+#endif // _GLIBCXX_USE_FLOAT128
 
   return 0;
 }
Index: testsuite/18_support/numeric_limits/quiet_NaN.cc
===================================================================
--- testsuite/18_support/numeric_limits/quiet_NaN.cc    (revision 271076)
+++ testsuite/18_support/numeric_limits/quiet_NaN.cc    (working copy)
@@ -49,6 +49,9 @@
   test_qnan<float>();
   test_qnan<double>();
   test_qnan<long double>();
+#ifdef _GLIBCXX_USE_FLOAT128
+  test_qnan<__float128>();
+#endif // _GLIBCXX_USE_FLOAT128
 
   return 0;
 }

Reply via email to