xref: /llvm-project/libcxx/include/__cxx03/__random/linear_congruential_engine.h (revision ce7771902dc50d900de639d499a60486b83f70e0)
1e78f53d1SNikolas Klauser //===----------------------------------------------------------------------===//
2e78f53d1SNikolas Klauser //
3e78f53d1SNikolas Klauser // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4e78f53d1SNikolas Klauser // See https://llvm.org/LICENSE.txt for license information.
5e78f53d1SNikolas Klauser // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6e78f53d1SNikolas Klauser //
7e78f53d1SNikolas Klauser //===----------------------------------------------------------------------===//
8e78f53d1SNikolas Klauser 
9*ce777190SNikolas Klauser #ifndef _LIBCPP___CXX03___RANDOM_LINEAR_CONGRUENTIAL_ENGINE_H
10*ce777190SNikolas Klauser #define _LIBCPP___CXX03___RANDOM_LINEAR_CONGRUENTIAL_ENGINE_H
11e78f53d1SNikolas Klauser 
1273fbae83SNikolas Klauser #include <__cxx03/__config>
1373fbae83SNikolas Klauser #include <__cxx03/__random/is_seed_sequence.h>
1473fbae83SNikolas Klauser #include <__cxx03/__type_traits/enable_if.h>
1573fbae83SNikolas Klauser #include <__cxx03/__type_traits/integral_constant.h>
1673fbae83SNikolas Klauser #include <__cxx03/__type_traits/is_unsigned.h>
1773fbae83SNikolas Klauser #include <__cxx03/cstdint>
1873fbae83SNikolas Klauser #include <__cxx03/iosfwd>
19e78f53d1SNikolas Klauser 
20e78f53d1SNikolas Klauser #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
21e78f53d1SNikolas Klauser #  pragma GCC system_header
22e78f53d1SNikolas Klauser #endif
23e78f53d1SNikolas Klauser 
24e78f53d1SNikolas Klauser _LIBCPP_PUSH_MACROS
2573fbae83SNikolas Klauser #include <__cxx03/__undef_macros>
26e78f53d1SNikolas Klauser 
27e78f53d1SNikolas Klauser _LIBCPP_BEGIN_NAMESPACE_STD
28e78f53d1SNikolas Klauser 
29e78f53d1SNikolas Klauser enum __lce_alg_type {
30e78f53d1SNikolas Klauser   _LCE_Full,
31e78f53d1SNikolas Klauser   _LCE_Part,
32e78f53d1SNikolas Klauser   _LCE_Schrage,
33e78f53d1SNikolas Klauser   _LCE_Promote,
34e78f53d1SNikolas Klauser };
35e78f53d1SNikolas Klauser 
36e78f53d1SNikolas Klauser template <unsigned long long __a,
37e78f53d1SNikolas Klauser           unsigned long long __c,
38e78f53d1SNikolas Klauser           unsigned long long __m,
39e78f53d1SNikolas Klauser           unsigned long long _Mp,
40e78f53d1SNikolas Klauser           bool _HasOverflow = (__a != 0ull && (__m & (__m - 1ull)) != 0ull),      // a != 0, m != 0, m != 2^n
41e78f53d1SNikolas Klauser           bool _Full        = (!_HasOverflow || __m - 1ull <= (_Mp - __c) / __a), // (a * x + c) % m works
42e78f53d1SNikolas Klauser           bool _Part        = (!_HasOverflow || __m - 1ull <= _Mp / __a),         // (a * x) % m works
43e78f53d1SNikolas Klauser           bool _Schrage     = (_HasOverflow && __m % __a <= __m / __a)>               // r <= q
44e78f53d1SNikolas Klauser struct __lce_alg_picker {
45e78f53d1SNikolas Klauser   static _LIBCPP_CONSTEXPR const __lce_alg_type __mode =
46e78f53d1SNikolas Klauser       _Full      ? _LCE_Full
47e78f53d1SNikolas Klauser       : _Part    ? _LCE_Part
48e78f53d1SNikolas Klauser       : _Schrage ? _LCE_Schrage
49e78f53d1SNikolas Klauser                  : _LCE_Promote;
50e78f53d1SNikolas Klauser 
51e78f53d1SNikolas Klauser #ifdef _LIBCPP_HAS_NO_INT128
52e78f53d1SNikolas Klauser   static_assert(_Mp != (unsigned long long)(-1) || _Full || _Part || _Schrage,
53e78f53d1SNikolas Klauser                 "The current values for a, c, and m are not currently supported on platforms without __int128");
54e78f53d1SNikolas Klauser #endif
55e78f53d1SNikolas Klauser };
56e78f53d1SNikolas Klauser 
57e78f53d1SNikolas Klauser template <unsigned long long __a,
58e78f53d1SNikolas Klauser           unsigned long long __c,
59e78f53d1SNikolas Klauser           unsigned long long __m,
60e78f53d1SNikolas Klauser           unsigned long long _Mp,
61e78f53d1SNikolas Klauser           __lce_alg_type _Mode = __lce_alg_picker<__a, __c, __m, _Mp>::__mode>
62e78f53d1SNikolas Klauser struct __lce_ta;
63e78f53d1SNikolas Klauser 
64e78f53d1SNikolas Klauser // 64
65e78f53d1SNikolas Klauser 
66e78f53d1SNikolas Klauser #ifndef _LIBCPP_HAS_NO_INT128
67e78f53d1SNikolas Klauser template <unsigned long long _Ap, unsigned long long _Cp, unsigned long long _Mp>
68e78f53d1SNikolas Klauser struct __lce_ta<_Ap, _Cp, _Mp, (unsigned long long)(-1), _LCE_Promote> {
69e78f53d1SNikolas Klauser   typedef unsigned long long result_type;
70e78f53d1SNikolas Klauser   _LIBCPP_HIDE_FROM_ABI static result_type next(result_type __xp) {
71e78f53d1SNikolas Klauser     __extension__ using __calc_type = unsigned __int128;
72e78f53d1SNikolas Klauser     const __calc_type __a           = static_cast<__calc_type>(_Ap);
73e78f53d1SNikolas Klauser     const __calc_type __c           = static_cast<__calc_type>(_Cp);
74e78f53d1SNikolas Klauser     const __calc_type __m           = static_cast<__calc_type>(_Mp);
75e78f53d1SNikolas Klauser     const __calc_type __x           = static_cast<__calc_type>(__xp);
76e78f53d1SNikolas Klauser     return static_cast<result_type>((__a * __x + __c) % __m);
77e78f53d1SNikolas Klauser   }
78e78f53d1SNikolas Klauser };
79e78f53d1SNikolas Klauser #endif
80e78f53d1SNikolas Klauser 
81e78f53d1SNikolas Klauser template <unsigned long long __a, unsigned long long __c, unsigned long long __m>
82e78f53d1SNikolas Klauser struct __lce_ta<__a, __c, __m, (unsigned long long)(-1), _LCE_Schrage> {
83e78f53d1SNikolas Klauser   typedef unsigned long long result_type;
84e78f53d1SNikolas Klauser   _LIBCPP_HIDE_FROM_ABI static result_type next(result_type __x) {
85e78f53d1SNikolas Klauser     // Schrage's algorithm
86e78f53d1SNikolas Klauser     const result_type __q  = __m / __a;
87e78f53d1SNikolas Klauser     const result_type __r  = __m % __a;
88e78f53d1SNikolas Klauser     const result_type __t0 = __a * (__x % __q);
89e78f53d1SNikolas Klauser     const result_type __t1 = __r * (__x / __q);
90e78f53d1SNikolas Klauser     __x                    = __t0 + (__t0 < __t1) * __m - __t1;
91e78f53d1SNikolas Klauser     __x += __c - (__x >= __m - __c) * __m;
92e78f53d1SNikolas Klauser     return __x;
93e78f53d1SNikolas Klauser   }
94e78f53d1SNikolas Klauser };
95e78f53d1SNikolas Klauser 
96e78f53d1SNikolas Klauser template <unsigned long long __a, unsigned long long __m>
97e78f53d1SNikolas Klauser struct __lce_ta<__a, 0ull, __m, (unsigned long long)(-1), _LCE_Schrage> {
98e78f53d1SNikolas Klauser   typedef unsigned long long result_type;
99e78f53d1SNikolas Klauser   _LIBCPP_HIDE_FROM_ABI static result_type next(result_type __x) {
100e78f53d1SNikolas Klauser     // Schrage's algorithm
101e78f53d1SNikolas Klauser     const result_type __q  = __m / __a;
102e78f53d1SNikolas Klauser     const result_type __r  = __m % __a;
103e78f53d1SNikolas Klauser     const result_type __t0 = __a * (__x % __q);
104e78f53d1SNikolas Klauser     const result_type __t1 = __r * (__x / __q);
105e78f53d1SNikolas Klauser     __x                    = __t0 + (__t0 < __t1) * __m - __t1;
106e78f53d1SNikolas Klauser     return __x;
107e78f53d1SNikolas Klauser   }
108e78f53d1SNikolas Klauser };
109e78f53d1SNikolas Klauser 
110e78f53d1SNikolas Klauser template <unsigned long long __a, unsigned long long __c, unsigned long long __m>
111e78f53d1SNikolas Klauser struct __lce_ta<__a, __c, __m, (unsigned long long)(-1), _LCE_Part> {
112e78f53d1SNikolas Klauser   typedef unsigned long long result_type;
113e78f53d1SNikolas Klauser   _LIBCPP_HIDE_FROM_ABI static result_type next(result_type __x) {
114e78f53d1SNikolas Klauser     // Use (((a*x) % m) + c) % m
115e78f53d1SNikolas Klauser     __x = (__a * __x) % __m;
116e78f53d1SNikolas Klauser     __x += __c - (__x >= __m - __c) * __m;
117e78f53d1SNikolas Klauser     return __x;
118e78f53d1SNikolas Klauser   }
119e78f53d1SNikolas Klauser };
120e78f53d1SNikolas Klauser 
121e78f53d1SNikolas Klauser template <unsigned long long __a, unsigned long long __c, unsigned long long __m>
122e78f53d1SNikolas Klauser struct __lce_ta<__a, __c, __m, (unsigned long long)(-1), _LCE_Full> {
123e78f53d1SNikolas Klauser   typedef unsigned long long result_type;
124e78f53d1SNikolas Klauser   _LIBCPP_HIDE_FROM_ABI static result_type next(result_type __x) { return (__a * __x + __c) % __m; }
125e78f53d1SNikolas Klauser };
126e78f53d1SNikolas Klauser 
127e78f53d1SNikolas Klauser template <unsigned long long __a, unsigned long long __c>
128e78f53d1SNikolas Klauser struct __lce_ta<__a, __c, 0ull, (unsigned long long)(-1), _LCE_Full> {
129e78f53d1SNikolas Klauser   typedef unsigned long long result_type;
130e78f53d1SNikolas Klauser   _LIBCPP_HIDE_FROM_ABI static result_type next(result_type __x) { return __a * __x + __c; }
131e78f53d1SNikolas Klauser };
132e78f53d1SNikolas Klauser 
133e78f53d1SNikolas Klauser // 32
134e78f53d1SNikolas Klauser 
135e78f53d1SNikolas Klauser template <unsigned long long __a, unsigned long long __c, unsigned long long __m>
136e78f53d1SNikolas Klauser struct __lce_ta<__a, __c, __m, unsigned(-1), _LCE_Promote> {
137e78f53d1SNikolas Klauser   typedef unsigned result_type;
138e78f53d1SNikolas Klauser   _LIBCPP_HIDE_FROM_ABI static result_type next(result_type __x) {
139e78f53d1SNikolas Klauser     return static_cast<result_type>(__lce_ta<__a, __c, __m, (unsigned long long)(-1)>::next(__x));
140e78f53d1SNikolas Klauser   }
141e78f53d1SNikolas Klauser };
142e78f53d1SNikolas Klauser 
143e78f53d1SNikolas Klauser template <unsigned long long _Ap, unsigned long long _Cp, unsigned long long _Mp>
144e78f53d1SNikolas Klauser struct __lce_ta<_Ap, _Cp, _Mp, unsigned(-1), _LCE_Schrage> {
145e78f53d1SNikolas Klauser   typedef unsigned result_type;
146e78f53d1SNikolas Klauser   _LIBCPP_HIDE_FROM_ABI static result_type next(result_type __x) {
147e78f53d1SNikolas Klauser     const result_type __a = static_cast<result_type>(_Ap);
148e78f53d1SNikolas Klauser     const result_type __c = static_cast<result_type>(_Cp);
149e78f53d1SNikolas Klauser     const result_type __m = static_cast<result_type>(_Mp);
150e78f53d1SNikolas Klauser     // Schrage's algorithm
151e78f53d1SNikolas Klauser     const result_type __q  = __m / __a;
152e78f53d1SNikolas Klauser     const result_type __r  = __m % __a;
153e78f53d1SNikolas Klauser     const result_type __t0 = __a * (__x % __q);
154e78f53d1SNikolas Klauser     const result_type __t1 = __r * (__x / __q);
155e78f53d1SNikolas Klauser     __x                    = __t0 + (__t0 < __t1) * __m - __t1;
156e78f53d1SNikolas Klauser     __x += __c - (__x >= __m - __c) * __m;
157e78f53d1SNikolas Klauser     return __x;
158e78f53d1SNikolas Klauser   }
159e78f53d1SNikolas Klauser };
160e78f53d1SNikolas Klauser 
161e78f53d1SNikolas Klauser template <unsigned long long _Ap, unsigned long long _Mp>
162e78f53d1SNikolas Klauser struct __lce_ta<_Ap, 0ull, _Mp, unsigned(-1), _LCE_Schrage> {
163e78f53d1SNikolas Klauser   typedef unsigned result_type;
164e78f53d1SNikolas Klauser   _LIBCPP_HIDE_FROM_ABI static result_type next(result_type __x) {
165e78f53d1SNikolas Klauser     const result_type __a = static_cast<result_type>(_Ap);
166e78f53d1SNikolas Klauser     const result_type __m = static_cast<result_type>(_Mp);
167e78f53d1SNikolas Klauser     // Schrage's algorithm
168e78f53d1SNikolas Klauser     const result_type __q  = __m / __a;
169e78f53d1SNikolas Klauser     const result_type __r  = __m % __a;
170e78f53d1SNikolas Klauser     const result_type __t0 = __a * (__x % __q);
171e78f53d1SNikolas Klauser     const result_type __t1 = __r * (__x / __q);
172e78f53d1SNikolas Klauser     __x                    = __t0 + (__t0 < __t1) * __m - __t1;
173e78f53d1SNikolas Klauser     return __x;
174e78f53d1SNikolas Klauser   }
175e78f53d1SNikolas Klauser };
176e78f53d1SNikolas Klauser 
177e78f53d1SNikolas Klauser template <unsigned long long _Ap, unsigned long long _Cp, unsigned long long _Mp>
178e78f53d1SNikolas Klauser struct __lce_ta<_Ap, _Cp, _Mp, unsigned(-1), _LCE_Part> {
179e78f53d1SNikolas Klauser   typedef unsigned result_type;
180e78f53d1SNikolas Klauser   _LIBCPP_HIDE_FROM_ABI static result_type next(result_type __x) {
181e78f53d1SNikolas Klauser     const result_type __a = static_cast<result_type>(_Ap);
182e78f53d1SNikolas Klauser     const result_type __c = static_cast<result_type>(_Cp);
183e78f53d1SNikolas Klauser     const result_type __m = static_cast<result_type>(_Mp);
184e78f53d1SNikolas Klauser     // Use (((a*x) % m) + c) % m
185e78f53d1SNikolas Klauser     __x = (__a * __x) % __m;
186e78f53d1SNikolas Klauser     __x += __c - (__x >= __m - __c) * __m;
187e78f53d1SNikolas Klauser     return __x;
188e78f53d1SNikolas Klauser   }
189e78f53d1SNikolas Klauser };
190e78f53d1SNikolas Klauser 
191e78f53d1SNikolas Klauser template <unsigned long long _Ap, unsigned long long _Cp, unsigned long long _Mp>
192e78f53d1SNikolas Klauser struct __lce_ta<_Ap, _Cp, _Mp, unsigned(-1), _LCE_Full> {
193e78f53d1SNikolas Klauser   typedef unsigned result_type;
194e78f53d1SNikolas Klauser   _LIBCPP_HIDE_FROM_ABI static result_type next(result_type __x) {
195e78f53d1SNikolas Klauser     const result_type __a = static_cast<result_type>(_Ap);
196e78f53d1SNikolas Klauser     const result_type __c = static_cast<result_type>(_Cp);
197e78f53d1SNikolas Klauser     const result_type __m = static_cast<result_type>(_Mp);
198e78f53d1SNikolas Klauser     return (__a * __x + __c) % __m;
199e78f53d1SNikolas Klauser   }
200e78f53d1SNikolas Klauser };
201e78f53d1SNikolas Klauser 
202e78f53d1SNikolas Klauser template <unsigned long long _Ap, unsigned long long _Cp>
203e78f53d1SNikolas Klauser struct __lce_ta<_Ap, _Cp, 0ull, unsigned(-1), _LCE_Full> {
204e78f53d1SNikolas Klauser   typedef unsigned result_type;
205e78f53d1SNikolas Klauser   _LIBCPP_HIDE_FROM_ABI static result_type next(result_type __x) {
206e78f53d1SNikolas Klauser     const result_type __a = static_cast<result_type>(_Ap);
207e78f53d1SNikolas Klauser     const result_type __c = static_cast<result_type>(_Cp);
208e78f53d1SNikolas Klauser     return __a * __x + __c;
209e78f53d1SNikolas Klauser   }
210e78f53d1SNikolas Klauser };
211e78f53d1SNikolas Klauser 
212e78f53d1SNikolas Klauser // 16
213e78f53d1SNikolas Klauser 
214e78f53d1SNikolas Klauser template <unsigned long long __a, unsigned long long __c, unsigned long long __m, __lce_alg_type __mode>
215e78f53d1SNikolas Klauser struct __lce_ta<__a, __c, __m, (unsigned short)(-1), __mode> {
216e78f53d1SNikolas Klauser   typedef unsigned short result_type;
217e78f53d1SNikolas Klauser   _LIBCPP_HIDE_FROM_ABI static result_type next(result_type __x) {
218e78f53d1SNikolas Klauser     return static_cast<result_type>(__lce_ta<__a, __c, __m, unsigned(-1)>::next(__x));
219e78f53d1SNikolas Klauser   }
220e78f53d1SNikolas Klauser };
221e78f53d1SNikolas Klauser 
222e78f53d1SNikolas Klauser template <class _UIntType, _UIntType __a, _UIntType __c, _UIntType __m>
223e78f53d1SNikolas Klauser class _LIBCPP_TEMPLATE_VIS linear_congruential_engine;
224e78f53d1SNikolas Klauser 
225e78f53d1SNikolas Klauser template <class _CharT, class _Traits, class _Up, _Up _Ap, _Up _Cp, _Up _Np>
226e78f53d1SNikolas Klauser _LIBCPP_HIDE_FROM_ABI basic_ostream<_CharT, _Traits>&
227e78f53d1SNikolas Klauser operator<<(basic_ostream<_CharT, _Traits>& __os, const linear_congruential_engine<_Up, _Ap, _Cp, _Np>&);
228e78f53d1SNikolas Klauser 
229e78f53d1SNikolas Klauser template <class _CharT, class _Traits, class _Up, _Up _Ap, _Up _Cp, _Up _Np>
230e78f53d1SNikolas Klauser _LIBCPP_HIDE_FROM_ABI basic_istream<_CharT, _Traits>&
231e78f53d1SNikolas Klauser operator>>(basic_istream<_CharT, _Traits>& __is, linear_congruential_engine<_Up, _Ap, _Cp, _Np>& __x);
232e78f53d1SNikolas Klauser 
233e78f53d1SNikolas Klauser template <class _UIntType, _UIntType __a, _UIntType __c, _UIntType __m>
234e78f53d1SNikolas Klauser class _LIBCPP_TEMPLATE_VIS linear_congruential_engine {
235e78f53d1SNikolas Klauser public:
236e78f53d1SNikolas Klauser   // types
237e78f53d1SNikolas Klauser   typedef _UIntType result_type;
238e78f53d1SNikolas Klauser 
239e78f53d1SNikolas Klauser private:
240e78f53d1SNikolas Klauser   result_type __x_;
241e78f53d1SNikolas Klauser 
242e78f53d1SNikolas Klauser   static _LIBCPP_CONSTEXPR const result_type _Mp = result_type(-1);
243e78f53d1SNikolas Klauser 
244e78f53d1SNikolas Klauser   static_assert(__m == 0 || __a < __m, "linear_congruential_engine invalid parameters");
245e78f53d1SNikolas Klauser   static_assert(__m == 0 || __c < __m, "linear_congruential_engine invalid parameters");
246e78f53d1SNikolas Klauser   static_assert(is_unsigned<_UIntType>::value, "_UIntType must be unsigned type");
247e78f53d1SNikolas Klauser 
248e78f53d1SNikolas Klauser public:
249e78f53d1SNikolas Klauser   static _LIBCPP_CONSTEXPR const result_type _Min = __c == 0u ? 1u : 0u;
250e78f53d1SNikolas Klauser   static _LIBCPP_CONSTEXPR const result_type _Max = __m - _UIntType(1u);
251e78f53d1SNikolas Klauser   static_assert(_Min < _Max, "linear_congruential_engine invalid parameters");
252e78f53d1SNikolas Klauser 
253e78f53d1SNikolas Klauser   // engine characteristics
254e78f53d1SNikolas Klauser   static _LIBCPP_CONSTEXPR const result_type multiplier = __a;
255e78f53d1SNikolas Klauser   static _LIBCPP_CONSTEXPR const result_type increment  = __c;
256e78f53d1SNikolas Klauser   static _LIBCPP_CONSTEXPR const result_type modulus    = __m;
257e78f53d1SNikolas Klauser   _LIBCPP_HIDE_FROM_ABI static _LIBCPP_CONSTEXPR result_type min() { return _Min; }
258e78f53d1SNikolas Klauser   _LIBCPP_HIDE_FROM_ABI static _LIBCPP_CONSTEXPR result_type max() { return _Max; }
259e78f53d1SNikolas Klauser   static _LIBCPP_CONSTEXPR const result_type default_seed = 1u;
260e78f53d1SNikolas Klauser 
261e78f53d1SNikolas Klauser   // constructors and seeding functions
262e78f53d1SNikolas Klauser #ifndef _LIBCPP_CXX03_LANG
263e78f53d1SNikolas Klauser   _LIBCPP_HIDE_FROM_ABI linear_congruential_engine() : linear_congruential_engine(default_seed) {}
264e78f53d1SNikolas Klauser   _LIBCPP_HIDE_FROM_ABI explicit linear_congruential_engine(result_type __s) { seed(__s); }
265e78f53d1SNikolas Klauser #else
266e78f53d1SNikolas Klauser   _LIBCPP_HIDE_FROM_ABI explicit linear_congruential_engine(result_type __s = default_seed) { seed(__s); }
267e78f53d1SNikolas Klauser #endif
268e78f53d1SNikolas Klauser   template <class _Sseq, __enable_if_t<__is_seed_sequence<_Sseq, linear_congruential_engine>::value, int> = 0>
269e78f53d1SNikolas Klauser   _LIBCPP_HIDE_FROM_ABI explicit linear_congruential_engine(_Sseq& __q) {
270e78f53d1SNikolas Klauser     seed(__q);
271e78f53d1SNikolas Klauser   }
272e78f53d1SNikolas Klauser   _LIBCPP_HIDE_FROM_ABI void seed(result_type __s = default_seed) {
273e78f53d1SNikolas Klauser     seed(integral_constant<bool, __m == 0>(), integral_constant<bool, __c == 0>(), __s);
274e78f53d1SNikolas Klauser   }
275e78f53d1SNikolas Klauser   template <class _Sseq, __enable_if_t<__is_seed_sequence<_Sseq, linear_congruential_engine>::value, int> = 0>
276e78f53d1SNikolas Klauser   _LIBCPP_HIDE_FROM_ABI void seed(_Sseq& __q) {
277e78f53d1SNikolas Klauser     __seed(
278e78f53d1SNikolas Klauser         __q,
279e78f53d1SNikolas Klauser         integral_constant<unsigned,
280e78f53d1SNikolas Klauser                           1 + (__m == 0 ? (sizeof(result_type) * __CHAR_BIT__ - 1) / 32 : (__m > 0x100000000ull))>());
281e78f53d1SNikolas Klauser   }
282e78f53d1SNikolas Klauser 
283e78f53d1SNikolas Klauser   // generating functions
284e78f53d1SNikolas Klauser   _LIBCPP_HIDE_FROM_ABI result_type operator()() {
285e78f53d1SNikolas Klauser     return __x_ = static_cast<result_type>(__lce_ta<__a, __c, __m, _Mp>::next(__x_));
286e78f53d1SNikolas Klauser   }
287e78f53d1SNikolas Klauser   _LIBCPP_HIDE_FROM_ABI void discard(unsigned long long __z) {
288e78f53d1SNikolas Klauser     for (; __z; --__z)
289e78f53d1SNikolas Klauser       operator()();
290e78f53d1SNikolas Klauser   }
291e78f53d1SNikolas Klauser 
292e78f53d1SNikolas Klauser   friend _LIBCPP_HIDE_FROM_ABI bool
293e78f53d1SNikolas Klauser   operator==(const linear_congruential_engine& __x, const linear_congruential_engine& __y) {
294e78f53d1SNikolas Klauser     return __x.__x_ == __y.__x_;
295e78f53d1SNikolas Klauser   }
296e78f53d1SNikolas Klauser   friend _LIBCPP_HIDE_FROM_ABI bool
297e78f53d1SNikolas Klauser   operator!=(const linear_congruential_engine& __x, const linear_congruential_engine& __y) {
298e78f53d1SNikolas Klauser     return !(__x == __y);
299e78f53d1SNikolas Klauser   }
300e78f53d1SNikolas Klauser 
301e78f53d1SNikolas Klauser private:
302e78f53d1SNikolas Klauser   _LIBCPP_HIDE_FROM_ABI void seed(true_type, true_type, result_type __s) { __x_ = __s == 0 ? 1 : __s; }
303e78f53d1SNikolas Klauser   _LIBCPP_HIDE_FROM_ABI void seed(true_type, false_type, result_type __s) { __x_ = __s; }
304e78f53d1SNikolas Klauser   _LIBCPP_HIDE_FROM_ABI void seed(false_type, true_type, result_type __s) { __x_ = __s % __m == 0 ? 1 : __s % __m; }
305e78f53d1SNikolas Klauser   _LIBCPP_HIDE_FROM_ABI void seed(false_type, false_type, result_type __s) { __x_ = __s % __m; }
306e78f53d1SNikolas Klauser 
307e78f53d1SNikolas Klauser   template <class _Sseq>
308e78f53d1SNikolas Klauser   _LIBCPP_HIDE_FROM_ABI void __seed(_Sseq& __q, integral_constant<unsigned, 1>);
309e78f53d1SNikolas Klauser   template <class _Sseq>
310e78f53d1SNikolas Klauser   _LIBCPP_HIDE_FROM_ABI void __seed(_Sseq& __q, integral_constant<unsigned, 2>);
311e78f53d1SNikolas Klauser 
312e78f53d1SNikolas Klauser   template <class _CharT, class _Traits, class _Up, _Up _Ap, _Up _Cp, _Up _Np>
313e78f53d1SNikolas Klauser   friend basic_ostream<_CharT, _Traits>&
314e78f53d1SNikolas Klauser   operator<<(basic_ostream<_CharT, _Traits>& __os, const linear_congruential_engine<_Up, _Ap, _Cp, _Np>&);
315e78f53d1SNikolas Klauser 
316e78f53d1SNikolas Klauser   template <class _CharT, class _Traits, class _Up, _Up _Ap, _Up _Cp, _Up _Np>
317e78f53d1SNikolas Klauser   friend basic_istream<_CharT, _Traits>&
318e78f53d1SNikolas Klauser   operator>>(basic_istream<_CharT, _Traits>& __is, linear_congruential_engine<_Up, _Ap, _Cp, _Np>& __x);
319e78f53d1SNikolas Klauser };
320e78f53d1SNikolas Klauser 
321e78f53d1SNikolas Klauser template <class _UIntType, _UIntType __a, _UIntType __c, _UIntType __m>
322e78f53d1SNikolas Klauser _LIBCPP_CONSTEXPR const typename linear_congruential_engine<_UIntType, __a, __c, __m>::result_type
323e78f53d1SNikolas Klauser     linear_congruential_engine<_UIntType, __a, __c, __m>::multiplier;
324e78f53d1SNikolas Klauser 
325e78f53d1SNikolas Klauser template <class _UIntType, _UIntType __a, _UIntType __c, _UIntType __m>
326e78f53d1SNikolas Klauser _LIBCPP_CONSTEXPR const typename linear_congruential_engine<_UIntType, __a, __c, __m>::result_type
327e78f53d1SNikolas Klauser     linear_congruential_engine<_UIntType, __a, __c, __m>::increment;
328e78f53d1SNikolas Klauser 
329e78f53d1SNikolas Klauser template <class _UIntType, _UIntType __a, _UIntType __c, _UIntType __m>
330e78f53d1SNikolas Klauser _LIBCPP_CONSTEXPR const typename linear_congruential_engine<_UIntType, __a, __c, __m>::result_type
331e78f53d1SNikolas Klauser     linear_congruential_engine<_UIntType, __a, __c, __m>::modulus;
332e78f53d1SNikolas Klauser 
333e78f53d1SNikolas Klauser template <class _UIntType, _UIntType __a, _UIntType __c, _UIntType __m>
334e78f53d1SNikolas Klauser _LIBCPP_CONSTEXPR const typename linear_congruential_engine<_UIntType, __a, __c, __m>::result_type
335e78f53d1SNikolas Klauser     linear_congruential_engine<_UIntType, __a, __c, __m>::default_seed;
336e78f53d1SNikolas Klauser 
337e78f53d1SNikolas Klauser template <class _UIntType, _UIntType __a, _UIntType __c, _UIntType __m>
338e78f53d1SNikolas Klauser template <class _Sseq>
339e78f53d1SNikolas Klauser void linear_congruential_engine<_UIntType, __a, __c, __m>::__seed(_Sseq& __q, integral_constant<unsigned, 1>) {
340e78f53d1SNikolas Klauser   const unsigned __k = 1;
341e78f53d1SNikolas Klauser   uint32_t __ar[__k + 3];
342e78f53d1SNikolas Klauser   __q.generate(__ar, __ar + __k + 3);
343e78f53d1SNikolas Klauser   result_type __s = static_cast<result_type>(__ar[3] % __m);
344e78f53d1SNikolas Klauser   __x_            = __c == 0 && __s == 0 ? result_type(1) : __s;
345e78f53d1SNikolas Klauser }
346e78f53d1SNikolas Klauser 
347e78f53d1SNikolas Klauser template <class _UIntType, _UIntType __a, _UIntType __c, _UIntType __m>
348e78f53d1SNikolas Klauser template <class _Sseq>
349e78f53d1SNikolas Klauser void linear_congruential_engine<_UIntType, __a, __c, __m>::__seed(_Sseq& __q, integral_constant<unsigned, 2>) {
350e78f53d1SNikolas Klauser   const unsigned __k = 2;
351e78f53d1SNikolas Klauser   uint32_t __ar[__k + 3];
352e78f53d1SNikolas Klauser   __q.generate(__ar, __ar + __k + 3);
353e78f53d1SNikolas Klauser   result_type __s = static_cast<result_type>((__ar[3] + ((uint64_t)__ar[4] << 32)) % __m);
354e78f53d1SNikolas Klauser   __x_            = __c == 0 && __s == 0 ? result_type(1) : __s;
355e78f53d1SNikolas Klauser }
356e78f53d1SNikolas Klauser 
357e78f53d1SNikolas Klauser template <class _CharT, class _Traits, class _UIntType, _UIntType __a, _UIntType __c, _UIntType __m>
358e78f53d1SNikolas Klauser inline _LIBCPP_HIDE_FROM_ABI basic_ostream<_CharT, _Traits>&
359e78f53d1SNikolas Klauser operator<<(basic_ostream<_CharT, _Traits>& __os, const linear_congruential_engine<_UIntType, __a, __c, __m>& __x) {
360e78f53d1SNikolas Klauser   __save_flags<_CharT, _Traits> __lx(__os);
361e78f53d1SNikolas Klauser   typedef basic_ostream<_CharT, _Traits> _Ostream;
362e78f53d1SNikolas Klauser   __os.flags(_Ostream::dec | _Ostream::left);
363e78f53d1SNikolas Klauser   __os.fill(__os.widen(' '));
364e78f53d1SNikolas Klauser   return __os << __x.__x_;
365e78f53d1SNikolas Klauser }
366e78f53d1SNikolas Klauser 
367e78f53d1SNikolas Klauser template <class _CharT, class _Traits, class _UIntType, _UIntType __a, _UIntType __c, _UIntType __m>
368e78f53d1SNikolas Klauser _LIBCPP_HIDE_FROM_ABI basic_istream<_CharT, _Traits>&
369e78f53d1SNikolas Klauser operator>>(basic_istream<_CharT, _Traits>& __is, linear_congruential_engine<_UIntType, __a, __c, __m>& __x) {
370e78f53d1SNikolas Klauser   __save_flags<_CharT, _Traits> __lx(__is);
371e78f53d1SNikolas Klauser   typedef basic_istream<_CharT, _Traits> _Istream;
372e78f53d1SNikolas Klauser   __is.flags(_Istream::dec | _Istream::skipws);
373e78f53d1SNikolas Klauser   _UIntType __t;
374e78f53d1SNikolas Klauser   __is >> __t;
375e78f53d1SNikolas Klauser   if (!__is.fail())
376e78f53d1SNikolas Klauser     __x.__x_ = __t;
377e78f53d1SNikolas Klauser   return __is;
378e78f53d1SNikolas Klauser }
379e78f53d1SNikolas Klauser 
380e78f53d1SNikolas Klauser typedef linear_congruential_engine<uint_fast32_t, 16807, 0, 2147483647> minstd_rand0;
381e78f53d1SNikolas Klauser typedef linear_congruential_engine<uint_fast32_t, 48271, 0, 2147483647> minstd_rand;
382e78f53d1SNikolas Klauser 
383e78f53d1SNikolas Klauser _LIBCPP_END_NAMESPACE_STD
384e78f53d1SNikolas Klauser 
385e78f53d1SNikolas Klauser _LIBCPP_POP_MACROS
386e78f53d1SNikolas Klauser 
387*ce777190SNikolas Klauser #endif // _LIBCPP___CXX03___RANDOM_LINEAR_CONGRUENTIAL_ENGINE_H
388