@@ -26,32 +26,60 @@ _LIBCPP_PUSH_MACROS
26
26
27
27
_LIBCPP_BEGIN_NAMESPACE_STD
28
28
29
+ enum __lce_alg_type {
30
+ _LCE_Full,
31
+ _LCE_Part,
32
+ _LCE_Schrage,
33
+ _LCE_Promote,
34
+ };
35
+
29
36
template <unsigned long long __a,
30
37
unsigned long long __c,
31
38
unsigned long long __m,
32
39
unsigned long long _Mp,
33
- bool _MightOverflow = (__a != 0 && __m != 0 && __m - 1 > (_Mp - __c) / __a),
34
- bool _OverflowOK = ((__m & (__m - 1 )) == 0ull ), // m = 2^n
35
- bool _SchrageOK = (__a != 0 && __m != 0 && __m % __a <= __m / __a)> // r <= q
40
+ bool _HasOverflow = (__a != 0ull && (__m & (__m - 1ull )) != 0ull ), // a != 0, m != 0, m != 2^n
41
+ bool _Full = (!_HasOverflow || __m - 1ull <= (_Mp - __c) / __a), // (a * x + c) % m works
42
+ bool _Part = (!_HasOverflow || __m - 1ull <= _Mp / __a), // (a * x) % m works
43
+ bool _Schrage = (_HasOverflow && __m % __a <= __m / __a)> // r <= q
36
44
struct __lce_alg_picker {
37
- static_assert (!_MightOverflow || _OverflowOK || _SchrageOK,
38
- " The current values of a, c, and m cannot generate a number "
39
- " within bounds of linear_congruential_engine." );
40
-
41
- static _LIBCPP_CONSTEXPR const bool __use_schrage = _MightOverflow && !_OverflowOK && _SchrageOK;
45
+ static _LIBCPP_CONSTEXPR const __lce_alg_type __mode =
46
+ _Full ? _LCE_Full
47
+ : _Part ? _LCE_Part
48
+ : _Schrage ? _LCE_Schrage
49
+ : _LCE_Promote;
50
+
51
+ #ifdef _LIBCPP_HAS_NO_INT128
52
+ static_assert (_Mp != (unsigned long long )(~0 ) || _Full || _Part || _Schrage,
53
+ "The current values for a, c, and m are not currently supported on platforms without __int128");
54
+ #endif
42
55
};
43
56
44
57
template <unsigned long long __a,
45
58
unsigned long long __c,
46
59
unsigned long long __m,
47
60
unsigned long long _Mp,
48
- bool _UseSchrage = __lce_alg_picker<__a, __c, __m, _Mp>::__use_schrage >
61
+ __lce_alg_type _Mode = __lce_alg_picker<__a, __c, __m, _Mp>::__mode >
49
62
struct __lce_ta ;
50
63
51
64
// 64
52
65
66
+ #ifndef _LIBCPP_HAS_NO_INT128
67
+ template <unsigned long long _Ap, unsigned long long _Cp, unsigned long long _Mp>
68
+ struct __lce_ta <_Ap, _Cp, _Mp, (unsigned long long )(~0 ), _LCE_Promote> {
69
+ typedef unsigned long long result_type;
70
+ _LIBCPP_HIDE_FROM_ABI static result_type next (result_type __xp) {
71
+ __extension__ using __calc_type = unsigned __int128;
72
+ const __calc_type __a = static_cast <__calc_type>(_Ap);
73
+ const __calc_type __c = static_cast <__calc_type>(_Cp);
74
+ const __calc_type __m = static_cast <__calc_type>(_Mp);
75
+ const __calc_type __x = static_cast <__calc_type>(__xp);
76
+ return static_cast <result_type>((__a * __x + __c) % __m);
77
+ }
78
+ };
79
+ #endif
80
+
53
81
template <unsigned long long __a, unsigned long long __c, unsigned long long __m>
54
- struct __lce_ta <__a, __c, __m, (unsigned long long )(~0 ), true > {
82
+ struct __lce_ta <__a, __c, __m, (unsigned long long )(~0 ), _LCE_Schrage > {
55
83
typedef unsigned long long result_type;
56
84
_LIBCPP_HIDE_FROM_ABI static result_type next (result_type __x) {
57
85
// Schrage's algorithm
@@ -66,7 +94,7 @@ struct __lce_ta<__a, __c, __m, (unsigned long long)(~0), true> {
66
94
};
67
95
68
96
template <unsigned long long __a, unsigned long long __m>
69
- struct __lce_ta <__a, 0 , __m, (unsigned long long )(~0 ), true > {
97
+ struct __lce_ta <__a, 0ull , __m, (unsigned long long )(~0 ), _LCE_Schrage > {
70
98
typedef unsigned long long result_type;
71
99
_LIBCPP_HIDE_FROM_ABI static result_type next (result_type __x) {
72
100
// Schrage's algorithm
@@ -80,21 +108,40 @@ struct __lce_ta<__a, 0, __m, (unsigned long long)(~0), true> {
80
108
};
81
109
82
110
template <unsigned long long __a, unsigned long long __c, unsigned long long __m>
83
- struct __lce_ta <__a, __c, __m, (unsigned long long )(~0 ), false > {
111
+ struct __lce_ta <__a, __c, __m, (unsigned long long )(~0 ), _LCE_Part> {
112
+ typedef unsigned long long result_type;
113
+ _LIBCPP_HIDE_FROM_ABI static result_type next (result_type __x) {
114
+ // Use (((a*x) % m) + c) % m
115
+ __x = (__a * __x) % __m;
116
+ __x += __c - (__x >= __m - __c) * __m;
117
+ return __x;
118
+ }
119
+ };
120
+
121
+ template <unsigned long long __a, unsigned long long __c, unsigned long long __m>
122
+ struct __lce_ta <__a, __c, __m, (unsigned long long )(~0 ), _LCE_Full> {
84
123
typedef unsigned long long result_type;
85
124
_LIBCPP_HIDE_FROM_ABI static result_type next (result_type __x) { return (__a * __x + __c) % __m; }
86
125
};
87
126
88
127
template <unsigned long long __a, unsigned long long __c>
89
- struct __lce_ta <__a, __c, 0 , (unsigned long long )(~0 ), false > {
128
+ struct __lce_ta <__a, __c, 0ull , (unsigned long long )(~0 ), _LCE_Full > {
90
129
typedef unsigned long long result_type;
91
130
_LIBCPP_HIDE_FROM_ABI static result_type next (result_type __x) { return __a * __x + __c; }
92
131
};
93
132
94
133
// 32
95
134
135
+ template <unsigned long long __a, unsigned long long __c, unsigned long long __m>
136
+ struct __lce_ta <__a, __c, __m, unsigned (~0 ), _LCE_Promote> {
137
+ typedef unsigned result_type;
138
+ _LIBCPP_HIDE_FROM_ABI static result_type next (result_type __x) {
139
+ return static_cast <result_type>(__lce_ta<__a, __c, __m, (unsigned long long )(~0 )>::next (__x));
140
+ }
141
+ };
142
+
96
143
template <unsigned long long _Ap, unsigned long long _Cp, unsigned long long _Mp>
97
- struct __lce_ta <_Ap, _Cp, _Mp, unsigned (~0 ), true > {
144
+ struct __lce_ta <_Ap, _Cp, _Mp, unsigned (~0 ), _LCE_Schrage > {
98
145
typedef unsigned result_type;
99
146
_LIBCPP_HIDE_FROM_ABI static result_type next (result_type __x) {
100
147
const result_type __a = static_cast <result_type>(_Ap);
@@ -112,7 +159,7 @@ struct __lce_ta<_Ap, _Cp, _Mp, unsigned(~0), true> {
112
159
};
113
160
114
161
template <unsigned long long _Ap, unsigned long long _Mp>
115
- struct __lce_ta <_Ap, 0 , _Mp, unsigned (~0 ), true > {
162
+ struct __lce_ta <_Ap, 0ull , _Mp, unsigned (~0 ), _LCE_Schrage > {
116
163
typedef unsigned result_type;
117
164
_LIBCPP_HIDE_FROM_ABI static result_type next (result_type __x) {
118
165
const result_type __a = static_cast <result_type>(_Ap);
@@ -128,7 +175,21 @@ struct __lce_ta<_Ap, 0, _Mp, unsigned(~0), true> {
128
175
};
129
176
130
177
template <unsigned long long _Ap, unsigned long long _Cp, unsigned long long _Mp>
131
- struct __lce_ta <_Ap, _Cp, _Mp, unsigned (~0 ), false > {
178
+ struct __lce_ta <_Ap, _Cp, _Mp, unsigned (~0 ), _LCE_Part> {
179
+ typedef unsigned result_type;
180
+ _LIBCPP_HIDE_FROM_ABI static result_type next (result_type __x) {
181
+ const result_type __a = static_cast <result_type>(_Ap);
182
+ const result_type __c = static_cast <result_type>(_Cp);
183
+ const result_type __m = static_cast <result_type>(_Mp);
184
+ // Use (((a*x) % m) + c) % m
185
+ __x = (__a * __x) % __m;
186
+ __x += __c - (__x >= __m - __c) * __m;
187
+ return __x;
188
+ }
189
+ };
190
+
191
+ template <unsigned long long _Ap, unsigned long long _Cp, unsigned long long _Mp>
192
+ struct __lce_ta <_Ap, _Cp, _Mp, unsigned (~0 ), _LCE_Full> {
132
193
typedef unsigned result_type;
133
194
_LIBCPP_HIDE_FROM_ABI static result_type next (result_type __x) {
134
195
const result_type __a = static_cast <result_type>(_Ap);
@@ -139,7 +200,7 @@ struct __lce_ta<_Ap, _Cp, _Mp, unsigned(~0), false> {
139
200
};
140
201
141
202
template <unsigned long long _Ap, unsigned long long _Cp>
142
- struct __lce_ta <_Ap, _Cp, 0 , unsigned (~0 ), false > {
203
+ struct __lce_ta <_Ap, _Cp, 0ull , unsigned (~0 ), _LCE_Full > {
143
204
typedef unsigned result_type;
144
205
_LIBCPP_HIDE_FROM_ABI static result_type next (result_type __x) {
145
206
const result_type __a = static_cast <result_type>(_Ap);
@@ -150,8 +211,8 @@ struct __lce_ta<_Ap, _Cp, 0, unsigned(~0), false> {
150
211
151
212
// 16
152
213
153
- template <unsigned long long __a, unsigned long long __c, unsigned long long __m, bool __b >
154
- struct __lce_ta <__a, __c, __m, (unsigned short )(~0 ), __b > {
214
+ template <unsigned long long __a, unsigned long long __c, unsigned long long __m, __lce_alg_type __mode >
215
+ struct __lce_ta <__a, __c, __m, (unsigned short )(~0 ), __mode > {
155
216
typedef unsigned short result_type;
156
217
_LIBCPP_HIDE_FROM_ABI static result_type next (result_type __x) {
157
218
return static_cast <result_type>(__lce_ta<__a, __c, __m, unsigned (~0 )>::next (__x));
0 commit comments