]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
libstdc++: Test for unsupported engine range for 128bits floating points [PR119739]
authorTomasz Kamiński <tkaminsk@redhat.com>
Wed, 13 May 2026 12:51:02 +0000 (14:51 +0200)
committerTomasz Kamiński <tkaminsk@redhat.com>
Wed, 13 May 2026 12:59:00 +0000 (14:59 +0200)
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 <nmyers@redhat.com>
Signed-off-by: Tomasz Kamiński <tkaminsk@redhat.com>
libstdc++-v3/testsuite/26_numerics/random/uniform_real_distribution/operators/gencanon_eng_neg.cc [new file with mode: 0644]

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 (file)
index 0000000..8b241fe
--- /dev/null
@@ -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" }