https://gcc.gnu.org/g:da5a5c55284969a1b99192b90571a21848a6446f

commit r16-6710-gda5a5c55284969a1b99192b90571a21848a6446f
Author: Tomasz Kamiński <[email protected]>
Date:   Mon Jan 12 11:07:35 2026 +0100

    libstdc++: Fix generate_cannonical test for 128bit floating points.
    
    This updates test01, so it properly handle 128bit floating points,
    including situation when long double uses such representation.
    Firstly, the computation of skips is corrected, by discarding number
    values equal to number of calls required to generate element
    (skips become zero for all non-float correctly). Furthermore, checks
    of histogram for types using iec559 representation, is moved inside
    test01 function, so we use correct value for long double, depending
    on number of digits in mantissa on given platform.
    
    We also extend test to cover __float128, to test 128bit floating
    point on more platforms.
    
    libstdc++-v3/ChangeLog:
    
            * 
testsuite/26_numerics/random/uniform_real_distribution/operators/gencanon.cc:
            Updated test.
    
    Reviewed-by: Jonathan Wakely <[email protected]>
    Signed-off-by: Tomasz Kamiński <[email protected]>

Diff:
---
 .../operators/gencanon.cc                          | 104 ++++++++++++++-------
 1 file changed, 68 insertions(+), 36 deletions(-)

diff --git 
a/libstdc++-v3/testsuite/26_numerics/random/uniform_real_distribution/operators/gencanon.cc
 
b/libstdc++-v3/testsuite/26_numerics/random/uniform_real_distribution/operators/gencanon.cc
index 69a061071da0..de3b0213cf57 100644
--- 
a/libstdc++-v3/testsuite/26_numerics/random/uniform_real_distribution/operators/gencanon.cc
+++ 
b/libstdc++-v3/testsuite/26_numerics/random/uniform_real_distribution/operators/gencanon.cc
@@ -25,13 +25,25 @@ struct local_rng : std::mt19937
 // sixth iteration for float, and not at all for double.
 // However, each double iteration requires two calls to the RNG.
 
+template<typename T>
+int ifloor(T t)
+{ return static_cast<int>(std::floor(t)); }
+
+#ifdef __SIZEOF_FLOAT128__
+int ifloor(__float128 t)
+{ return static_cast<int>(t); }
+#endif
+
 template <typename T, typename RNG>
 void
-test01(RNG& rng, RNG& rng2,
-  int& deviation, int& max, int& rms, int& zero, int& skips)
+test01(RNG& rng, RNG& rng2, int& skips)
 {
+  constexpr size_t mantissa = std::numeric_limits<T>::digits;
+  constexpr size_t call_per_elem = (mantissa + 31) / 32;
+
   const auto size = 1000000, buckets = 100;
   std::array<int, buckets> histo{};
+  int zero = 0;
   for (auto i = 0; i != size; ++i) {
     T sample = std::generate_canonical<T, -1u>(rng);
     VERIFY(sample >= T(0.0));
@@ -39,16 +51,20 @@ test01(RNG& rng, RNG& rng2,
     if (sample == T(0.0)) {
       ++zero;
     }
-    auto bucket = static_cast<int>(std::floor(sample * buckets));
+    auto bucket = ifloor(sample * buckets);
     ++histo[bucket];
-    rng2.discard(1);
+    rng2.discard(call_per_elem);
     if (rng != rng2) {
       ++skips;
-      rng2.discard(1);
+      rng2.discard(call_per_elem);
       VERIFY(rng == rng2);
     }
   }
-  int devsquare = 0;
+
+  if (!std::numeric_limits<T>::is_iec559)
+    return;
+
+  int deviation = 0, max = 0, rms = 0, devsquare = 0;
   for (int i = 0; i < buckets; ++i) {
     const auto expected = size / buckets;
     auto count = histo[i];
@@ -59,6 +75,32 @@ test01(RNG& rng, RNG& rng2,
     if (diff > max) max = diff;
   }
   rms = std::sqrt(devsquare);
+
+  switch (mantissa)
+  {
+  case 24: // ieee32
+    VERIFY(deviation == 7032);
+    VERIFY(max == 276);
+    VERIFY(rms == 906);
+    VERIFY(zero == 0);
+    break;
+  case 53: // ieee64
+  case 64: // ieee80 
+    VERIFY(deviation == 7650);
+    VERIFY(max == 259);
+    VERIFY(rms == 975);
+    VERIFY(zero == 0);
+    break;
+  case 113: // ieee128
+    VERIFY(deviation == 9086);
+    VERIFY(max == 290);
+    VERIFY(rms == 1142);
+    VERIFY(zero == 0);
+    break;
+  default:
+    VERIFY(false);
+    break;
+  }
 }
 
 // This one is for use with local_rng
@@ -145,47 +187,37 @@ test00()
   rng.discard(12 * 629143);
 
   { // float
-    int deviation{}, max{}, rms{}, zero{}, skips{};
+    int skips{};
     auto rng2{rng};
     auto rng3{rng};
-    test01<float>(rng2, rng3, deviation, max, rms, zero, skips);
-
-    if (std::numeric_limits<float>::is_iec559) {
-      VERIFY(deviation == 7032);
-      VERIFY(max == 276);
-      VERIFY(rms == 906);
-      VERIFY(zero == 0);
-    }
+    test01<float>(rng2, rng3, skips);
     VERIFY(skips == 1);
   }
   { // double
-    int deviation{}, max{}, rms{}, zero{}, skips{};
+    int skips{};
     auto rng2{rng};
     auto rng3{rng};
-    test01<double>(rng2, rng3, deviation, max, rms, zero, skips);
-
-    if (std::numeric_limits<double>::is_iec559) {
-      VERIFY(deviation == 7650);
-      VERIFY(max == 259);
-      VERIFY(rms == 975);
-      VERIFY(zero == 0);
-    }
-    VERIFY(skips == 1000000);
+    test01<double>(rng2, rng3, skips);
+    VERIFY(skips == 0);
   }
-  { // long double, same answers as double
-    int deviation{}, max{}, rms{}, zero{}, skips{};
+  { // long double
+    int skips{};
     auto rng2{rng};
     auto rng3{rng};
-    test01<long double>(rng2, rng3, deviation, max, rms, zero, skips);
-
-    if (std::numeric_limits<double>::is_iec559) {
-      VERIFY(deviation == 7650);
-      VERIFY(max == 259);
-      VERIFY(rms == 975);
-      VERIFY(zero == 0);
-    }
-    VERIFY(skips == 1000000);
+    test01<long double>(rng2, rng3, skips);
+    VERIFY(skips == 0);
+  }
+#ifndef _GLIBCXX_GENERATE_CANONICAL_STRICT
+#  ifdef __SIZEOF_FLOAT128__
+  {
+    int skips{};
+    auto rng2{rng};
+    auto rng3{rng};
+    test01<__float128>(rng2, rng3, skips);
+    VERIFY(skips == 0);
   }
+#  endif
+#endif
 
   { // local RNG, returns [0..999'999)
     int deviation{}, max{}, rms{}, zero{}, skips{};

Reply via email to