diff --git a/stl/inc/random b/stl/inc/random index f866dab8eaa..90ae36415a5 100644 --- a/stl/inc/random +++ b/stl/inc/random @@ -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 _NODISCARD _Uint _Next_linear_congruential_value(_Uint _Prev) noexcept { // Choose intermediate type: @@ -500,16 +492,13 @@ _NODISCARD _Uint _Next_linear_congruential_value(_Uint _Prev) noexcept { const auto _Mul = static_cast(_Prev) * static_cast(_Ax) + static_cast(_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(_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); } } diff --git a/stl/src/multprec.cpp b/stl/src/multprec.cpp index 0043cfbfb96..326fd9cbb7c 100644 --- a/stl/src/multprec.cpp +++ b/stl/src/multprec.cpp @@ -3,15 +3,18 @@ // implements multiprecision math for random number generators -#include -#include +#include _STD_BEGIN -constexpr int shift = _STD numeric_limits::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]; } @@ -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; @@ -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; @@ -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;