Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 3 additions & 14 deletions stl/inc/random
Original file line number Diff line number Diff line change
Expand Up @@ -461,14 +461,6 @@ _NODISCARD _Real _Nrand_impl(_Gen& _Gx) { // build a floating-point value from r
}
}

_INLINE_VAR constexpr int _MP_len = 5;
using _MP_arr = uint64_t[_MP_len];

extern "C++" _NODISCARD _CRTIMP2_PURE uint64_t __CLRCALL_PURE_OR_CDECL _MP_Get(_MP_arr) noexcept;
extern "C++" _CRTIMP2_PURE void __CLRCALL_PURE_OR_CDECL _MP_Add(_MP_arr, uint64_t) noexcept;
extern "C++" _CRTIMP2_PURE void __CLRCALL_PURE_OR_CDECL _MP_Mul(_MP_arr, uint64_t, uint64_t) noexcept;
extern "C++" _CRTIMP2_PURE void __CLRCALL_PURE_OR_CDECL _MP_Rem(_MP_arr, uint64_t) noexcept;

template <class _Uint, _Uint _Ax, _Uint _Cx, _Uint _Mx>
_NODISCARD _Uint _Next_linear_congruential_value(_Uint _Prev) noexcept {
// Choose intermediate type:
Expand Down Expand Up @@ -500,16 +492,13 @@ _NODISCARD _Uint _Next_linear_congruential_value(_Uint _Prev) noexcept {
const auto _Mul =
static_cast<unsigned int>(_Prev) * static_cast<unsigned int>(_Ax) + static_cast<unsigned int>(_Cx);
return static_cast<_Uint>(_Mul % _Mx);
} else if constexpr (_Cx <= ULLONG_MAX && static_cast<_Uint>(_Mx - 1) <= (ULLONG_MAX - _Cx) / _Ax) {
} else if constexpr (static_cast<_Uint>(_Mx - 1) <= (ULLONG_MAX - _Cx) / _Ax) {
// unsigned long long is sufficient to store intermediate calculation
const auto _Mul = static_cast<unsigned long long>(_Prev) * _Ax + _Cx;
return static_cast<_Uint>(_Mul % _Mx);
} else { // no intermediate integral type fits; fall back to multiprecision
_MP_arr _Wx;
_MP_Mul(_Wx, _Prev, _Ax);
_MP_Add(_Wx, _Cx);
_MP_Rem(_Wx, _Mx);
return static_cast<_Uint>(_MP_Get(_Wx));
const auto _Mul = _Unsigned128{_Prev} * _Ax + _Cx;
return static_cast<_Uint>(_Mul % _Mx);
}
}

Expand Down
20 changes: 13 additions & 7 deletions stl/src/multprec.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,18 @@

// implements multiprecision math for random number generators

#include <limits>
#include <random>
#include <yvals.h>

_STD_BEGIN
constexpr int shift = _STD numeric_limits<unsigned long long>::digits / 2;
constexpr int _MP_len = 5;
using _MP_arr = unsigned long long[_MP_len];

constexpr int shift = 64 / 2;
constexpr unsigned long long mask = ~(~0ULL << shift);
constexpr unsigned long long maxVal = mask + 1;

[[nodiscard]] unsigned long long __CLRCALL_PURE_OR_CDECL _MP_Get(
// TRANSITION, ABI: preserved for binary compatibility
[[nodiscard]] _CRTIMP2_PURE unsigned long long __CLRCALL_PURE_OR_CDECL _MP_Get(
_MP_arr u) noexcept { // convert multi-word value to scalar value
return (u[1] << shift) + u[0];
}
Expand All @@ -32,7 +35,8 @@ static void add(unsigned long long* u, int ulen, unsigned long long* v,
}
}

void __CLRCALL_PURE_OR_CDECL _MP_Add(
// TRANSITION, ABI: preserved for binary compatibility
_CRTIMP2_PURE void __CLRCALL_PURE_OR_CDECL _MP_Add(
_MP_arr u, unsigned long long v0) noexcept { // add scalar value to multi-word value
unsigned long long v[2];
v[0] = v0 & mask;
Expand All @@ -50,7 +54,8 @@ static void mul(
}
}

void __CLRCALL_PURE_OR_CDECL _MP_Mul(
// TRANSITION, ABI: preserved for binary compatibility
_CRTIMP2_PURE void __CLRCALL_PURE_OR_CDECL _MP_Mul(
_MP_arr w, unsigned long long u0, unsigned long long v0) noexcept { // multiply multi-word value by multi-word value
constexpr int m = 2;
constexpr int n = 2;
Expand Down Expand Up @@ -106,7 +111,8 @@ static void div(_MP_arr u,
return ulen;
}

void __CLRCALL_PURE_OR_CDECL _MP_Rem(
// TRANSITION, ABI: preserved for binary compatibility
_CRTIMP2_PURE void __CLRCALL_PURE_OR_CDECL _MP_Rem(
_MP_arr u, unsigned long long v0) noexcept { // divide multi-word value by value, leaving remainder in u
unsigned long long v[2];
v[0] = v0 & mask;
Expand Down