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.
---
I was planing to add the test before christmas break, but didn't managed to.
I have some ideas, how to handle it, without requiring 128bit integers,
but not sure how important this is. The failures will seem to be very arbitral
form user-perspective, but custom engines are I assume uncommon.

Tested new test on x86_64-linux locally with all supported standard modes,
and with/without -m32. OK for trunk?


 .../operators/gencanon_eng_neg.cc             | 89 +++++++++++++++++++
 1 file changed, 89 insertions(+)
 create mode 100644 
libstdc++-v3/testsuite/26_numerics/random/uniform_real_distribution/operators/gencanon_eng_neg.cc

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 00000000000..42a4bc65d22
--- /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>(); // 4 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" }
-- 
2.52.0

Reply via email to