@@ -26,32 +26,56 @@ _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." );
45
+ static _LIBCPP_CONSTEXPR const __lce_alg_type __mode = _Full ? _LCE_Full : _Part ? _LCE_Part : _Schrage ? _LCE_Schrage : _LCE_Promote;
40
46
41
- static _LIBCPP_CONSTEXPR const bool __use_schrage = _MightOverflow && !_OverflowOK && _SchrageOK;
47
+ #ifdef _LIBCPP_HAS_NO_INT128
48
+ static_assert (_Mp != (unsigned long long )(~0 ) || _Full || _Part || _Schrage,
49
+ "The current values for a, c, and m are not currently supported on platforms without __int128");
50
+ #endif
42
51
};
43
52
44
53
template <unsigned long long __a,
45
54
unsigned long long __c,
46
55
unsigned long long __m,
47
56
unsigned long long _Mp,
48
- bool _UseSchrage = __lce_alg_picker<__a, __c, __m, _Mp>::__use_schrage >
57
+ __lce_alg_type _Mode = __lce_alg_picker<__a, __c, __m, _Mp>::__mode >
49
58
struct __lce_ta ;
50
59
51
60
// 64
52
61
62
+ #ifndef _LIBCPP_HAS_NO_INT128
63
+ template <unsigned long long _Ap, unsigned long long _Cp, unsigned long long _Mp>
64
+ struct __lce_ta <_Ap, _Cp, _Mp, (unsigned long long )(~0 ), _LCE_Promote> {
65
+ typedef unsigned long long result_type;
66
+ _LIBCPP_HIDE_FROM_ABI static result_type next (result_type __xp) {
67
+ __extension__ using __calc_type = unsigned __int128;
68
+ const __calc_type __a = static_cast <__calc_type>(_Ap);
69
+ const __calc_type __c = static_cast <__calc_type>(_Cp);
70
+ const __calc_type __m = static_cast <__calc_type>(_Mp);
71
+ const __calc_type __x = static_cast <__calc_type>(__xp);
72
+ return static_cast <result_type>((__a * __x + __c) % __m);
73
+ }
74
+ };
75
+ #endif
76
+
53
77
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 > {
78
+ struct __lce_ta <__a, __c, __m, (unsigned long long )(~0 ), _LCE_Schrage > {
55
79
typedef unsigned long long result_type;
56
80
_LIBCPP_HIDE_FROM_ABI static result_type next (result_type __x) {
57
81
// Schrage's algorithm
@@ -66,7 +90,7 @@ struct __lce_ta<__a, __c, __m, (unsigned long long)(~0), true> {
66
90
};
67
91
68
92
template <unsigned long long __a, unsigned long long __m>
69
- struct __lce_ta <__a, 0 , __m, (unsigned long long )(~0 ), true > {
93
+ struct __lce_ta <__a, 0ull , __m, (unsigned long long )(~0 ), _LCE_Schrage > {
70
94
typedef unsigned long long result_type;
71
95
_LIBCPP_HIDE_FROM_ABI static result_type next (result_type __x) {
72
96
// Schrage's algorithm
@@ -80,21 +104,40 @@ struct __lce_ta<__a, 0, __m, (unsigned long long)(~0), true> {
80
104
};
81
105
82
106
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 > {
107
+ struct __lce_ta <__a, __c, __m, (unsigned long long )(~0 ), _LCE_Part> {
108
+ typedef unsigned long long result_type;
109
+ _LIBCPP_HIDE_FROM_ABI static result_type next (result_type __x) {
110
+ // Use (((a*x) % m) + c) % m
111
+ __x = (__a * __x) % __m;
112
+ __x += __c - (__x >= __m - __c) * __m;
113
+ return __x;
114
+ }
115
+ };
116
+
117
+ template <unsigned long long __a, unsigned long long __c, unsigned long long __m>
118
+ struct __lce_ta <__a, __c, __m, (unsigned long long )(~0 ), _LCE_Full> {
84
119
typedef unsigned long long result_type;
85
120
_LIBCPP_HIDE_FROM_ABI static result_type next (result_type __x) { return (__a * __x + __c) % __m; }
86
121
};
87
122
88
123
template <unsigned long long __a, unsigned long long __c>
89
- struct __lce_ta <__a, __c, 0 , (unsigned long long )(~0 ), false > {
124
+ struct __lce_ta <__a, __c, 0ull , (unsigned long long )(~0 ), _LCE_Full > {
90
125
typedef unsigned long long result_type;
91
126
_LIBCPP_HIDE_FROM_ABI static result_type next (result_type __x) { return __a * __x + __c; }
92
127
};
93
128
94
129
// 32
95
130
131
+ template <unsigned long long __a, unsigned long long __c, unsigned long long __m>
132
+ struct __lce_ta <__a, __c, __m, unsigned (~0 ), _LCE_Promote> {
133
+ typedef unsigned result_type;
134
+ _LIBCPP_HIDE_FROM_ABI static result_type next (result_type __x) {
135
+ return static_cast <result_type>(__lce_ta<__a, __c, __m, (unsigned long long )(~0 )>::next (__x));
136
+ }
137
+ };
138
+
96
139
template <unsigned long long _Ap, unsigned long long _Cp, unsigned long long _Mp>
97
- struct __lce_ta <_Ap, _Cp, _Mp, unsigned (~0 ), true > {
140
+ struct __lce_ta <_Ap, _Cp, _Mp, unsigned (~0 ), _LCE_Schrage > {
98
141
typedef unsigned result_type;
99
142
_LIBCPP_HIDE_FROM_ABI static result_type next (result_type __x) {
100
143
const result_type __a = static_cast <result_type>(_Ap);
@@ -112,7 +155,7 @@ struct __lce_ta<_Ap, _Cp, _Mp, unsigned(~0), true> {
112
155
};
113
156
114
157
template <unsigned long long _Ap, unsigned long long _Mp>
115
- struct __lce_ta <_Ap, 0 , _Mp, unsigned (~0 ), true > {
158
+ struct __lce_ta <_Ap, 0ull , _Mp, unsigned (~0 ), _LCE_Schrage > {
116
159
typedef unsigned result_type;
117
160
_LIBCPP_HIDE_FROM_ABI static result_type next (result_type __x) {
118
161
const result_type __a = static_cast <result_type>(_Ap);
@@ -128,7 +171,21 @@ struct __lce_ta<_Ap, 0, _Mp, unsigned(~0), true> {
128
171
};
129
172
130
173
template <unsigned long long _Ap, unsigned long long _Cp, unsigned long long _Mp>
131
- struct __lce_ta <_Ap, _Cp, _Mp, unsigned (~0 ), false > {
174
+ struct __lce_ta <_Ap, _Cp, _Mp, unsigned (~0 ), _LCE_Part> {
175
+ typedef unsigned result_type;
176
+ _LIBCPP_HIDE_FROM_ABI static result_type next (result_type __x) {
177
+ const result_type __a = static_cast <result_type>(_Ap);
178
+ const result_type __c = static_cast <result_type>(_Cp);
179
+ const result_type __m = static_cast <result_type>(_Mp);
180
+ // Use (((a*x) % m) + c) % m
181
+ __x = (__a * __x) % __m;
182
+ __x += __c - (__x >= __m - __c) * __m;
183
+ return __x;
184
+ }
185
+ };
186
+
187
+ template <unsigned long long _Ap, unsigned long long _Cp, unsigned long long _Mp>
188
+ struct __lce_ta <_Ap, _Cp, _Mp, unsigned (~0 ), _LCE_Full> {
132
189
typedef unsigned result_type;
133
190
_LIBCPP_HIDE_FROM_ABI static result_type next (result_type __x) {
134
191
const result_type __a = static_cast <result_type>(_Ap);
@@ -139,7 +196,7 @@ struct __lce_ta<_Ap, _Cp, _Mp, unsigned(~0), false> {
139
196
};
140
197
141
198
template <unsigned long long _Ap, unsigned long long _Cp>
142
- struct __lce_ta <_Ap, _Cp, 0 , unsigned (~0 ), false > {
199
+ struct __lce_ta <_Ap, _Cp, 0ull , unsigned (~0 ), _LCE_Full > {
143
200
typedef unsigned result_type;
144
201
_LIBCPP_HIDE_FROM_ABI static result_type next (result_type __x) {
145
202
const result_type __a = static_cast <result_type>(_Ap);
@@ -150,8 +207,8 @@ struct __lce_ta<_Ap, _Cp, 0, unsigned(~0), false> {
150
207
151
208
// 16
152
209
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 > {
210
+ template <unsigned long long __a, unsigned long long __c, unsigned long long __m, int __mode >
211
+ struct __lce_ta <__a, __c, __m, (unsigned short )(~0 ), __mode > {
155
212
typedef unsigned short result_type;
156
213
_LIBCPP_HIDE_FROM_ABI static result_type next (result_type __x) {
157
214
return static_cast <result_type>(__lce_ta<__a, __c, __m, unsigned (~0 )>::next (__x));
0 commit comments