On Wed, Dec 17, 2025 at 8:51 PM Jonathan Wakely <[email protected]> wrote:

> This moves the __detail::_Select_uint_least_t<N>::type class to
> namespace scope and extends it with more 128-bit arithmetic operations,
> implemented in terms of uint64_t.
>
> Now std::philox_engine can use _Select_uint_least_t<w*2>::type instead
> of __uint128_t, so that it works on targets without 128-bit integers.
> This also means that targets that do support __uint128_t only use it
> when actually necessary, so that we use uint64_t when generating a
> 32-bit result (e.g. with std::philox4x32).
>
> libstdc++-v3/ChangeLog:
>
>         * include/bits/random.h [!__SIZEOF_INT128__] (__rand_uint128):
>         Refactor and rename _Select_uint_least_t<128>::type to a new
>         class. Make all members constexpr. Add new member functions for
>         additional arithmetic and bitwise operations, and comparisons.
>         (__detail::_Select_uint_least_t<>::type): Define as an alias of
>         __rand_uint128.
>         * include/bits/random.tcc (philox_engine::_M_mulhi): Use
>         _Select_uint_least_t<w*2>::type instead of __uint128_t.
>         (philox_engine::_M_transition): Likewise.
>         * include/bits/version.def (philox_engine): Remove extra_cond.
>         * include/bits/version.h: Regenerate.
>         * testsuite/26_numerics/random/philox4x32.cc: Remove
>         dg-require-cpp-feature-test directive.
>         * testsuite/26_numerics/random/philox4x64.cc: Likewise.
>         * testsuite/26_numerics/random/philox_engine/cons/copy.cc:
>         Likewise.
>         * testsuite/26_numerics/random/philox_engine/cons/default.cc:
>         Likewise.
>         * testsuite/26_numerics/random/philox_engine/cons/seed.cc:
>         Likewise.
>         * testsuite/26_numerics/random/philox_engine/operators/equal.cc:
>         Likewise.
>         *
> testsuite/26_numerics/random/philox_engine/operators/serialize.cc:
>         Likewise.
>         *
> testsuite/26_numerics/random/philox_engine/requirements/constants.cc:
>         Likewise.
>         *
> testsuite/26_numerics/random/philox_engine/requirements/typedefs.cc:
>         Likewise.
>
> Co-authored-by: Jakub Jelinek <[email protected]>
> ---
>
> Tested x86_64-linux
> Also checked -m32 and -D_GLIBCXX_USE_OLD_GENERATE_CANONICAL

LGTM.
I haven't fully verified the algorithms part of __int128, but they look ok
in general.
Checked, if additional operations are matching ones that were removed.

>
>  libstdc++-v3/include/bits/random.h            | 516 ++++++++++++++----
>  libstdc++-v3/include/bits/random.tcc          |  39 +-
>  libstdc++-v3/include/bits/version.def         |   1 -
>  libstdc++-v3/include/bits/version.h           |   2 +-
>  .../26_numerics/random/philox4x32.cc          |   1 -
>  .../26_numerics/random/philox4x64.cc          |   1 -
>  .../random/philox_engine/cons/copy.cc         |   1 -
>  .../random/philox_engine/cons/default.cc      |   1 -
>  .../random/philox_engine/cons/seed.cc         |   1 -
>  .../random/philox_engine/operators/equal.cc   |   1 -
>  .../philox_engine/operators/serialize.cc      |   1 -
>  .../philox_engine/requirements/constants.cc   |   1 -
>  .../philox_engine/requirements/typedefs.cc    |   1 -
>  13 files changed, 440 insertions(+), 127 deletions(-)
>
> diff --git a/libstdc++-v3/include/bits/random.h
> b/libstdc++-v3/include/bits/random.h
> index 5a959ed6ebec..7a9ba0a7a9e9 100644
> --- a/libstdc++-v3/include/bits/random.h
> +++ b/libstdc++-v3/include/bits/random.h
> @@ -74,6 +74,424 @@ _GLIBCXX_END_INLINE_ABI_NAMESPACE(_V2)
>  #pragma GCC diagnostic push
>  #pragma GCC diagnostic ignored "-Wc++17-extensions"
>
> +#ifndef __SIZEOF_INT128__
> +    // Emulate 128-bit integer type, for the arithmetic ops used in
> <random>.
> +    // The __detail::__mod function needs: (type(a) * x + c) % m.
> +    // std::philox_engine needs multiplication and bitwise ops.
> +    struct __rand_uint128
> +    {
> +      using type = __rand_uint128;
> +
> +      __rand_uint128() = default;
> +
> +      explicit constexpr
> +      __rand_uint128(uint64_t __lo) noexcept : _M_lo(__lo) { }
> +
> +      __rand_uint128(const __rand_uint128&) = default;
> +      __rand_uint128& operator=(const __rand_uint128&) = default;
> +
> +      _GLIBCXX14_CONSTEXPR type&
> +      operator=(uint64_t __x) noexcept
> +      { return *this = type(__x); }
> +
> +      _GLIBCXX14_CONSTEXPR type&
> +      operator++() noexcept
> +      { return *this = *this + 1; }
> +
> +      _GLIBCXX14_CONSTEXPR type&
> +      operator--() noexcept
> +      { return *this = *this - 1; }
> +
> +      _GLIBCXX14_CONSTEXPR type
> +      operator++(int) noexcept
> +      {
> +       auto __tmp = *this;
> +       ++*this;
> +       return __tmp;
> +      }
> +
> +      _GLIBCXX14_CONSTEXPR type
> +      operator--(int) noexcept
> +      {
> +       auto __tmp = *this;
> +       --*this;
> +       return __tmp;
> +      }
> +
> +      _GLIBCXX14_CONSTEXPR type&
> +      operator+=(const type& __r) noexcept
> +      {
> +       _M_hi += __r._M_hi + __builtin_add_overflow(_M_lo, __r._M_lo,
> &_M_lo);
> +       return *this;
> +      }
> +
> +      friend _GLIBCXX14_CONSTEXPR type
> +      operator+(type __l, const type& __r) noexcept
> +      { return __l += __r; }
> +
> +      // Addition with 64-bit operand
> +      friend _GLIBCXX14_CONSTEXPR type
> +      operator+(type __l, uint64_t __r) noexcept
> +      { return __l += type(__r); }
> +
> +      // Subtraction with 64-bit operand
> +      _GLIBCXX14_CONSTEXPR type&
> +      operator-=(uint64_t __r) noexcept
> +      {
> +       _M_hi -= __builtin_sub_overflow(_M_lo, __r, &_M_lo);
> +       return *this;
> +      }
> +
> +      friend _GLIBCXX14_CONSTEXPR type
> +      operator-(type __l, uint64_t __r) noexcept
> +      { return __l -= __r; }
> +
> +      _GLIBCXX14_CONSTEXPR type&
> +      operator*=(const type& __x) noexcept
> +      {
> +       uint64_t __a[12] = {
> +         uint32_t(_M_lo), _M_lo >> 32,
> +         uint32_t(_M_hi), _M_hi >> 32,
> +         uint32_t(__x._M_lo), __x._M_lo >> 32,
> +         uint32_t(__x._M_hi), __x._M_hi >> 32,
> +         0, 0,
> +         0, 0 };
> +       for (int __i = 0; __i < 4; ++__i)
> +         {
> +           uint64_t __c = 0;
> +           for (int __j = __i; __j < 4; ++__j)
> +             {
> +               __c += __a[__i] * __a[4 + __j - __i] + __a[8 + __j];
> +               __a[8 + __j] = uint32_t(__c);
> +               __c >>= 32;
> +             }
> +         }
> +       _M_lo = __a[8] + (__a[9] << 32);
> +       _M_hi = __a[10] + (__a[11] << 32);
> +       return *this;
> +      }
> +
> +      // Multiplication with a 64-bit operand is simpler.
> +      // pre: _M_hi == 0
> +      _GLIBCXX14_CONSTEXPR type&
> +      operator*=(uint64_t __x) noexcept
> +      {
> +       // Split 64-bit values _M_lo and __x into high and low 32-bit
> +       // limbs and multiply those individually.
> +       // l * x = (l0 + l1) * (x0 + x1) = l0x0 + l0x1 + l1x0 + l1x1
> +
> +       constexpr uint64_t __mask = 0xffffffff;
> +       uint64_t __ll[2] = { _M_lo >> 32, _M_lo & __mask };
> +       uint64_t __xx[2] = { __x >> 32, __x & __mask };
> +       uint64_t __l0x0 = __ll[0] * __xx[0];
> +       uint64_t __l0x1 = __ll[0] * __xx[1];
> +       uint64_t __l1x0 = __ll[1] * __xx[0];
> +       uint64_t __l1x1 = __ll[1] * __xx[1];
> +       // These bits are the low half of _M_hi and the high half of _M_lo.
> +       uint64_t __mid
> +         = (__l0x1 & __mask) + (__l1x0 & __mask) + (__l1x1 >> 32);
> +       _M_hi = __l0x0 + (__l0x1 >> 32) + (__l1x0 >> 32) + (__mid >> 32);
> +       _M_lo = (__mid << 32) + (__l1x1 & __mask);
> +       return *this;
> +      }
> +
> +      _GLIBCXX14_CONSTEXPR type&
> +      operator/=(const type& __r) noexcept

+      {
> +       if (!_M_hi)
> +         {
> +           if (!__r._M_hi)
> +             _M_lo = _M_lo / __r._M_lo;
> +           else
> +             _M_lo = 0;
> +         }
> +       else
> +         {
> +           uint64_t __a[13] = {
> +             uint32_t(_M_lo), _M_lo >> 32,
> +             uint32_t(_M_hi), _M_hi >> 32,
> +             0,
> +             uint32_t(__r._M_lo), __r._M_lo >> 32,
> +             uint32_t(__r._M_hi), __r._M_hi >> 32,
> +             0, 0,
> +             0, 0
> +           };
> +           uint64_t __c = 0, __w = 0;
> +           if (!__r._M_hi && __r._M_lo <= ~uint32_t(0))
> +             for (int __i = 3; ; --__i)
> +               {
> +                 __w = __a[__i] + (__c << 32);
> +                 __a[9 + __i] = __w / __r._M_lo;
> +                 if (__i == 0)
> +                   break;
> +                 __c = __w % __r._M_lo;
> +               }
> +           else
> +             {
> +               // See Donald E. Knuth's "Seminumerical Algorithms".
> +               int __n = 0, __d = 0;
> +               uint64_t __q = 0, __s = 0;
> +               for (__d = 3; __a[5 + __d] == 0; --__d)
> +                 ;
> +               __s = (uint64_t(1) << 32) / (__a[5 + __d] + 1);
> +               if (__s > 1)
> +                 {
> +                   for (int __i = 0; __i <= 3; ++__i)
> +                     {
> +                       __w = __a[__i] * __s + __c;
> +                       __a[__i] = uint32_t(__w);
> +                       __c = __w >> 32;
> +                     }
> +                   __a[4] = __c;
> +                   __c = 0;
> +                   for (int __i = 0; __i <= 3; ++__i)
> +                     {
> +                       __w = __a[5 + __i] * __s + __c;
> +                       __a[5 + __i] = uint32_t(__w);
> +                       __c = __w >> 32;
> +                       if (__a[5 + __i])
> +                         __d = __i;
> +                     }
> +                 }
> +               __n = 4;
> +               for (int __i = __n - __d - 1; __i >= 0; --__i)
> +                 {
> +                   __n = __i + __d + 1;
> +                   __w = (__a[__n] << 32) + __a[__n - 1];
> +                   if (__a[__n] != __a[5 + __d])
> +                     __q = __w / __a[5 + __d];
> +                   else
> +                     __q = ~uint32_t(0);
> +                   uint64_t __t = __w - __q * __a[5 + __d];
> +                   if (__t <= ~uint32_t(0)
> +                         && __a[4 + __d] * __q > (__t << 32) + __a[__n -
> 2])
> +                     --__q;
> +                   __c = 0;
> +                   for (int __j = 0; __j <= __d; ++__j)
> +                     {
> +                       __w = __q * __a[5 + __j] + __c;
> +                       __c = __w >> 32;
> +                       __w = __a[__i + __j] - uint32_t(__w);
> +                       __a[__i + __j] = uint32_t(__w);
> +                       __c += (__w >> 32) != 0;
> +                     }
> +                   if (int64_t(__a[__n]) < int64_t(__c))
> +                     {
> +                       --__q;
> +                       __c = 0;
> +                       for (int __j = 0; __j <= __d; ++__j)
> +                         {
> +                           __w = __a[__i + __j] + __a[5 + __j] + __c;
> +                           __c = __w >> 32;
> +                           __a[__i + __j] = uint32_t(__w);
> +                         }
> +                       __a[__n] += __c;
> +                     }
> +                   __a[9 + __i] = __q;
> +                 }
> +             }
> +           _M_lo = __a[9] + (__a[10] << 32);
> +           _M_hi = __a[11] + (__a[12] << 32);
> +         }
> +       return *this;
> +      }
> +
> +      // Currently only supported for 64-bit operands.
> +      _GLIBCXX14_CONSTEXPR type&
> +      operator%=(uint64_t __m) noexcept
> +      {
> +       if (_M_hi == 0)
> +         {
> +           _M_lo %= __m;
> +           return *this;
> +         }
> +
> +       int __shift = __builtin_clzll(__m) + 64 - __builtin_clzll(_M_hi);
> +       type __x(0);
> +       if (__shift >= 64)
> +         {
> +           __x._M_hi = __m << (__shift - 64);
> +           __x._M_lo = 0;
> +         }
> +       else
> +         {
> +           __x._M_hi = __m >> (64 - __shift);
> +           __x._M_lo = __m << __shift;
> +         }
> +
> +       while (_M_hi != 0 || _M_lo >= __m)
> +         {
> +           if (__x <= *this)
> +             {
> +               _M_hi -= __x._M_hi;
> +               _M_hi -= __builtin_sub_overflow(_M_lo, __x._M_lo,
> +                                                   &_M_lo);
> +             }
> +           __x._M_lo = (__x._M_lo >> 1) | (__x._M_hi << 63);
> +           __x._M_hi >>= 1;
> +         }
> +       return *this;
> +      }
> +
> +      friend _GLIBCXX14_CONSTEXPR type
> +      operator*(type __l, const type& __r) noexcept
> +      { return __l *= __r; }
> +
> +      friend _GLIBCXX14_CONSTEXPR type
> +      operator*(type __l, uint64_t __r) noexcept
> +      { return __l *= __r; }
> +
> +      friend _GLIBCXX14_CONSTEXPR type
> +      operator/(type __l, const type& __r) noexcept
> +      { return __l /= __r; }
> +
> +      friend _GLIBCXX14_CONSTEXPR type
> +      operator%(type __l, uint64_t __m) noexcept
> +      { return __l %= __m; }
> +
> +      friend _GLIBCXX14_CONSTEXPR type
> +      operator~(type __v) noexcept
> +      {
> +       __v._M_hi = ~__v._M_hi;
> +       __v._M_lo = ~__v._M_lo;
> +       return __v;
> +      }
> +
> +      _GLIBCXX14_CONSTEXPR type&
> +      operator>>=(unsigned __c) noexcept
> +      {
> +       if (__c >= 64)
> +         {
> +           _M_lo = _M_hi >>= (__c - 64);
> +           _M_hi = 0;
> +         }
> +       else if (__c != 0)
> +         {
> +           _M_lo = (_M_lo >> __c) | (_M_hi << (64 - __c));
> +           _M_hi >>= __c;
> +         }
> +       return *this;
> +      }
> +
> +      _GLIBCXX14_CONSTEXPR type&
> +      operator<<=(unsigned __c) noexcept
> +      {
> +       if (__c >= 64)
> +         {
> +           _M_hi = _M_lo << (__c - 64);
> +           _M_lo = 0;
> +         }
> +       else if (__c != 0)
> +         {
> +           _M_hi = (_M_hi << __c) | (_M_lo >> (64 - __c));
> +           _M_lo <<= __c;
> +         }
> +       return *this;
> +      }
> +
> +      friend _GLIBCXX14_CONSTEXPR type
> +      operator>>(type __x, unsigned __c) noexcept
> +      { return __x >>= __c; }
> +
> +      friend _GLIBCXX14_CONSTEXPR type
> +      operator<<(type __x, unsigned __c) noexcept
> +      { return __x <<= __c; }
> +
> +      _GLIBCXX14_CONSTEXPR type&
> +      operator|=(const type& __r) noexcept
> +      {
> +       _M_hi |= __r._M_hi;
> +       _M_lo |= __r._M_lo;
> +       return *this;
> +      }
> +
> +      _GLIBCXX14_CONSTEXPR type&
> +      operator^=(const type& __r) noexcept
> +      {
> +       _M_hi ^= __r._M_hi;
> +       _M_lo ^= __r._M_lo;
> +       return *this;
> +      }
> +
> +      _GLIBCXX14_CONSTEXPR type&
> +      operator&=(const type& __r) noexcept
> +      {
> +       _M_hi &= __r._M_hi;
> +       _M_lo &= __r._M_lo;
> +       return *this;
> +      }
> +
> +      friend _GLIBCXX14_CONSTEXPR type
> +      operator|(type __l, const type& __r) noexcept
> +      { return __l |= __r; }
> +
> +      friend _GLIBCXX14_CONSTEXPR type
> +      operator^(type __l, const type& __r) noexcept
> +      { return __l ^= __r; }
> +
> +      friend _GLIBCXX14_CONSTEXPR type
> +      operator&(type __l, const type& __r) noexcept
> +      { return __l &= __r; }
> +
> +      friend _GLIBCXX14_CONSTEXPR type
> +      operator&(type __l, uint64_t __r) noexcept
> +      {
> +       __l._M_hi = 0;
> +       __l._M_lo &= __r;
> +       return __l;
> +      }
> +
> +#if __cpp_impl_three_way_comparison >= 201907L
> +      friend std::strong_ordering
> +      operator<=>(const type&, const type&) = default;
> +
> +      friend bool
> +      operator==(const type&, const type&) = default;
> +#else
> +      friend constexpr bool
> +      operator==(const type& __l, const type& __r) noexcept
> +      { return __l._M_hi == __r._M_hi && __l._M_lo == __r._M_lo; }
> +
> +      friend _GLIBCXX14_CONSTEXPR bool
> +      operator<(const type& __l, const type& __r) noexcept
> +      {
> +       if (__l._M_hi < __r._M_hi)
> +         return true;
> +       else if (__l._M_hi == __r._M_hi)
> +         return __l._M_lo < __r._M_lo;
> +       else
> +         return false;
> +      }
> +
> +      friend _GLIBCXX14_CONSTEXPR bool
> +      operator<=(const type& __l, const type& __r) noexcept
> +      { return !(__r < __l); }
> +#endif
> +
> +      friend _GLIBCXX14_CONSTEXPR bool
> +      operator==(const type& __l, uint64_t __r) noexcept
> +      { return __l == type(__r); }
> +
> +      template<typename _RealT>
> +       constexpr explicit operator _RealT() const noexcept
> +       {
> +         static_assert(std::is_floating_point<_RealT>::value,
> +                       "template argument must be a floating point type");
> +         return _M_hi == 0
> +                  ? _RealT(_M_lo)
> +                  : _RealT(_M_hi) * _RealT(18446744073709551616.0)
> +                    + _RealT(_M_lo);
> +       }
> +
> +      // pre: _M_hi == 0
> +      constexpr explicit operator uint64_t() const noexcept
> +      { return _M_lo; }
> +
> +      uint64_t _M_hi = 0;
> +      uint64_t _M_lo = 0;
> +    };
> +#endif // ! __SIZEOF_INT128__
> +
>      template<typename _UIntType, size_t __w,
>              bool = __w < static_cast<size_t>
>                           (std::numeric_limits<_UIntType>::digits)>
> @@ -117,103 +535,7 @@ _GLIBCXX_END_INLINE_ABI_NAMESPACE(_V2)
>      && defined __UINT64_TYPE__
>      template<int __s>
>        struct _Select_uint_least_t<__s, 1>
> -      {
> -       // This is NOT a general-purpose 128-bit integer type.
> -       // It only supports (type(a) * x + c) % m as needed by __mod.
> -       struct type
> -       {
> -         explicit
> -         type(uint64_t __a) noexcept : _M_lo(__a), _M_hi(0) { }
> -
> -         // pre: __l._M_hi == 0
> -         friend type
> -         operator*(type __l, uint64_t __x) noexcept
> -         {
> -           // Split 64-bit values __l._M_lo and __x into high and low
> 32-bit
> -           // limbs and multiply those individually.
> -           // l * x = (l0 + l1) * (x0 + x1) = l0x0 + l0x1 + l1x0 + l1x1
> -
> -           constexpr uint64_t __mask = 0xffffffff;
> -           uint64_t __ll[2] = { __l._M_lo >> 32, __l._M_lo & __mask };
> -           uint64_t __xx[2] = { __x >> 32, __x & __mask };
> -           uint64_t __l0x0 = __ll[0] * __xx[0];
> -           uint64_t __l0x1 = __ll[0] * __xx[1];
> -           uint64_t __l1x0 = __ll[1] * __xx[0];
> -           uint64_t __l1x1 = __ll[1] * __xx[1];
> -           // These bits are the low half of __l._M_hi
> -           // and the high half of __l._M_lo.
> -           uint64_t __mid
> -             = (__l0x1 & __mask) + (__l1x0 & __mask) + (__l1x1 >> 32);
> -           __l._M_hi = __l0x0 + (__l0x1 >> 32) + (__l1x0 >> 32) + (__mid
> >> 32);
> -           __l._M_lo = (__mid << 32) + (__l1x1 & __mask);
> -           return __l;
> -         }
> -
> -         friend type
> -         operator+(type __l, uint64_t __c) noexcept
> -         {
> -           __l._M_hi += __builtin_add_overflow(__l._M_lo, __c,
> &__l._M_lo);
> -           return __l;
> -         }
> -
> -         friend type
> -         operator%(type __l, uint64_t __m) noexcept
> -         {
> -           if (__builtin_expect(__l._M_hi == 0, 0))
> -             {
> -               __l._M_lo %= __m;
> -               return __l;
> -             }
> -
> -           int __shift = __builtin_clzll(__m) + 64
> -                           - __builtin_clzll(__l._M_hi);
> -           type __x(0);
> -           if (__shift >= 64)
> -             {
> -               __x._M_hi = __m << (__shift - 64);
> -               __x._M_lo = 0;
> -             }
> -           else
> -             {
> -               __x._M_hi = __m >> (64 - __shift);
> -               __x._M_lo = __m << __shift;
> -             }
> -
> -           while (__l._M_hi != 0 || __l._M_lo >= __m)
> -             {
> -               if (__x <= __l)
> -                 {
> -                   __l._M_hi -= __x._M_hi;
> -                   __l._M_hi -= __builtin_sub_overflow(__l._M_lo,
> __x._M_lo,
> -                                                       &__l._M_lo);
> -                 }
> -               __x._M_lo = (__x._M_lo >> 1) | (__x._M_hi << 63);
> -               __x._M_hi >>= 1;
> -             }
> -           return __l;
> -         }
> -
> -         // pre: __l._M_hi == 0
> -         explicit operator uint64_t() const noexcept
> -         { return _M_lo; }
> -
> -         friend bool operator<(const type& __l, const type& __r) noexcept
> -         {
> -           if (__l._M_hi < __r._M_hi)
> -             return true;
> -           else if (__l._M_hi == __r._M_hi)
> -             return __l._M_lo < __r._M_lo;
> -           else
> -             return false;
> -         }
> -
> -         friend bool operator<=(const type& __l, const type& __r) noexcept
> -         { return !(__r < __l); }
> -
> -         uint64_t _M_lo;
> -         uint64_t _M_hi;
> -       };
> -      };
> +      { using type = __rand_uint128; };
>  #endif
>
>      // Assume a != 0, a < m, c < m, x < m.
> diff --git a/libstdc++-v3/include/bits/random.tcc
> b/libstdc++-v3/include/bits/random.tcc
> index e16eb9814a55..68eae419b721 100644
> --- a/libstdc++-v3/include/bits/random.tcc
> +++ b/libstdc++-v3/include/bits/random.tcc
> @@ -915,9 +915,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
>      philox_engine<_UIntType, __w, __n, __r, __consts...>::
>      _S_mulhi(_UIntType __a, _UIntType __b)
>      {
> -      const __uint128_t __num =
> -         static_cast<__uint128_t>(__a) * static_cast<__uint128_t>(__b);
> -      return static_cast<_UIntType>((__num >> __w) & max());
> +      using __type = typename __detail::_Select_uint_least_t<__w *
> 2>::type;
> +      const __type __num = static_cast<__type>(__a) * __b;
> +      return static_cast<_UIntType>(__num >> __w) & max();
>      }
>
>    template<typename _UIntType, size_t __w, size_t __n, size_t __r,
> @@ -938,33 +938,34 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
>        if (_M_i != __n)
>         return;
>
> +      using __type = typename __detail::_Select_uint_least_t<__w *
> 2>::type;
> +
>        _M_philox();
>        if constexpr (__n == 4)
>         {
> -         __uint128_t __uh =
> -           (static_cast<__uint128_t>(_M_x[1]) << __w)
> -                 | (static_cast<__uint128_t>(_M_x[0]) + 1);
> -         __uint128_t __lh =
> -           ((static_cast<__uint128_t>(_M_x[3]) << __w)
> -                 | (_M_x[2]));
> -         __uint128_t __bigMask =
> -           (static_cast<__uint128_t>(1) << ((2 * __w) - 1))
> -                 | ((static_cast<__uint128_t>(1) << ((2 * __w) - 1)) - 1);
> +         __type __uh
> +           = (static_cast<__type>(_M_x[1]) << __w)
> +               | (static_cast<__type>(_M_x[0]) + 1);
> +         __type __lh
> +           = (static_cast<__type>(_M_x[3]) << __w)
> +               | static_cast<__type>(_M_x[2]);
> +         __type __bigMask
> +           = ~__type(0) >> ((sizeof(__type) * __CHAR_BIT__) - (__w * 2));
>           if ((__uh & __bigMask) == 0)
>             {
>               ++__lh;
>               __uh = 0;
>             }
> -         _M_x[0] = __uh & max();
> -         _M_x[1] = (__uh >> (__w)) & max();
> -         _M_x[2] = __lh & max();
> -         _M_x[3] = (__lh >> (__w)) & max();
> +         _M_x[0] = static_cast<_UIntType>(__uh & max());
> +         _M_x[1] = static_cast<_UIntType>((__uh >> (__w)) & max());
> +         _M_x[2] = static_cast<_UIntType>(__lh & max());
> +         _M_x[3] = static_cast<_UIntType>((__lh >> (__w)) & max());
>         }
>        else
>         {
> -         __uint128_t __num =
> -                 (static_cast<__uint128_t>(_M_x[1]) << __w)
> -                 | (static_cast<__uint128_t>(_M_x[0]) + 1);
> +         __type __num =
> +                 (static_cast<__type>(_M_x[1]) << __w)
> +                 | (static_cast<__type>(_M_x[0]) + 1);
>           _M_x[0] = __num & max();
>           _M_x[1] = (__num >> __w) & max();
>         }
> diff --git a/libstdc++-v3/include/bits/version.def
> b/libstdc++-v3/include/bits/version.def
> index 3042318a8128..9fe6ada4ff46 100644
> --- a/libstdc++-v3/include/bits/version.def
> +++ b/libstdc++-v3/include/bits/version.def
> @@ -2242,7 +2242,6 @@ ftms = {
>    values = {
>      v = 202406;
>      cxxmin = 26;
> -    extra_cond = "__SIZEOF_INT128__";
>    };
>  };
>
> diff --git a/libstdc++-v3/include/bits/version.h
> b/libstdc++-v3/include/bits/version.h
> index 34c1e9f1b80f..08c738d410fb 100644
> --- a/libstdc++-v3/include/bits/version.h
> +++ b/libstdc++-v3/include/bits/version.h
> @@ -2507,7 +2507,7 @@
>  #undef __glibcxx_want_constexpr_exceptions
>
>  #if !defined(__cpp_lib_philox_engine)
> -# if (__cplusplus >  202302L) && (__SIZEOF_INT128__)
> +# if (__cplusplus >  202302L)
>  #  define __glibcxx_philox_engine 202406L
>  #  if defined(__glibcxx_want_all) || defined(__glibcxx_want_philox_engine)
>  #   define __cpp_lib_philox_engine 202406L
> diff --git a/libstdc++-v3/testsuite/26_numerics/random/philox4x32.cc
> b/libstdc++-v3/testsuite/26_numerics/random/philox4x32.cc
> index 33842bb8db03..cf2192c17b58 100644
> --- a/libstdc++-v3/testsuite/26_numerics/random/philox4x32.cc
> +++ b/libstdc++-v3/testsuite/26_numerics/random/philox4x32.cc
> @@ -1,5 +1,4 @@
>  // { dg-do run { target c++26 } }
> -// { dg-require-cpp-feature-test __cpp_lib_philox_engine }
>
>  // N5014 29.5.6 Engines and engine adaptors with predefined parameters
>
> diff --git a/libstdc++-v3/testsuite/26_numerics/random/philox4x64.cc
> b/libstdc++-v3/testsuite/26_numerics/random/philox4x64.cc
> index 11a5691804e0..fd3e576b9a22 100644
> --- a/libstdc++-v3/testsuite/26_numerics/random/philox4x64.cc
> +++ b/libstdc++-v3/testsuite/26_numerics/random/philox4x64.cc
> @@ -1,5 +1,4 @@
>  // { dg-do run { target c++26 } }
> -// { dg-require-cpp-feature-test __cpp_lib_philox_engine }
>
>  // N5014 29.5.6 Engines and engine adaptors with predefined parameters
>
> diff --git
> a/libstdc++-v3/testsuite/26_numerics/random/philox_engine/cons/copy.cc
> b/libstdc++-v3/testsuite/26_numerics/random/philox_engine/cons/copy.cc
> index 163aec082332..34387335a200 100644
> --- a/libstdc++-v3/testsuite/26_numerics/random/philox_engine/cons/copy.cc
> +++ b/libstdc++-v3/testsuite/26_numerics/random/philox_engine/cons/copy.cc
> @@ -1,5 +1,4 @@
>  // { dg-do run { target c++26 } }
> -// { dg-require-cpp-feature-test __cpp_lib_philox_engine }
>
>  // N5014 29.5.4 Random Number Engine Class Templates
>  // N5014 29.5.4.5 Class Template philox_engine
> diff --git
> a/libstdc++-v3/testsuite/26_numerics/random/philox_engine/cons/default.cc
> b/libstdc++-v3/testsuite/26_numerics/random/philox_engine/cons/default.cc
> index 183ca8201093..7f2005bcb380 100644
> ---
> a/libstdc++-v3/testsuite/26_numerics/random/philox_engine/cons/default.cc
> +++
> b/libstdc++-v3/testsuite/26_numerics/random/philox_engine/cons/default.cc
> @@ -1,5 +1,4 @@
>  // { dg-do run { target c++26 } }
> -// { dg-require-cpp-feature-test __cpp_lib_philox_engine }
>
>  // N5014 29.5.4.5 Class Template philox_engine
>
> diff --git
> a/libstdc++-v3/testsuite/26_numerics/random/philox_engine/cons/seed.cc
> b/libstdc++-v3/testsuite/26_numerics/random/philox_engine/cons/seed.cc
> index 2b667b233644..07f39acb3a70 100644
> --- a/libstdc++-v3/testsuite/26_numerics/random/philox_engine/cons/seed.cc
> +++ b/libstdc++-v3/testsuite/26_numerics/random/philox_engine/cons/seed.cc
> @@ -1,5 +1,4 @@
>  // { dg-do run { target c++26 } }
> -// { dg-require-cpp-feature-test __cpp_lib_philox_engine }
>
>  #include <random>
>  #include <testsuite_hooks.h>
> diff --git
> a/libstdc++-v3/testsuite/26_numerics/random/philox_engine/operators/equal.cc
> b/libstdc++-v3/testsuite/26_numerics/random/philox_engine/operators/equal.cc
> index cca1654603ef..0fe323170cc3 100644
> ---
> a/libstdc++-v3/testsuite/26_numerics/random/philox_engine/operators/equal.cc
> +++
> b/libstdc++-v3/testsuite/26_numerics/random/philox_engine/operators/equal.cc
> @@ -1,5 +1,4 @@
>  // { dg-do run { target c++26 } }
> -// { dg-require-cpp-feature-test __cpp_lib_philox_engine }
>
>  // N5014 29.5.4.5 Class Template philox_engine
>
> diff --git
> a/libstdc++-v3/testsuite/26_numerics/random/philox_engine/operators/serialize.cc
> b/libstdc++-v3/testsuite/26_numerics/random/philox_engine/operators/serialize.cc
> index 4bd40e74a6b5..c82fb5139bda 100644
> ---
> a/libstdc++-v3/testsuite/26_numerics/random/philox_engine/operators/serialize.cc
> +++
> b/libstdc++-v3/testsuite/26_numerics/random/philox_engine/operators/serialize.cc
> @@ -1,5 +1,4 @@
>  // { dg-do run { target c++26 } }
> -// { dg-require-cpp-feature-test __cpp_lib_philox_engine }
>
>  // N5014 29.5.4.5 Class Template philox_engine
>
> diff --git
> a/libstdc++-v3/testsuite/26_numerics/random/philox_engine/requirements/constants.cc
> b/libstdc++-v3/testsuite/26_numerics/random/philox_engine/requirements/constants.cc
> index a3cb24eb0667..6cbf25f08bbe 100644
> ---
> a/libstdc++-v3/testsuite/26_numerics/random/philox_engine/requirements/constants.cc
> +++
> b/libstdc++-v3/testsuite/26_numerics/random/philox_engine/requirements/constants.cc
> @@ -1,5 +1,4 @@
>  // { dg-do compile { target c++26 } }
> -// { dg-require-cpp-feature-test __cpp_lib_philox_engine }
>
>  // N5014 29.5.4.5 Class Template philox_engine
>
> diff --git
> a/libstdc++-v3/testsuite/26_numerics/random/philox_engine/requirements/typedefs.cc
> b/libstdc++-v3/testsuite/26_numerics/random/philox_engine/requirements/typedefs.cc
> index 1fc8fedc4c69..0ad30ae138f1 100644
> ---
> a/libstdc++-v3/testsuite/26_numerics/random/philox_engine/requirements/typedefs.cc
> +++
> b/libstdc++-v3/testsuite/26_numerics/random/philox_engine/requirements/typedefs.cc
> @@ -1,5 +1,4 @@
>  // { dg-do compile { target c++26 } }
> -// { dg-require-cpp-feature-test __cpp_lib_philox_engine }
>
>  // N5014 29.5.4.5 Class Template philox_engine
>
> --
> 2.52.0
>
>

Reply via email to