On Wed, Dec 17, 2025 at 9:10 AM Jakub Jelinek <[email protected]> wrote:
> On Wed, Dec 17, 2025 at 07:55:01AM +0100, Jakub Jelinek wrote:
> > Because we don't have unsigned _BitInt(128) in C++ right now, I'm afraid
> you
> > want some unsigned __int128 like class for #ifndef __SIZEOF_INT128__
> which
> > will handle all the operations you need on a pair of unsigned long long.
>
> Though, I wonder if you really need unsigned __int128 type for 32-bit
> hosts (if __generate_canonical_pow2/any are copied/edited for the
> 128-bit cases.
>
> Without 128-bit integral type, I think you don't need to worry about
> __log2_R > 64, because simply there is no such unsigned integral type to
> hold it.
>
Adding to above we can use uint32/uint64 if __rd ^ rk fits inside of it, we
can check
if __gen_can_rng_calls_needed(_R, _rd) <
__gen_can_rng_calls_needed(UInt(-1), _rd),
or we could check _Unit(-1) / _R >= __rd, and check then for 32, 64 bits.
These values are all known at compile time.
For above to work __gen_can_rng_calls_needed(val, r) would need to use
division,
to avoid overflow during multiplication.
> So
> constexpr _RealT __Rk = _RealT(_UInt(1) << (__log2_Rk - 1)) * 2.0;
> can be done in that case even using unsigned long long type.
> (Though I wonder if it shouldn't be _RealT(2.0) instead of 2.0).
> I'd hope that
> const _UInt __x = _UInt(1) << __log2_x;
> and
> _UInt __sum = _UInt(__urng() - _Urbg::min());
> can be still done in unsigned long long type as well for similar reasons.
> Only the
> for (unsigned __i = __k - 1, __shift = 0; __i > 0; --__i)
> {
> __shift += __log2_R;
> __sum |= _UInt(__urng() - _Urbg::min()) << __shift;
> }
> const _RealT __ret = _RealT(__sum >> __log2_x) / __rd;
> part is problematic, but can't that be handled by hand with a pair of
> unsigned long long __sums? Of course one can't convert to _RealT in
> that case from the pair but needs to be done from the MS half, multiply
> by some precomputed constant and add the LS half.
>
> Jakub
>
>