OK with those changes, and the "mantisa" typo discussed privately.
On Mon, 12 Jan 2026 at 10:34, Jonathan Wakely <[email protected]> wrote: > > On Mon, 12 Jan 2026 at 10:25, Tomasz Kamiński <[email protected]> wrote: > > > > 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 > > number values equal to number of calls required to generate element > > "discarding number number values" -> "discarding the number of values" > > > (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. > > --- > > Tested the gencanon.cc file locally with all standard modes, and > > with/without -m32. OK for trunk? > > > > .../operators/gencanon.cc | 106 ++++++++++++------ > > 1 file changed, 70 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 69a061071da..96f18b19c25 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 > > @@ -8,6 +8,7 @@ > > #include <cmath> > > #include <testsuite_hooks.h> > > #include <array> > > +#include <iostream> > > > > template <std::uint64_t max_val> > > struct local_rng : std::mt19937 > > @@ -25,13 +26,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 mantisa = std::numeric_limits<T>::digits; > > + constexpr size_t call_per_elem = (mantisa + 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 +52,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 +76,33 @@ test01(RNG& rng, RNG& rng2, > > if (diff > max) max = diff; > > } > > rms = std::sqrt(devsquare); > > + > > + switch (mantisa) > > + { > > + case 24: // iee32 > > iee32 -> ieee32 > > > + std::cout << deviation << std::endl; > > This line and the #include <iostream> can be removed. > > > + VERIFY(deviation == 7032); > > + VERIFY(max == 276); > > + VERIFY(rms == 906); > > + VERIFY(zero == 0); > > + break; > > + case 53: // iee64 > > iee64 -> ieee64 > > > + case 64: // iee80 9086 > > ieee > > > + VERIFY(deviation == 7650); > > + VERIFY(max == 259); > > + VERIFY(rms == 975); > > + VERIFY(zero == 0); > > + break; > > + case 113: // iee128 > > ieee > > > + 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 +189,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{}; > > -- > > 2.52.0 > >
