mirror of
https://forge.sourceware.org/marek/gcc.git
synced 2026-02-22 03:47:02 -05:00
libstdc++: Implement std::philox_engine for targets without __int128
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 <jakub@redhat.com> Reviewed-by: Tomasz Kamiński <tkaminsk@redhat.com>
This commit is contained in:
committed by
Jonathan Wakely
parent
a9eb2f24b0
commit
12084561db
@@ -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.
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
@@ -2241,7 +2241,6 @@ ftms = {
|
||||
values = {
|
||||
v = 202406;
|
||||
cxxmin = 26;
|
||||
extra_cond = "__SIZEOF_INT128__";
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
Reference in New Issue
Block a user