https://gcc.gnu.org/g:80fa93f2b4d46619c9410314915ef964b0690a1e
commit r17-1230-g80fa93f2b4d46619c9410314915ef964b0690a1e Author: Tomasz Kamiński <[email protected]> Date: Thu Jan 15 14:45:53 2026 +0100 libstdc++: Expand supported operations for __rand_uint128. This patch adds following operations to __rand_uint128: * explicit operator bool * operator- with __rand_uint128 * operator* with uint64_t for _M_hi != 0 * operator/ with uint64_t The division is currently stubbed by converting to __rand_uint128. When __rand_uint128 is used, the platform does not provide native 128bit integer types, thus random number generators will return at most 64bit integer. In consequence, __generate_cannonical_any will use these overloads when multiplying by result of generator invocation. libstdc++-v3/ChangeLog: * include/bits/random.h (__rand_uint128::operator bool): (__rand_uint128::operator-=(const type& __r)) (__rand_uint128::operator-(type __l, const type& __r)): Implement. (__rand_uint128::operator/=(uint64_t __r)) (__rand_uint128::operator/(type __l, uint64_t __r)): Define by converting to type. (__rand_uint128::operator*=(const type& __r)): Remove precondition and handle _M_hi != 0. Reviewed-by: Jonathan Wakely <[email protected]> Signed-off-by: Tomasz Kamiński <[email protected]> Diff: --- libstdc++-v3/include/bits/random.h | 28 ++++++++++++++++++++++++++-- 1 file changed, 26 insertions(+), 2 deletions(-) diff --git a/libstdc++-v3/include/bits/random.h b/libstdc++-v3/include/bits/random.h index a0592a007634..fd7b8b4fb202 100644 --- a/libstdc++-v3/include/bits/random.h +++ b/libstdc++-v3/include/bits/random.h @@ -90,6 +90,10 @@ _GLIBCXX_END_INLINE_ABI_NAMESPACE(_V2) __rand_uint128(const __rand_uint128&) = default; __rand_uint128& operator=(const __rand_uint128&) = default; + constexpr explicit + operator bool() const noexcept + { return _M_lo || _M_hi; } + _GLIBCXX14_CONSTEXPR type& operator=(uint64_t __x) noexcept { return *this = type(__x); } @@ -134,6 +138,13 @@ _GLIBCXX_END_INLINE_ABI_NAMESPACE(_V2) operator+(type __l, uint64_t __r) noexcept { return __l += type(__r); } + _GLIBCXX14_CONSTEXPR type& + operator-=(const type& __r) noexcept + { + _M_hi -= __r._M_hi + __builtin_sub_overflow(_M_lo, __r._M_lo, &_M_lo); + return *this; + } + // Subtraction with 64-bit operand _GLIBCXX14_CONSTEXPR type& operator-=(uint64_t __r) noexcept @@ -142,6 +153,10 @@ _GLIBCXX_END_INLINE_ABI_NAMESPACE(_V2) 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; } @@ -172,7 +187,6 @@ _GLIBCXX_END_INLINE_ABI_NAMESPACE(_V2) } // Multiplication with a 64-bit operand is simpler. - // pre: _M_hi == 0 _GLIBCXX14_CONSTEXPR type& operator*=(uint64_t __x) noexcept { @@ -190,7 +204,9 @@ _GLIBCXX_END_INLINE_ABI_NAMESPACE(_V2) // 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_hi *= __x; + _M_hi += __l0x0 + (__l0x1 >> 32) + (__l1x0 >> 32) + (__mid >> 32); _M_lo = (__mid << 32) + (__l1x1 & __mask); return *this; } @@ -296,6 +312,10 @@ _GLIBCXX_END_INLINE_ABI_NAMESPACE(_V2) return *this; } + _GLIBCXX14_CONSTEXPR type& + operator/=(uint64_t __r) noexcept + { return *this /= type(__r); } + // Currently only supported for 64-bit operands. _GLIBCXX14_CONSTEXPR type& operator%=(uint64_t __m) noexcept @@ -345,6 +365,10 @@ _GLIBCXX_END_INLINE_ABI_NAMESPACE(_V2) 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, uint64_t __m) noexcept { return __l %= __m; }
