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

commit r17-496-gda540dc6d7634a708768008d23b3cee9110a7121
Author: Tomasz Kamiński <[email protected]>
Date:   Wed May 13 14:51:02 2026 +0200

    libstdc++: Test for unsupported engine range for 128bits floating points 
[PR119739]
    
    This patch add test illustrating, that after implementing P0952 "A new 
specification for
    std::generate_canonical",  generators, that emit range of non-power-of-two 
size, that
    span over B bits, are not supported in combination with 128bits integer are 
not
    support for B in ranges: [22, 23), [26, 29), [33, 38), [43, 57). This is 
because, the
    lowest multiply of B that is larger of equal than 113 (size of mantisa of 
float128)
    is greater than 128, and thus they will require 256 bits integers support.
    
    This does not impact any generate defined in standard (see gencanon_eng.cc 
tests),
    nor generate emitting power of 2 sized ranges.
    
            PR libstdc++/119739
    
    libstdc++-v3/ChangeLog:
    
            * 
testsuite/26_numerics/random/uniform_real_distribution/operators/gencanon_eng_neg.cc:
            New test.
    
    Reviewed-by: Nathan Myers <[email protected]>
    Signed-off-by: Tomasz Kamiński <[email protected]>

Diff:
---
 .../operators/gencanon_eng_neg.cc                  | 89 ++++++++++++++++++++++
 1 file changed, 89 insertions(+)

diff --git 
a/libstdc++-v3/testsuite/26_numerics/random/uniform_real_distribution/operators/gencanon_eng_neg.cc
 
b/libstdc++-v3/testsuite/26_numerics/random/uniform_real_distribution/operators/gencanon_eng_neg.cc
new file mode 100644
index 000000000000..8b241fee7edf
--- /dev/null
+++ 
b/libstdc++-v3/testsuite/26_numerics/random/uniform_real_distribution/operators/gencanon_eng_neg.cc
@@ -0,0 +1,89 @@
+// { dg-do compile { target { c++11 } } }
+
+#include <random>
+#include <cstdint>
+
+template<std::uint64_t Max, typename Under = std::mt19937_64>
+struct trimmed_engine
+{
+  using result_type = std::uint64_t;
+
+  static constexpr
+  result_type min()
+  { return result_type(0); }
+
+  static constexpr
+  result_type max()
+  { return result_type(Max); }
+
+  trimmed_engine() : dist(min(), max())
+  {}
+
+  result_type operator()()
+  { return dist(under); }
+
+private:
+  Under under;
+  std::uniform_int_distribution<result_type> dist;
+};
+
+template<typename Real, size_t Bits>
+void
+test_non_pow2()
+{
+  trimmed_engine<(std::uint64_t(1) << Bits) - 2> non_pow2_engine;
+  (void)std::generate_canonical<Real, -1u>(non_pow2_engine);
+}
+
+template<typename Real, size_t Bits>
+void
+test_pow2()
+{
+  trimmed_engine<(std::uint64_t(1) << Bits) - 1> pow2_engine;
+  (void)std::generate_canonical<Real, -1u>(pow2_engine);
+}
+
+int main()
+{
+// For 128bit floating points, generator emitting a range, which size is 
+// not power of two, but of width of B bits, such that for any N:
+// N * B < 113 (bits in ieee128)
+// (N+1) * B > 128
+// are not supported, as they would require integer with more than 127 bits.
+#ifndef _GLIBCXX_GENERATE_CANONICAL_STRICT
+#  ifdef __SIZEOF_FLOAT128__
+  // N == 3: B in [43, 57)
+  test_non_pow2<__float128, 42>(); // 3 calls
+  test_non_pow2<__float128, 43>(); // { dg-error "from here" }
+  test_non_pow2<__float128, 56>(); // { dg-error "from here" }
+  test_non_pow2<__float128, 57>(); // 2 calls
+  test_pow2<__float128, 43>();
+  test_pow2<__float128, 56>();
+
+  // N == 4: B in [33, 38)
+  test_non_pow2<__float128, 32>(); // 4 calls
+  test_non_pow2<__float128, 33>(); // { dg-error "from here" }
+  test_non_pow2<__float128, 37>(); // { dg-error "from here" }
+  test_non_pow2<__float128, 38>(); // 3 calls
+  test_pow2<__float128, 33>();
+  test_pow2<__float128, 37>();
+
+  // N == 5: B in [26, 29)
+  test_non_pow2<__float128, 25>(); // 5 calls
+  test_non_pow2<__float128, 26>(); // { dg-error "from here" }
+  test_non_pow2<__float128, 28>(); // { dg-error "from here" }
+  test_non_pow2<__float128, 29>(); // 4 calls
+  test_pow2<__float128, 26>();
+  test_pow2<__float128, 28>();
+
+  // N == 6: B == 22
+  test_non_pow2<__float128, 21>(); // 6 calls
+  test_non_pow2<__float128, 22>(); // { dg-error "from here" }
+  test_non_pow2<__float128, 23>(); // 5 calls
+  test_pow2<__float128, 22>();
+#  endif
+#endif 
+}
+
+// { dg-prune-output "no type named 'type' in 'struct 
std::__detail::_Select_uint_least_t" }
+// { dg-prune-output "static assertion failed: sorry, would be too much 
trouble for a slow result" }

Reply via email to