Skip to content

Commit 8e9f4ee

Browse files
<random>: Use _Unsigned128 for linear_congruential_engine (microsoft#5436)
1 parent 1b9594a commit 8e9f4ee

File tree

2 files changed

+16
-21
lines changed

2 files changed

+16
-21
lines changed

stl/inc/random

+3-14
Original file line numberDiff line numberDiff line change
@@ -461,14 +461,6 @@ _NODISCARD _Real _Nrand_impl(_Gen& _Gx) { // build a floating-point value from r
461461
}
462462
}
463463

464-
_INLINE_VAR constexpr int _MP_len = 5;
465-
using _MP_arr = uint64_t[_MP_len];
466-
467-
extern "C++" _NODISCARD _CRTIMP2_PURE uint64_t __CLRCALL_PURE_OR_CDECL _MP_Get(_MP_arr) noexcept;
468-
extern "C++" _CRTIMP2_PURE void __CLRCALL_PURE_OR_CDECL _MP_Add(_MP_arr, uint64_t) noexcept;
469-
extern "C++" _CRTIMP2_PURE void __CLRCALL_PURE_OR_CDECL _MP_Mul(_MP_arr, uint64_t, uint64_t) noexcept;
470-
extern "C++" _CRTIMP2_PURE void __CLRCALL_PURE_OR_CDECL _MP_Rem(_MP_arr, uint64_t) noexcept;
471-
472464
template <class _Uint, _Uint _Ax, _Uint _Cx, _Uint _Mx>
473465
_NODISCARD _Uint _Next_linear_congruential_value(_Uint _Prev) noexcept {
474466
// Choose intermediate type:
@@ -500,16 +492,13 @@ _NODISCARD _Uint _Next_linear_congruential_value(_Uint _Prev) noexcept {
500492
const auto _Mul =
501493
static_cast<unsigned int>(_Prev) * static_cast<unsigned int>(_Ax) + static_cast<unsigned int>(_Cx);
502494
return static_cast<_Uint>(_Mul % _Mx);
503-
} else if constexpr (_Cx <= ULLONG_MAX && static_cast<_Uint>(_Mx - 1) <= (ULLONG_MAX - _Cx) / _Ax) {
495+
} else if constexpr (static_cast<_Uint>(_Mx - 1) <= (ULLONG_MAX - _Cx) / _Ax) {
504496
// unsigned long long is sufficient to store intermediate calculation
505497
const auto _Mul = static_cast<unsigned long long>(_Prev) * _Ax + _Cx;
506498
return static_cast<_Uint>(_Mul % _Mx);
507499
} else { // no intermediate integral type fits; fall back to multiprecision
508-
_MP_arr _Wx;
509-
_MP_Mul(_Wx, _Prev, _Ax);
510-
_MP_Add(_Wx, _Cx);
511-
_MP_Rem(_Wx, _Mx);
512-
return static_cast<_Uint>(_MP_Get(_Wx));
500+
const auto _Mul = _Unsigned128{_Prev} * _Ax + _Cx;
501+
return static_cast<_Uint>(_Mul % _Mx);
513502
}
514503
}
515504

stl/src/multprec.cpp

+13-7
Original file line numberDiff line numberDiff line change
@@ -3,15 +3,18 @@
33

44
// implements multiprecision math for random number generators
55

6-
#include <limits>
7-
#include <random>
6+
#include <yvals.h>
87

98
_STD_BEGIN
10-
constexpr int shift = _STD numeric_limits<unsigned long long>::digits / 2;
9+
constexpr int _MP_len = 5;
10+
using _MP_arr = unsigned long long[_MP_len];
11+
12+
constexpr int shift = 64 / 2;
1113
constexpr unsigned long long mask = ~(~0ULL << shift);
1214
constexpr unsigned long long maxVal = mask + 1;
1315

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

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

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

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

0 commit comments

Comments
 (0)