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" }
