xref: /llvm-project/libcxx/include/__random/linear_congruential_engine.h (revision b69ddbc62838f23ace237c206676b1ed1c882638)
1344cef66SArthur O'Dwyer //===----------------------------------------------------------------------===//
2344cef66SArthur O'Dwyer //
3344cef66SArthur O'Dwyer // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4344cef66SArthur O'Dwyer // See https://llvm.org/LICENSE.txt for license information.
5344cef66SArthur O'Dwyer // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6344cef66SArthur O'Dwyer //
7344cef66SArthur O'Dwyer //===----------------------------------------------------------------------===//
8344cef66SArthur O'Dwyer 
9344cef66SArthur O'Dwyer #ifndef _LIBCPP___RANDOM_LINEAR_CONGRUENTIAL_ENGINE_H
10344cef66SArthur O'Dwyer #define _LIBCPP___RANDOM_LINEAR_CONGRUENTIAL_ENGINE_H
11344cef66SArthur O'Dwyer 
12344cef66SArthur O'Dwyer #include <__config>
13344cef66SArthur O'Dwyer #include <__random/is_seed_sequence.h>
140a4aa8a1SNikolas Klauser #include <__type_traits/enable_if.h>
150a4aa8a1SNikolas Klauser #include <__type_traits/integral_constant.h>
160a4aa8a1SNikolas Klauser #include <__type_traits/is_unsigned.h>
17344cef66SArthur O'Dwyer #include <cstdint>
18344cef66SArthur O'Dwyer #include <iosfwd>
19344cef66SArthur O'Dwyer 
20344cef66SArthur O'Dwyer #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
21344cef66SArthur O'Dwyer #  pragma GCC system_header
22344cef66SArthur O'Dwyer #endif
23344cef66SArthur O'Dwyer 
24344cef66SArthur O'Dwyer _LIBCPP_PUSH_MACROS
25344cef66SArthur O'Dwyer #include <__undef_macros>
26344cef66SArthur O'Dwyer 
27344cef66SArthur O'Dwyer _LIBCPP_BEGIN_NAMESPACE_STD
28344cef66SArthur O'Dwyer 
2941e69629SLRFLEW enum __lce_alg_type {
3041e69629SLRFLEW   _LCE_Full,
3141e69629SLRFLEW   _LCE_Part,
3241e69629SLRFLEW   _LCE_Schrage,
3341e69629SLRFLEW   _LCE_Promote,
34344cef66SArthur O'Dwyer };
35344cef66SArthur O'Dwyer 
369783f28cSLouis Dionne template <unsigned long long __a,
379783f28cSLouis Dionne           unsigned long long __c,
389783f28cSLouis Dionne           unsigned long long __m,
399783f28cSLouis Dionne           unsigned long long _Mp,
4041e69629SLRFLEW           bool _HasOverflow = (__a != 0ull && (__m & (__m - 1ull)) != 0ull),      // a != 0, m != 0, m != 2^n
4141e69629SLRFLEW           bool _Full        = (!_HasOverflow || __m - 1ull <= (_Mp - __c) / __a), // (a * x + c) % m works
4241e69629SLRFLEW           bool _Part        = (!_HasOverflow || __m - 1ull <= _Mp / __a),         // (a * x) % m works
4341e69629SLRFLEW           bool _Schrage     = (_HasOverflow && __m % __a <= __m / __a)>               // r <= q
4441e69629SLRFLEW struct __lce_alg_picker {
4541e69629SLRFLEW   static _LIBCPP_CONSTEXPR const __lce_alg_type __mode =
4641e69629SLRFLEW       _Full      ? _LCE_Full
4741e69629SLRFLEW       : _Part    ? _LCE_Part
4841e69629SLRFLEW       : _Schrage ? _LCE_Schrage
4941e69629SLRFLEW                  : _LCE_Promote;
5041e69629SLRFLEW 
51ba87515fSNikolas Klauser #if !_LIBCPP_HAS_INT128
5241e69629SLRFLEW   static_assert(_Mp != (unsigned long long)(-1) || _Full || _Part || _Schrage,
5341e69629SLRFLEW                 "The current values for a, c, and m are not currently supported on platforms without __int128");
5441e69629SLRFLEW #endif
5541e69629SLRFLEW };
5641e69629SLRFLEW 
5741e69629SLRFLEW template <unsigned long long __a,
5841e69629SLRFLEW           unsigned long long __c,
5941e69629SLRFLEW           unsigned long long __m,
6041e69629SLRFLEW           unsigned long long _Mp,
6141e69629SLRFLEW           __lce_alg_type _Mode = __lce_alg_picker<__a, __c, __m, _Mp>::__mode>
62344cef66SArthur O'Dwyer struct __lce_ta;
63344cef66SArthur O'Dwyer 
64344cef66SArthur O'Dwyer // 64
65344cef66SArthur O'Dwyer 
66ba87515fSNikolas Klauser #if _LIBCPP_HAS_INT128
6741e69629SLRFLEW template <unsigned long long _Ap, unsigned long long _Cp, unsigned long long _Mp>
6841e69629SLRFLEW struct __lce_ta<_Ap, _Cp, _Mp, (unsigned long long)(-1), _LCE_Promote> {
6941e69629SLRFLEW   typedef unsigned long long result_type;
7041e69629SLRFLEW   _LIBCPP_HIDE_FROM_ABI static result_type next(result_type __xp) {
7141e69629SLRFLEW     __extension__ using __calc_type = unsigned __int128;
7241e69629SLRFLEW     const __calc_type __a           = static_cast<__calc_type>(_Ap);
7341e69629SLRFLEW     const __calc_type __c           = static_cast<__calc_type>(_Cp);
7441e69629SLRFLEW     const __calc_type __m           = static_cast<__calc_type>(_Mp);
7541e69629SLRFLEW     const __calc_type __x           = static_cast<__calc_type>(__xp);
7641e69629SLRFLEW     return static_cast<result_type>((__a * __x + __c) % __m);
7741e69629SLRFLEW   }
7841e69629SLRFLEW };
7941e69629SLRFLEW #endif
8041e69629SLRFLEW 
81344cef66SArthur O'Dwyer template <unsigned long long __a, unsigned long long __c, unsigned long long __m>
8241e69629SLRFLEW struct __lce_ta<__a, __c, __m, (unsigned long long)(-1), _LCE_Schrage> {
83344cef66SArthur O'Dwyer   typedef unsigned long long result_type;
849783f28cSLouis Dionne   _LIBCPP_HIDE_FROM_ABI static result_type next(result_type __x) {
85344cef66SArthur O'Dwyer     // Schrage's algorithm
86344cef66SArthur O'Dwyer     const result_type __q  = __m / __a;
87344cef66SArthur O'Dwyer     const result_type __r  = __m % __a;
88344cef66SArthur O'Dwyer     const result_type __t0 = __a * (__x % __q);
89344cef66SArthur O'Dwyer     const result_type __t1 = __r * (__x / __q);
90344cef66SArthur O'Dwyer     __x                    = __t0 + (__t0 < __t1) * __m - __t1;
91344cef66SArthur O'Dwyer     __x += __c - (__x >= __m - __c) * __m;
92344cef66SArthur O'Dwyer     return __x;
93344cef66SArthur O'Dwyer   }
94344cef66SArthur O'Dwyer };
95344cef66SArthur O'Dwyer 
96344cef66SArthur O'Dwyer template <unsigned long long __a, unsigned long long __m>
9741e69629SLRFLEW struct __lce_ta<__a, 0ull, __m, (unsigned long long)(-1), _LCE_Schrage> {
98344cef66SArthur O'Dwyer   typedef unsigned long long result_type;
999783f28cSLouis Dionne   _LIBCPP_HIDE_FROM_ABI static result_type next(result_type __x) {
100344cef66SArthur O'Dwyer     // Schrage's algorithm
101344cef66SArthur O'Dwyer     const result_type __q  = __m / __a;
102344cef66SArthur O'Dwyer     const result_type __r  = __m % __a;
103344cef66SArthur O'Dwyer     const result_type __t0 = __a * (__x % __q);
104344cef66SArthur O'Dwyer     const result_type __t1 = __r * (__x / __q);
105344cef66SArthur O'Dwyer     __x                    = __t0 + (__t0 < __t1) * __m - __t1;
106344cef66SArthur O'Dwyer     return __x;
107344cef66SArthur O'Dwyer   }
108344cef66SArthur O'Dwyer };
109344cef66SArthur O'Dwyer 
110344cef66SArthur O'Dwyer template <unsigned long long __a, unsigned long long __c, unsigned long long __m>
11141e69629SLRFLEW struct __lce_ta<__a, __c, __m, (unsigned long long)(-1), _LCE_Part> {
11241e69629SLRFLEW   typedef unsigned long long result_type;
11341e69629SLRFLEW   _LIBCPP_HIDE_FROM_ABI static result_type next(result_type __x) {
11441e69629SLRFLEW     // Use (((a*x) % m) + c) % m
11541e69629SLRFLEW     __x = (__a * __x) % __m;
11641e69629SLRFLEW     __x += __c - (__x >= __m - __c) * __m;
11741e69629SLRFLEW     return __x;
11841e69629SLRFLEW   }
11941e69629SLRFLEW };
12041e69629SLRFLEW 
12141e69629SLRFLEW template <unsigned long long __a, unsigned long long __c, unsigned long long __m>
12241e69629SLRFLEW struct __lce_ta<__a, __c, __m, (unsigned long long)(-1), _LCE_Full> {
123344cef66SArthur O'Dwyer   typedef unsigned long long result_type;
1249783f28cSLouis Dionne   _LIBCPP_HIDE_FROM_ABI static result_type next(result_type __x) { return (__a * __x + __c) % __m; }
125344cef66SArthur O'Dwyer };
126344cef66SArthur O'Dwyer 
127344cef66SArthur O'Dwyer template <unsigned long long __a, unsigned long long __c>
12841e69629SLRFLEW struct __lce_ta<__a, __c, 0ull, (unsigned long long)(-1), _LCE_Full> {
129344cef66SArthur O'Dwyer   typedef unsigned long long result_type;
1309783f28cSLouis Dionne   _LIBCPP_HIDE_FROM_ABI static result_type next(result_type __x) { return __a * __x + __c; }
131344cef66SArthur O'Dwyer };
132344cef66SArthur O'Dwyer 
133344cef66SArthur O'Dwyer // 32
134344cef66SArthur O'Dwyer 
13541e69629SLRFLEW template <unsigned long long __a, unsigned long long __c, unsigned long long __m>
13641e69629SLRFLEW struct __lce_ta<__a, __c, __m, unsigned(-1), _LCE_Promote> {
13741e69629SLRFLEW   typedef unsigned result_type;
13841e69629SLRFLEW   _LIBCPP_HIDE_FROM_ABI static result_type next(result_type __x) {
13941e69629SLRFLEW     return static_cast<result_type>(__lce_ta<__a, __c, __m, (unsigned long long)(-1)>::next(__x));
14041e69629SLRFLEW   }
14141e69629SLRFLEW };
14241e69629SLRFLEW 
143344cef66SArthur O'Dwyer template <unsigned long long _Ap, unsigned long long _Cp, unsigned long long _Mp>
14441e69629SLRFLEW struct __lce_ta<_Ap, _Cp, _Mp, unsigned(-1), _LCE_Schrage> {
145344cef66SArthur O'Dwyer   typedef unsigned result_type;
1469783f28cSLouis Dionne   _LIBCPP_HIDE_FROM_ABI static result_type next(result_type __x) {
147344cef66SArthur O'Dwyer     const result_type __a = static_cast<result_type>(_Ap);
148344cef66SArthur O'Dwyer     const result_type __c = static_cast<result_type>(_Cp);
149344cef66SArthur O'Dwyer     const result_type __m = static_cast<result_type>(_Mp);
150344cef66SArthur O'Dwyer     // Schrage's algorithm
151344cef66SArthur O'Dwyer     const result_type __q  = __m / __a;
152344cef66SArthur O'Dwyer     const result_type __r  = __m % __a;
153344cef66SArthur O'Dwyer     const result_type __t0 = __a * (__x % __q);
154344cef66SArthur O'Dwyer     const result_type __t1 = __r * (__x / __q);
155344cef66SArthur O'Dwyer     __x                    = __t0 + (__t0 < __t1) * __m - __t1;
156344cef66SArthur O'Dwyer     __x += __c - (__x >= __m - __c) * __m;
157344cef66SArthur O'Dwyer     return __x;
158344cef66SArthur O'Dwyer   }
159344cef66SArthur O'Dwyer };
160344cef66SArthur O'Dwyer 
161344cef66SArthur O'Dwyer template <unsigned long long _Ap, unsigned long long _Mp>
16241e69629SLRFLEW struct __lce_ta<_Ap, 0ull, _Mp, unsigned(-1), _LCE_Schrage> {
163344cef66SArthur O'Dwyer   typedef unsigned result_type;
1649783f28cSLouis Dionne   _LIBCPP_HIDE_FROM_ABI static result_type next(result_type __x) {
165344cef66SArthur O'Dwyer     const result_type __a = static_cast<result_type>(_Ap);
166344cef66SArthur O'Dwyer     const result_type __m = static_cast<result_type>(_Mp);
167344cef66SArthur O'Dwyer     // Schrage's algorithm
168344cef66SArthur O'Dwyer     const result_type __q  = __m / __a;
169344cef66SArthur O'Dwyer     const result_type __r  = __m % __a;
170344cef66SArthur O'Dwyer     const result_type __t0 = __a * (__x % __q);
171344cef66SArthur O'Dwyer     const result_type __t1 = __r * (__x / __q);
172344cef66SArthur O'Dwyer     __x                    = __t0 + (__t0 < __t1) * __m - __t1;
173344cef66SArthur O'Dwyer     return __x;
174344cef66SArthur O'Dwyer   }
175344cef66SArthur O'Dwyer };
176344cef66SArthur O'Dwyer 
177344cef66SArthur O'Dwyer template <unsigned long long _Ap, unsigned long long _Cp, unsigned long long _Mp>
17841e69629SLRFLEW struct __lce_ta<_Ap, _Cp, _Mp, unsigned(-1), _LCE_Part> {
17941e69629SLRFLEW   typedef unsigned result_type;
18041e69629SLRFLEW   _LIBCPP_HIDE_FROM_ABI static result_type next(result_type __x) {
18141e69629SLRFLEW     const result_type __a = static_cast<result_type>(_Ap);
18241e69629SLRFLEW     const result_type __c = static_cast<result_type>(_Cp);
18341e69629SLRFLEW     const result_type __m = static_cast<result_type>(_Mp);
18441e69629SLRFLEW     // Use (((a*x) % m) + c) % m
18541e69629SLRFLEW     __x = (__a * __x) % __m;
18641e69629SLRFLEW     __x += __c - (__x >= __m - __c) * __m;
18741e69629SLRFLEW     return __x;
18841e69629SLRFLEW   }
18941e69629SLRFLEW };
19041e69629SLRFLEW 
19141e69629SLRFLEW template <unsigned long long _Ap, unsigned long long _Cp, unsigned long long _Mp>
19241e69629SLRFLEW struct __lce_ta<_Ap, _Cp, _Mp, unsigned(-1), _LCE_Full> {
193344cef66SArthur O'Dwyer   typedef unsigned result_type;
1949783f28cSLouis Dionne   _LIBCPP_HIDE_FROM_ABI static result_type next(result_type __x) {
195344cef66SArthur O'Dwyer     const result_type __a = static_cast<result_type>(_Ap);
196344cef66SArthur O'Dwyer     const result_type __c = static_cast<result_type>(_Cp);
197344cef66SArthur O'Dwyer     const result_type __m = static_cast<result_type>(_Mp);
198344cef66SArthur O'Dwyer     return (__a * __x + __c) % __m;
199344cef66SArthur O'Dwyer   }
200344cef66SArthur O'Dwyer };
201344cef66SArthur O'Dwyer 
202344cef66SArthur O'Dwyer template <unsigned long long _Ap, unsigned long long _Cp>
20341e69629SLRFLEW struct __lce_ta<_Ap, _Cp, 0ull, unsigned(-1), _LCE_Full> {
204344cef66SArthur O'Dwyer   typedef unsigned result_type;
2059783f28cSLouis Dionne   _LIBCPP_HIDE_FROM_ABI static result_type next(result_type __x) {
206344cef66SArthur O'Dwyer     const result_type __a = static_cast<result_type>(_Ap);
207344cef66SArthur O'Dwyer     const result_type __c = static_cast<result_type>(_Cp);
208344cef66SArthur O'Dwyer     return __a * __x + __c;
209344cef66SArthur O'Dwyer   }
210344cef66SArthur O'Dwyer };
211344cef66SArthur O'Dwyer 
212344cef66SArthur O'Dwyer // 16
213344cef66SArthur O'Dwyer 
21441e69629SLRFLEW template <unsigned long long __a, unsigned long long __c, unsigned long long __m, __lce_alg_type __mode>
21541e69629SLRFLEW struct __lce_ta<__a, __c, __m, (unsigned short)(-1), __mode> {
216344cef66SArthur O'Dwyer   typedef unsigned short result_type;
2179783f28cSLouis Dionne   _LIBCPP_HIDE_FROM_ABI static result_type next(result_type __x) {
21841e69629SLRFLEW     return static_cast<result_type>(__lce_ta<__a, __c, __m, unsigned(-1)>::next(__x));
219344cef66SArthur O'Dwyer   }
220344cef66SArthur O'Dwyer };
221344cef66SArthur O'Dwyer 
222344cef66SArthur O'Dwyer template <class _UIntType, _UIntType __a, _UIntType __c, _UIntType __m>
223344cef66SArthur O'Dwyer class _LIBCPP_TEMPLATE_VIS linear_congruential_engine;
224344cef66SArthur O'Dwyer 
2259783f28cSLouis Dionne template <class _CharT, class _Traits, class _Up, _Up _Ap, _Up _Cp, _Up _Np>
2269783f28cSLouis Dionne _LIBCPP_HIDE_FROM_ABI basic_ostream<_CharT, _Traits>&
2279783f28cSLouis Dionne operator<<(basic_ostream<_CharT, _Traits>& __os, const linear_congruential_engine<_Up, _Ap, _Cp, _Np>&);
228344cef66SArthur O'Dwyer 
2299783f28cSLouis Dionne template <class _CharT, class _Traits, class _Up, _Up _Ap, _Up _Cp, _Up _Np>
23080c7e93aSNikolas Klauser _LIBCPP_HIDE_FROM_ABI basic_istream<_CharT, _Traits>&
2319783f28cSLouis Dionne operator>>(basic_istream<_CharT, _Traits>& __is, linear_congruential_engine<_Up, _Ap, _Cp, _Np>& __x);
232344cef66SArthur O'Dwyer 
233344cef66SArthur O'Dwyer template <class _UIntType, _UIntType __a, _UIntType __c, _UIntType __m>
2349783f28cSLouis Dionne class _LIBCPP_TEMPLATE_VIS linear_congruential_engine {
235344cef66SArthur O'Dwyer public:
236344cef66SArthur O'Dwyer   // types
237344cef66SArthur O'Dwyer   typedef _UIntType result_type;
238344cef66SArthur O'Dwyer 
239344cef66SArthur O'Dwyer private:
240344cef66SArthur O'Dwyer   result_type __x_;
241344cef66SArthur O'Dwyer 
24241e69629SLRFLEW   static _LIBCPP_CONSTEXPR const result_type _Mp = result_type(-1);
243344cef66SArthur O'Dwyer 
244344cef66SArthur O'Dwyer   static_assert(__m == 0 || __a < __m, "linear_congruential_engine invalid parameters");
245344cef66SArthur O'Dwyer   static_assert(__m == 0 || __c < __m, "linear_congruential_engine invalid parameters");
246344cef66SArthur O'Dwyer   static_assert(is_unsigned<_UIntType>::value, "_UIntType must be unsigned type");
2479783f28cSLouis Dionne 
248344cef66SArthur O'Dwyer public:
249344cef66SArthur O'Dwyer   static _LIBCPP_CONSTEXPR const result_type _Min = __c == 0u ? 1u : 0u;
250e39095a3SLouis Dionne   static _LIBCPP_CONSTEXPR const result_type _Max = __m - _UIntType(1u);
251344cef66SArthur O'Dwyer   static_assert(_Min < _Max, "linear_congruential_engine invalid parameters");
252344cef66SArthur O'Dwyer 
253344cef66SArthur O'Dwyer   // engine characteristics
254*b69ddbc6SNikolas Klauser   static inline _LIBCPP_CONSTEXPR const result_type multiplier = __a;
255*b69ddbc6SNikolas Klauser   static inline _LIBCPP_CONSTEXPR const result_type increment  = __c;
256*b69ddbc6SNikolas Klauser   static inline _LIBCPP_CONSTEXPR const result_type modulus    = __m;
2579783f28cSLouis Dionne   _LIBCPP_HIDE_FROM_ABI static _LIBCPP_CONSTEXPR result_type min() { return _Min; }
2589783f28cSLouis Dionne   _LIBCPP_HIDE_FROM_ABI static _LIBCPP_CONSTEXPR result_type max() { return _Max; }
259*b69ddbc6SNikolas Klauser   static inline _LIBCPP_CONSTEXPR const result_type default_seed = 1u;
260344cef66SArthur O'Dwyer 
261344cef66SArthur O'Dwyer   // constructors and seeding functions
262344cef66SArthur O'Dwyer #ifndef _LIBCPP_CXX03_LANG
2639783f28cSLouis Dionne   _LIBCPP_HIDE_FROM_ABI linear_congruential_engine() : linear_congruential_engine(default_seed) {}
2649783f28cSLouis Dionne   _LIBCPP_HIDE_FROM_ABI explicit linear_congruential_engine(result_type __s) { seed(__s); }
265344cef66SArthur O'Dwyer #else
2669783f28cSLouis Dionne   _LIBCPP_HIDE_FROM_ABI explicit linear_congruential_engine(result_type __s = default_seed) { seed(__s); }
267344cef66SArthur O'Dwyer #endif
2684da76ea7SNikolas Klauser   template <class _Sseq, __enable_if_t<__is_seed_sequence<_Sseq, linear_congruential_engine>::value, int> = 0>
2699783f28cSLouis Dionne   _LIBCPP_HIDE_FROM_ABI explicit linear_congruential_engine(_Sseq& __q) {
2709783f28cSLouis Dionne     seed(__q);
2719783f28cSLouis Dionne   }
2729783f28cSLouis Dionne   _LIBCPP_HIDE_FROM_ABI void seed(result_type __s = default_seed) {
2739783f28cSLouis Dionne     seed(integral_constant<bool, __m == 0>(), integral_constant<bool, __c == 0>(), __s);
2749783f28cSLouis Dionne   }
275475bd19eSNikolas Klauser   template <class _Sseq, __enable_if_t<__is_seed_sequence<_Sseq, linear_congruential_engine>::value, int> = 0>
2769783f28cSLouis Dionne   _LIBCPP_HIDE_FROM_ABI void seed(_Sseq& __q) {
2779783f28cSLouis Dionne     __seed(
2789783f28cSLouis Dionne         __q,
2799783f28cSLouis Dionne         integral_constant<unsigned,
2809783f28cSLouis Dionne                           1 + (__m == 0 ? (sizeof(result_type) * __CHAR_BIT__ - 1) / 32 : (__m > 0x100000000ull))>());
2819783f28cSLouis Dionne   }
282344cef66SArthur O'Dwyer 
283344cef66SArthur O'Dwyer   // generating functions
2849783f28cSLouis Dionne   _LIBCPP_HIDE_FROM_ABI result_type operator()() {
2859783f28cSLouis Dionne     return __x_ = static_cast<result_type>(__lce_ta<__a, __c, __m, _Mp>::next(__x_));
2869783f28cSLouis Dionne   }
2879783f28cSLouis Dionne   _LIBCPP_HIDE_FROM_ABI void discard(unsigned long long __z) {
2889783f28cSLouis Dionne     for (; __z; --__z)
2899783f28cSLouis Dionne       operator()();
2909783f28cSLouis Dionne   }
291344cef66SArthur O'Dwyer 
2929783f28cSLouis Dionne   friend _LIBCPP_HIDE_FROM_ABI bool
2939783f28cSLouis Dionne   operator==(const linear_congruential_engine& __x, const linear_congruential_engine& __y) {
2949783f28cSLouis Dionne     return __x.__x_ == __y.__x_;
2959783f28cSLouis Dionne   }
2969783f28cSLouis Dionne   friend _LIBCPP_HIDE_FROM_ABI bool
2979783f28cSLouis Dionne   operator!=(const linear_congruential_engine& __x, const linear_congruential_engine& __y) {
2989783f28cSLouis Dionne     return !(__x == __y);
2999783f28cSLouis Dionne   }
300344cef66SArthur O'Dwyer 
301344cef66SArthur O'Dwyer private:
3029783f28cSLouis Dionne   _LIBCPP_HIDE_FROM_ABI void seed(true_type, true_type, result_type __s) { __x_ = __s == 0 ? 1 : __s; }
3039783f28cSLouis Dionne   _LIBCPP_HIDE_FROM_ABI void seed(true_type, false_type, result_type __s) { __x_ = __s; }
3049783f28cSLouis Dionne   _LIBCPP_HIDE_FROM_ABI void seed(false_type, true_type, result_type __s) { __x_ = __s % __m == 0 ? 1 : __s % __m; }
3059783f28cSLouis Dionne   _LIBCPP_HIDE_FROM_ABI void seed(false_type, false_type, result_type __s) { __x_ = __s % __m; }
306344cef66SArthur O'Dwyer 
307344cef66SArthur O'Dwyer   template <class _Sseq>
30883ce1397SNikolas Klauser   _LIBCPP_HIDE_FROM_ABI void __seed(_Sseq& __q, integral_constant<unsigned, 1>);
309344cef66SArthur O'Dwyer   template <class _Sseq>
31083ce1397SNikolas Klauser   _LIBCPP_HIDE_FROM_ABI void __seed(_Sseq& __q, integral_constant<unsigned, 2>);
311344cef66SArthur O'Dwyer 
3129783f28cSLouis Dionne   template <class _CharT, class _Traits, class _Up, _Up _Ap, _Up _Cp, _Up _Np>
3139783f28cSLouis Dionne   friend basic_ostream<_CharT, _Traits>&
3149783f28cSLouis Dionne   operator<<(basic_ostream<_CharT, _Traits>& __os, const linear_congruential_engine<_Up, _Ap, _Cp, _Np>&);
315344cef66SArthur O'Dwyer 
3169783f28cSLouis Dionne   template <class _CharT, class _Traits, class _Up, _Up _Ap, _Up _Cp, _Up _Np>
3179783f28cSLouis Dionne   friend basic_istream<_CharT, _Traits>&
3189783f28cSLouis Dionne   operator>>(basic_istream<_CharT, _Traits>& __is, linear_congruential_engine<_Up, _Ap, _Cp, _Np>& __x);
319344cef66SArthur O'Dwyer };
320344cef66SArthur O'Dwyer 
321344cef66SArthur O'Dwyer template <class _UIntType, _UIntType __a, _UIntType __c, _UIntType __m>
322344cef66SArthur O'Dwyer template <class _Sseq>
3239783f28cSLouis Dionne void linear_congruential_engine<_UIntType, __a, __c, __m>::__seed(_Sseq& __q, integral_constant<unsigned, 1>) {
324344cef66SArthur O'Dwyer   const unsigned __k = 1;
325344cef66SArthur O'Dwyer   uint32_t __ar[__k + 3];
326344cef66SArthur O'Dwyer   __q.generate(__ar, __ar + __k + 3);
327344cef66SArthur O'Dwyer   result_type __s = static_cast<result_type>(__ar[3] % __m);
328344cef66SArthur O'Dwyer   __x_            = __c == 0 && __s == 0 ? result_type(1) : __s;
329344cef66SArthur O'Dwyer }
330344cef66SArthur O'Dwyer 
331344cef66SArthur O'Dwyer template <class _UIntType, _UIntType __a, _UIntType __c, _UIntType __m>
332344cef66SArthur O'Dwyer template <class _Sseq>
3339783f28cSLouis Dionne void linear_congruential_engine<_UIntType, __a, __c, __m>::__seed(_Sseq& __q, integral_constant<unsigned, 2>) {
334344cef66SArthur O'Dwyer   const unsigned __k = 2;
335344cef66SArthur O'Dwyer   uint32_t __ar[__k + 3];
336344cef66SArthur O'Dwyer   __q.generate(__ar, __ar + __k + 3);
3379783f28cSLouis Dionne   result_type __s = static_cast<result_type>((__ar[3] + ((uint64_t)__ar[4] << 32)) % __m);
338344cef66SArthur O'Dwyer   __x_            = __c == 0 && __s == 0 ? result_type(1) : __s;
339344cef66SArthur O'Dwyer }
340344cef66SArthur O'Dwyer 
3419783f28cSLouis Dionne template <class _CharT, class _Traits, class _UIntType, _UIntType __a, _UIntType __c, _UIntType __m>
3429783f28cSLouis Dionne inline _LIBCPP_HIDE_FROM_ABI basic_ostream<_CharT, _Traits>&
3439783f28cSLouis Dionne operator<<(basic_ostream<_CharT, _Traits>& __os, const linear_congruential_engine<_UIntType, __a, __c, __m>& __x) {
344344cef66SArthur O'Dwyer   __save_flags<_CharT, _Traits> __lx(__os);
345344cef66SArthur O'Dwyer   typedef basic_ostream<_CharT, _Traits> _Ostream;
346344cef66SArthur O'Dwyer   __os.flags(_Ostream::dec | _Ostream::left);
347344cef66SArthur O'Dwyer   __os.fill(__os.widen(' '));
348344cef66SArthur O'Dwyer   return __os << __x.__x_;
349344cef66SArthur O'Dwyer }
350344cef66SArthur O'Dwyer 
3519783f28cSLouis Dionne template <class _CharT, class _Traits, class _UIntType, _UIntType __a, _UIntType __c, _UIntType __m>
35280c7e93aSNikolas Klauser _LIBCPP_HIDE_FROM_ABI basic_istream<_CharT, _Traits>&
3539783f28cSLouis Dionne operator>>(basic_istream<_CharT, _Traits>& __is, linear_congruential_engine<_UIntType, __a, __c, __m>& __x) {
354344cef66SArthur O'Dwyer   __save_flags<_CharT, _Traits> __lx(__is);
355344cef66SArthur O'Dwyer   typedef basic_istream<_CharT, _Traits> _Istream;
356344cef66SArthur O'Dwyer   __is.flags(_Istream::dec | _Istream::skipws);
357344cef66SArthur O'Dwyer   _UIntType __t;
358344cef66SArthur O'Dwyer   __is >> __t;
359344cef66SArthur O'Dwyer   if (!__is.fail())
360344cef66SArthur O'Dwyer     __x.__x_ = __t;
361344cef66SArthur O'Dwyer   return __is;
362344cef66SArthur O'Dwyer }
363344cef66SArthur O'Dwyer 
3649783f28cSLouis Dionne typedef linear_congruential_engine<uint_fast32_t, 16807, 0, 2147483647> minstd_rand0;
3659783f28cSLouis Dionne typedef linear_congruential_engine<uint_fast32_t, 48271, 0, 2147483647> minstd_rand;
366344cef66SArthur O'Dwyer 
367344cef66SArthur O'Dwyer _LIBCPP_END_NAMESPACE_STD
368344cef66SArthur O'Dwyer 
369344cef66SArthur O'Dwyer _LIBCPP_POP_MACROS
370344cef66SArthur O'Dwyer 
371344cef66SArthur O'Dwyer #endif // _LIBCPP___RANDOM_LINEAR_CONGRUENTIAL_ENGINE_H
372