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