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

Reply via email to