xref: /freebsd/contrib/llvm-project/libcxx/include/__random/linear_congruential_engine.h (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
14824e7fdSDimitry Andric //===----------------------------------------------------------------------===//
24824e7fdSDimitry Andric //
34824e7fdSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
44824e7fdSDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
54824e7fdSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
64824e7fdSDimitry Andric //
74824e7fdSDimitry Andric //===----------------------------------------------------------------------===//
84824e7fdSDimitry Andric 
94824e7fdSDimitry Andric #ifndef _LIBCPP___RANDOM_LINEAR_CONGRUENTIAL_ENGINE_H
104824e7fdSDimitry Andric #define _LIBCPP___RANDOM_LINEAR_CONGRUENTIAL_ENGINE_H
114824e7fdSDimitry Andric 
124824e7fdSDimitry Andric #include <__config>
134824e7fdSDimitry Andric #include <__random/is_seed_sequence.h>
1406c3fb27SDimitry Andric #include <__type_traits/enable_if.h>
1506c3fb27SDimitry Andric #include <__type_traits/integral_constant.h>
1606c3fb27SDimitry Andric #include <__type_traits/is_unsigned.h>
174824e7fdSDimitry Andric #include <cstdint>
184824e7fdSDimitry Andric #include <iosfwd>
194824e7fdSDimitry Andric 
204824e7fdSDimitry Andric #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
214824e7fdSDimitry Andric #  pragma GCC system_header
224824e7fdSDimitry Andric #endif
234824e7fdSDimitry Andric 
244824e7fdSDimitry Andric _LIBCPP_PUSH_MACROS
254824e7fdSDimitry Andric #include <__undef_macros>
264824e7fdSDimitry Andric 
274824e7fdSDimitry Andric _LIBCPP_BEGIN_NAMESPACE_STD
284824e7fdSDimitry Andric 
29*0fca6ea1SDimitry Andric enum __lce_alg_type {
30*0fca6ea1SDimitry Andric   _LCE_Full,
31*0fca6ea1SDimitry Andric   _LCE_Part,
32*0fca6ea1SDimitry Andric   _LCE_Schrage,
33*0fca6ea1SDimitry Andric   _LCE_Promote,
344824e7fdSDimitry Andric };
354824e7fdSDimitry Andric 
36cb14a3feSDimitry Andric template <unsigned long long __a,
37cb14a3feSDimitry Andric           unsigned long long __c,
38cb14a3feSDimitry Andric           unsigned long long __m,
39cb14a3feSDimitry Andric           unsigned long long _Mp,
40*0fca6ea1SDimitry Andric           bool _HasOverflow = (__a != 0ull && (__m & (__m - 1ull)) != 0ull),      // a != 0, m != 0, m != 2^n
41*0fca6ea1SDimitry Andric           bool _Full        = (!_HasOverflow || __m - 1ull <= (_Mp - __c) / __a), // (a * x + c) % m works
42*0fca6ea1SDimitry Andric           bool _Part        = (!_HasOverflow || __m - 1ull <= _Mp / __a),         // (a * x) % m works
43*0fca6ea1SDimitry Andric           bool _Schrage     = (_HasOverflow && __m % __a <= __m / __a)>               // r <= q
44*0fca6ea1SDimitry Andric struct __lce_alg_picker {
45*0fca6ea1SDimitry Andric   static _LIBCPP_CONSTEXPR const __lce_alg_type __mode =
46*0fca6ea1SDimitry Andric       _Full      ? _LCE_Full
47*0fca6ea1SDimitry Andric       : _Part    ? _LCE_Part
48*0fca6ea1SDimitry Andric       : _Schrage ? _LCE_Schrage
49*0fca6ea1SDimitry Andric                  : _LCE_Promote;
50*0fca6ea1SDimitry Andric 
51*0fca6ea1SDimitry Andric #ifdef _LIBCPP_HAS_NO_INT128
52*0fca6ea1SDimitry Andric   static_assert(_Mp != (unsigned long long)(-1) || _Full || _Part || _Schrage,
53*0fca6ea1SDimitry Andric                 "The current values for a, c, and m are not currently supported on platforms without __int128");
54*0fca6ea1SDimitry Andric #endif
55*0fca6ea1SDimitry Andric };
56*0fca6ea1SDimitry Andric 
57*0fca6ea1SDimitry Andric template <unsigned long long __a,
58*0fca6ea1SDimitry Andric           unsigned long long __c,
59*0fca6ea1SDimitry Andric           unsigned long long __m,
60*0fca6ea1SDimitry Andric           unsigned long long _Mp,
61*0fca6ea1SDimitry Andric           __lce_alg_type _Mode = __lce_alg_picker<__a, __c, __m, _Mp>::__mode>
624824e7fdSDimitry Andric struct __lce_ta;
634824e7fdSDimitry Andric 
644824e7fdSDimitry Andric // 64
654824e7fdSDimitry Andric 
66*0fca6ea1SDimitry Andric #ifndef _LIBCPP_HAS_NO_INT128
67*0fca6ea1SDimitry Andric template <unsigned long long _Ap, unsigned long long _Cp, unsigned long long _Mp>
68*0fca6ea1SDimitry Andric struct __lce_ta<_Ap, _Cp, _Mp, (unsigned long long)(-1), _LCE_Promote> {
69*0fca6ea1SDimitry Andric   typedef unsigned long long result_type;
70*0fca6ea1SDimitry Andric   _LIBCPP_HIDE_FROM_ABI static result_type next(result_type __xp) {
71*0fca6ea1SDimitry Andric     __extension__ using __calc_type = unsigned __int128;
72*0fca6ea1SDimitry Andric     const __calc_type __a           = static_cast<__calc_type>(_Ap);
73*0fca6ea1SDimitry Andric     const __calc_type __c           = static_cast<__calc_type>(_Cp);
74*0fca6ea1SDimitry Andric     const __calc_type __m           = static_cast<__calc_type>(_Mp);
75*0fca6ea1SDimitry Andric     const __calc_type __x           = static_cast<__calc_type>(__xp);
76*0fca6ea1SDimitry Andric     return static_cast<result_type>((__a * __x + __c) % __m);
77*0fca6ea1SDimitry Andric   }
78*0fca6ea1SDimitry Andric };
79*0fca6ea1SDimitry Andric #endif
80*0fca6ea1SDimitry Andric 
814824e7fdSDimitry Andric template <unsigned long long __a, unsigned long long __c, unsigned long long __m>
82*0fca6ea1SDimitry Andric struct __lce_ta<__a, __c, __m, (unsigned long long)(-1), _LCE_Schrage> {
834824e7fdSDimitry Andric   typedef unsigned long long result_type;
84cb14a3feSDimitry Andric   _LIBCPP_HIDE_FROM_ABI static result_type next(result_type __x) {
854824e7fdSDimitry Andric     // Schrage's algorithm
864824e7fdSDimitry Andric     const result_type __q  = __m / __a;
874824e7fdSDimitry Andric     const result_type __r  = __m % __a;
884824e7fdSDimitry Andric     const result_type __t0 = __a * (__x % __q);
894824e7fdSDimitry Andric     const result_type __t1 = __r * (__x / __q);
904824e7fdSDimitry Andric     __x                    = __t0 + (__t0 < __t1) * __m - __t1;
914824e7fdSDimitry Andric     __x += __c - (__x >= __m - __c) * __m;
924824e7fdSDimitry Andric     return __x;
934824e7fdSDimitry Andric   }
944824e7fdSDimitry Andric };
954824e7fdSDimitry Andric 
964824e7fdSDimitry Andric template <unsigned long long __a, unsigned long long __m>
97*0fca6ea1SDimitry Andric struct __lce_ta<__a, 0ull, __m, (unsigned long long)(-1), _LCE_Schrage> {
984824e7fdSDimitry Andric   typedef unsigned long long result_type;
99cb14a3feSDimitry Andric   _LIBCPP_HIDE_FROM_ABI static result_type next(result_type __x) {
1004824e7fdSDimitry Andric     // Schrage's algorithm
1014824e7fdSDimitry Andric     const result_type __q  = __m / __a;
1024824e7fdSDimitry Andric     const result_type __r  = __m % __a;
1034824e7fdSDimitry Andric     const result_type __t0 = __a * (__x % __q);
1044824e7fdSDimitry Andric     const result_type __t1 = __r * (__x / __q);
1054824e7fdSDimitry Andric     __x                    = __t0 + (__t0 < __t1) * __m - __t1;
1064824e7fdSDimitry Andric     return __x;
1074824e7fdSDimitry Andric   }
1084824e7fdSDimitry Andric };
1094824e7fdSDimitry Andric 
1104824e7fdSDimitry Andric template <unsigned long long __a, unsigned long long __c, unsigned long long __m>
111*0fca6ea1SDimitry Andric struct __lce_ta<__a, __c, __m, (unsigned long long)(-1), _LCE_Part> {
112*0fca6ea1SDimitry Andric   typedef unsigned long long result_type;
113*0fca6ea1SDimitry Andric   _LIBCPP_HIDE_FROM_ABI static result_type next(result_type __x) {
114*0fca6ea1SDimitry Andric     // Use (((a*x) % m) + c) % m
115*0fca6ea1SDimitry Andric     __x = (__a * __x) % __m;
116*0fca6ea1SDimitry Andric     __x += __c - (__x >= __m - __c) * __m;
117*0fca6ea1SDimitry Andric     return __x;
118*0fca6ea1SDimitry Andric   }
119*0fca6ea1SDimitry Andric };
120*0fca6ea1SDimitry Andric 
121*0fca6ea1SDimitry Andric template <unsigned long long __a, unsigned long long __c, unsigned long long __m>
122*0fca6ea1SDimitry Andric struct __lce_ta<__a, __c, __m, (unsigned long long)(-1), _LCE_Full> {
1234824e7fdSDimitry Andric   typedef unsigned long long result_type;
124cb14a3feSDimitry Andric   _LIBCPP_HIDE_FROM_ABI static result_type next(result_type __x) { return (__a * __x + __c) % __m; }
1254824e7fdSDimitry Andric };
1264824e7fdSDimitry Andric 
1274824e7fdSDimitry Andric template <unsigned long long __a, unsigned long long __c>
128*0fca6ea1SDimitry Andric struct __lce_ta<__a, __c, 0ull, (unsigned long long)(-1), _LCE_Full> {
1294824e7fdSDimitry Andric   typedef unsigned long long result_type;
130cb14a3feSDimitry Andric   _LIBCPP_HIDE_FROM_ABI static result_type next(result_type __x) { return __a * __x + __c; }
1314824e7fdSDimitry Andric };
1324824e7fdSDimitry Andric 
1334824e7fdSDimitry Andric // 32
1344824e7fdSDimitry Andric 
135*0fca6ea1SDimitry Andric template <unsigned long long __a, unsigned long long __c, unsigned long long __m>
136*0fca6ea1SDimitry Andric struct __lce_ta<__a, __c, __m, unsigned(-1), _LCE_Promote> {
137*0fca6ea1SDimitry Andric   typedef unsigned result_type;
138*0fca6ea1SDimitry Andric   _LIBCPP_HIDE_FROM_ABI static result_type next(result_type __x) {
139*0fca6ea1SDimitry Andric     return static_cast<result_type>(__lce_ta<__a, __c, __m, (unsigned long long)(-1)>::next(__x));
140*0fca6ea1SDimitry Andric   }
141*0fca6ea1SDimitry Andric };
142*0fca6ea1SDimitry Andric 
1434824e7fdSDimitry Andric template <unsigned long long _Ap, unsigned long long _Cp, unsigned long long _Mp>
144*0fca6ea1SDimitry Andric struct __lce_ta<_Ap, _Cp, _Mp, unsigned(-1), _LCE_Schrage> {
1454824e7fdSDimitry Andric   typedef unsigned result_type;
146cb14a3feSDimitry Andric   _LIBCPP_HIDE_FROM_ABI static result_type next(result_type __x) {
1474824e7fdSDimitry Andric     const result_type __a = static_cast<result_type>(_Ap);
1484824e7fdSDimitry Andric     const result_type __c = static_cast<result_type>(_Cp);
1494824e7fdSDimitry Andric     const result_type __m = static_cast<result_type>(_Mp);
1504824e7fdSDimitry Andric     // Schrage's algorithm
1514824e7fdSDimitry Andric     const result_type __q  = __m / __a;
1524824e7fdSDimitry Andric     const result_type __r  = __m % __a;
1534824e7fdSDimitry Andric     const result_type __t0 = __a * (__x % __q);
1544824e7fdSDimitry Andric     const result_type __t1 = __r * (__x / __q);
1554824e7fdSDimitry Andric     __x                    = __t0 + (__t0 < __t1) * __m - __t1;
1564824e7fdSDimitry Andric     __x += __c - (__x >= __m - __c) * __m;
1574824e7fdSDimitry Andric     return __x;
1584824e7fdSDimitry Andric   }
1594824e7fdSDimitry Andric };
1604824e7fdSDimitry Andric 
1614824e7fdSDimitry Andric template <unsigned long long _Ap, unsigned long long _Mp>
162*0fca6ea1SDimitry Andric struct __lce_ta<_Ap, 0ull, _Mp, unsigned(-1), _LCE_Schrage> {
1634824e7fdSDimitry Andric   typedef unsigned result_type;
164cb14a3feSDimitry Andric   _LIBCPP_HIDE_FROM_ABI static result_type next(result_type __x) {
1654824e7fdSDimitry Andric     const result_type __a = static_cast<result_type>(_Ap);
1664824e7fdSDimitry Andric     const result_type __m = static_cast<result_type>(_Mp);
1674824e7fdSDimitry Andric     // Schrage's algorithm
1684824e7fdSDimitry Andric     const result_type __q  = __m / __a;
1694824e7fdSDimitry Andric     const result_type __r  = __m % __a;
1704824e7fdSDimitry Andric     const result_type __t0 = __a * (__x % __q);
1714824e7fdSDimitry Andric     const result_type __t1 = __r * (__x / __q);
1724824e7fdSDimitry Andric     __x                    = __t0 + (__t0 < __t1) * __m - __t1;
1734824e7fdSDimitry Andric     return __x;
1744824e7fdSDimitry Andric   }
1754824e7fdSDimitry Andric };
1764824e7fdSDimitry Andric 
1774824e7fdSDimitry Andric template <unsigned long long _Ap, unsigned long long _Cp, unsigned long long _Mp>
178*0fca6ea1SDimitry Andric struct __lce_ta<_Ap, _Cp, _Mp, unsigned(-1), _LCE_Part> {
179*0fca6ea1SDimitry Andric   typedef unsigned result_type;
180*0fca6ea1SDimitry Andric   _LIBCPP_HIDE_FROM_ABI static result_type next(result_type __x) {
181*0fca6ea1SDimitry Andric     const result_type __a = static_cast<result_type>(_Ap);
182*0fca6ea1SDimitry Andric     const result_type __c = static_cast<result_type>(_Cp);
183*0fca6ea1SDimitry Andric     const result_type __m = static_cast<result_type>(_Mp);
184*0fca6ea1SDimitry Andric     // Use (((a*x) % m) + c) % m
185*0fca6ea1SDimitry Andric     __x = (__a * __x) % __m;
186*0fca6ea1SDimitry Andric     __x += __c - (__x >= __m - __c) * __m;
187*0fca6ea1SDimitry Andric     return __x;
188*0fca6ea1SDimitry Andric   }
189*0fca6ea1SDimitry Andric };
190*0fca6ea1SDimitry Andric 
191*0fca6ea1SDimitry Andric template <unsigned long long _Ap, unsigned long long _Cp, unsigned long long _Mp>
192*0fca6ea1SDimitry Andric struct __lce_ta<_Ap, _Cp, _Mp, unsigned(-1), _LCE_Full> {
1934824e7fdSDimitry Andric   typedef unsigned result_type;
194cb14a3feSDimitry Andric   _LIBCPP_HIDE_FROM_ABI static result_type next(result_type __x) {
1954824e7fdSDimitry Andric     const result_type __a = static_cast<result_type>(_Ap);
1964824e7fdSDimitry Andric     const result_type __c = static_cast<result_type>(_Cp);
1974824e7fdSDimitry Andric     const result_type __m = static_cast<result_type>(_Mp);
1984824e7fdSDimitry Andric     return (__a * __x + __c) % __m;
1994824e7fdSDimitry Andric   }
2004824e7fdSDimitry Andric };
2014824e7fdSDimitry Andric 
2024824e7fdSDimitry Andric template <unsigned long long _Ap, unsigned long long _Cp>
203*0fca6ea1SDimitry Andric struct __lce_ta<_Ap, _Cp, 0ull, unsigned(-1), _LCE_Full> {
2044824e7fdSDimitry Andric   typedef unsigned result_type;
205cb14a3feSDimitry Andric   _LIBCPP_HIDE_FROM_ABI static result_type next(result_type __x) {
2064824e7fdSDimitry Andric     const result_type __a = static_cast<result_type>(_Ap);
2074824e7fdSDimitry Andric     const result_type __c = static_cast<result_type>(_Cp);
2084824e7fdSDimitry Andric     return __a * __x + __c;
2094824e7fdSDimitry Andric   }
2104824e7fdSDimitry Andric };
2114824e7fdSDimitry Andric 
2124824e7fdSDimitry Andric // 16
2134824e7fdSDimitry Andric 
214*0fca6ea1SDimitry Andric template <unsigned long long __a, unsigned long long __c, unsigned long long __m, __lce_alg_type __mode>
215*0fca6ea1SDimitry Andric struct __lce_ta<__a, __c, __m, (unsigned short)(-1), __mode> {
2164824e7fdSDimitry Andric   typedef unsigned short result_type;
217cb14a3feSDimitry Andric   _LIBCPP_HIDE_FROM_ABI static result_type next(result_type __x) {
218*0fca6ea1SDimitry Andric     return static_cast<result_type>(__lce_ta<__a, __c, __m, unsigned(-1)>::next(__x));
2194824e7fdSDimitry Andric   }
2204824e7fdSDimitry Andric };
2214824e7fdSDimitry Andric 
2224824e7fdSDimitry Andric template <class _UIntType, _UIntType __a, _UIntType __c, _UIntType __m>
2234824e7fdSDimitry Andric class _LIBCPP_TEMPLATE_VIS linear_congruential_engine;
2244824e7fdSDimitry Andric 
225cb14a3feSDimitry Andric template <class _CharT, class _Traits, class _Up, _Up _Ap, _Up _Cp, _Up _Np>
226cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI basic_ostream<_CharT, _Traits>&
227cb14a3feSDimitry Andric operator<<(basic_ostream<_CharT, _Traits>& __os, const linear_congruential_engine<_Up, _Ap, _Cp, _Np>&);
2284824e7fdSDimitry Andric 
229cb14a3feSDimitry Andric template <class _CharT, class _Traits, class _Up, _Up _Ap, _Up _Cp, _Up _Np>
230bdd1243dSDimitry Andric _LIBCPP_HIDE_FROM_ABI basic_istream<_CharT, _Traits>&
231cb14a3feSDimitry Andric operator>>(basic_istream<_CharT, _Traits>& __is, linear_congruential_engine<_Up, _Ap, _Cp, _Np>& __x);
2324824e7fdSDimitry Andric 
2334824e7fdSDimitry Andric template <class _UIntType, _UIntType __a, _UIntType __c, _UIntType __m>
234cb14a3feSDimitry Andric class _LIBCPP_TEMPLATE_VIS linear_congruential_engine {
2354824e7fdSDimitry Andric public:
2364824e7fdSDimitry Andric   // types
2374824e7fdSDimitry Andric   typedef _UIntType result_type;
2384824e7fdSDimitry Andric 
2394824e7fdSDimitry Andric private:
2404824e7fdSDimitry Andric   result_type __x_;
2414824e7fdSDimitry Andric 
242*0fca6ea1SDimitry Andric   static _LIBCPP_CONSTEXPR const result_type _Mp = result_type(-1);
2434824e7fdSDimitry Andric 
2444824e7fdSDimitry Andric   static_assert(__m == 0 || __a < __m, "linear_congruential_engine invalid parameters");
2454824e7fdSDimitry Andric   static_assert(__m == 0 || __c < __m, "linear_congruential_engine invalid parameters");
2464824e7fdSDimitry Andric   static_assert(is_unsigned<_UIntType>::value, "_UIntType must be unsigned type");
247cb14a3feSDimitry Andric 
2484824e7fdSDimitry Andric public:
2494824e7fdSDimitry Andric   static _LIBCPP_CONSTEXPR const result_type _Min = __c == 0u ? 1u : 0u;
25081ad6265SDimitry Andric   static _LIBCPP_CONSTEXPR const result_type _Max = __m - _UIntType(1u);
2514824e7fdSDimitry Andric   static_assert(_Min < _Max, "linear_congruential_engine invalid parameters");
2524824e7fdSDimitry Andric 
2534824e7fdSDimitry Andric   // engine characteristics
2544824e7fdSDimitry Andric   static _LIBCPP_CONSTEXPR const result_type multiplier = __a;
2554824e7fdSDimitry Andric   static _LIBCPP_CONSTEXPR const result_type increment  = __c;
2564824e7fdSDimitry Andric   static _LIBCPP_CONSTEXPR const result_type modulus    = __m;
257cb14a3feSDimitry Andric   _LIBCPP_HIDE_FROM_ABI static _LIBCPP_CONSTEXPR result_type min() { return _Min; }
258cb14a3feSDimitry Andric   _LIBCPP_HIDE_FROM_ABI static _LIBCPP_CONSTEXPR result_type max() { return _Max; }
2594824e7fdSDimitry Andric   static _LIBCPP_CONSTEXPR const result_type default_seed = 1u;
2604824e7fdSDimitry Andric 
2614824e7fdSDimitry Andric   // constructors and seeding functions
2624824e7fdSDimitry Andric #ifndef _LIBCPP_CXX03_LANG
263cb14a3feSDimitry Andric   _LIBCPP_HIDE_FROM_ABI linear_congruential_engine() : linear_congruential_engine(default_seed) {}
264cb14a3feSDimitry Andric   _LIBCPP_HIDE_FROM_ABI explicit linear_congruential_engine(result_type __s) { seed(__s); }
2654824e7fdSDimitry Andric #else
266cb14a3feSDimitry Andric   _LIBCPP_HIDE_FROM_ABI explicit linear_congruential_engine(result_type __s = default_seed) { seed(__s); }
2674824e7fdSDimitry Andric #endif
2685f757f3fSDimitry Andric   template <class _Sseq, __enable_if_t<__is_seed_sequence<_Sseq, linear_congruential_engine>::value, int> = 0>
269cb14a3feSDimitry Andric   _LIBCPP_HIDE_FROM_ABI explicit linear_congruential_engine(_Sseq& __q) {
270cb14a3feSDimitry Andric     seed(__q);
271cb14a3feSDimitry Andric   }
272cb14a3feSDimitry Andric   _LIBCPP_HIDE_FROM_ABI void seed(result_type __s = default_seed) {
273cb14a3feSDimitry Andric     seed(integral_constant<bool, __m == 0>(), integral_constant<bool, __c == 0>(), __s);
274cb14a3feSDimitry Andric   }
2755f757f3fSDimitry Andric   template <class _Sseq, __enable_if_t<__is_seed_sequence<_Sseq, linear_congruential_engine>::value, int> = 0>
276cb14a3feSDimitry Andric   _LIBCPP_HIDE_FROM_ABI void seed(_Sseq& __q) {
277cb14a3feSDimitry Andric     __seed(
278cb14a3feSDimitry Andric         __q,
279cb14a3feSDimitry Andric         integral_constant<unsigned,
280cb14a3feSDimitry Andric                           1 + (__m == 0 ? (sizeof(result_type) * __CHAR_BIT__ - 1) / 32 : (__m > 0x100000000ull))>());
281cb14a3feSDimitry Andric   }
2824824e7fdSDimitry Andric 
2834824e7fdSDimitry Andric   // generating functions
284cb14a3feSDimitry Andric   _LIBCPP_HIDE_FROM_ABI result_type operator()() {
285cb14a3feSDimitry Andric     return __x_ = static_cast<result_type>(__lce_ta<__a, __c, __m, _Mp>::next(__x_));
286cb14a3feSDimitry Andric   }
287cb14a3feSDimitry Andric   _LIBCPP_HIDE_FROM_ABI void discard(unsigned long long __z) {
288cb14a3feSDimitry Andric     for (; __z; --__z)
289cb14a3feSDimitry Andric       operator()();
290cb14a3feSDimitry Andric   }
2914824e7fdSDimitry Andric 
292cb14a3feSDimitry Andric   friend _LIBCPP_HIDE_FROM_ABI bool
293cb14a3feSDimitry Andric   operator==(const linear_congruential_engine& __x, const linear_congruential_engine& __y) {
294cb14a3feSDimitry Andric     return __x.__x_ == __y.__x_;
295cb14a3feSDimitry Andric   }
296cb14a3feSDimitry Andric   friend _LIBCPP_HIDE_FROM_ABI bool
297cb14a3feSDimitry Andric   operator!=(const linear_congruential_engine& __x, const linear_congruential_engine& __y) {
298cb14a3feSDimitry Andric     return !(__x == __y);
299cb14a3feSDimitry Andric   }
3004824e7fdSDimitry Andric 
3014824e7fdSDimitry Andric private:
302cb14a3feSDimitry Andric   _LIBCPP_HIDE_FROM_ABI void seed(true_type, true_type, result_type __s) { __x_ = __s == 0 ? 1 : __s; }
303cb14a3feSDimitry Andric   _LIBCPP_HIDE_FROM_ABI void seed(true_type, false_type, result_type __s) { __x_ = __s; }
304cb14a3feSDimitry Andric   _LIBCPP_HIDE_FROM_ABI void seed(false_type, true_type, result_type __s) { __x_ = __s % __m == 0 ? 1 : __s % __m; }
305cb14a3feSDimitry Andric   _LIBCPP_HIDE_FROM_ABI void seed(false_type, false_type, result_type __s) { __x_ = __s % __m; }
3064824e7fdSDimitry Andric 
3074824e7fdSDimitry Andric   template <class _Sseq>
30806c3fb27SDimitry Andric   _LIBCPP_HIDE_FROM_ABI void __seed(_Sseq& __q, integral_constant<unsigned, 1>);
3094824e7fdSDimitry Andric   template <class _Sseq>
31006c3fb27SDimitry Andric   _LIBCPP_HIDE_FROM_ABI void __seed(_Sseq& __q, integral_constant<unsigned, 2>);
3114824e7fdSDimitry Andric 
312cb14a3feSDimitry Andric   template <class _CharT, class _Traits, class _Up, _Up _Ap, _Up _Cp, _Up _Np>
313cb14a3feSDimitry Andric   friend basic_ostream<_CharT, _Traits>&
314cb14a3feSDimitry Andric   operator<<(basic_ostream<_CharT, _Traits>& __os, const linear_congruential_engine<_Up, _Ap, _Cp, _Np>&);
3154824e7fdSDimitry Andric 
316cb14a3feSDimitry Andric   template <class _CharT, class _Traits, class _Up, _Up _Ap, _Up _Cp, _Up _Np>
317cb14a3feSDimitry Andric   friend basic_istream<_CharT, _Traits>&
318cb14a3feSDimitry Andric   operator>>(basic_istream<_CharT, _Traits>& __is, linear_congruential_engine<_Up, _Ap, _Cp, _Np>& __x);
3194824e7fdSDimitry Andric };
3204824e7fdSDimitry Andric 
3214824e7fdSDimitry Andric template <class _UIntType, _UIntType __a, _UIntType __c, _UIntType __m>
3224824e7fdSDimitry Andric _LIBCPP_CONSTEXPR const typename linear_congruential_engine<_UIntType, __a, __c, __m>::result_type
3234824e7fdSDimitry Andric     linear_congruential_engine<_UIntType, __a, __c, __m>::multiplier;
3244824e7fdSDimitry Andric 
3254824e7fdSDimitry Andric template <class _UIntType, _UIntType __a, _UIntType __c, _UIntType __m>
3264824e7fdSDimitry Andric _LIBCPP_CONSTEXPR const typename linear_congruential_engine<_UIntType, __a, __c, __m>::result_type
3274824e7fdSDimitry Andric     linear_congruential_engine<_UIntType, __a, __c, __m>::increment;
3284824e7fdSDimitry Andric 
3294824e7fdSDimitry Andric template <class _UIntType, _UIntType __a, _UIntType __c, _UIntType __m>
3304824e7fdSDimitry Andric _LIBCPP_CONSTEXPR const typename linear_congruential_engine<_UIntType, __a, __c, __m>::result_type
3314824e7fdSDimitry Andric     linear_congruential_engine<_UIntType, __a, __c, __m>::modulus;
3324824e7fdSDimitry Andric 
3334824e7fdSDimitry Andric template <class _UIntType, _UIntType __a, _UIntType __c, _UIntType __m>
3344824e7fdSDimitry Andric _LIBCPP_CONSTEXPR const typename linear_congruential_engine<_UIntType, __a, __c, __m>::result_type
3354824e7fdSDimitry Andric     linear_congruential_engine<_UIntType, __a, __c, __m>::default_seed;
3364824e7fdSDimitry Andric 
3374824e7fdSDimitry Andric template <class _UIntType, _UIntType __a, _UIntType __c, _UIntType __m>
3384824e7fdSDimitry Andric template <class _Sseq>
339cb14a3feSDimitry Andric void linear_congruential_engine<_UIntType, __a, __c, __m>::__seed(_Sseq& __q, integral_constant<unsigned, 1>) {
3404824e7fdSDimitry Andric   const unsigned __k = 1;
3414824e7fdSDimitry Andric   uint32_t __ar[__k + 3];
3424824e7fdSDimitry Andric   __q.generate(__ar, __ar + __k + 3);
3434824e7fdSDimitry Andric   result_type __s = static_cast<result_type>(__ar[3] % __m);
3444824e7fdSDimitry Andric   __x_            = __c == 0 && __s == 0 ? result_type(1) : __s;
3454824e7fdSDimitry Andric }
3464824e7fdSDimitry Andric 
3474824e7fdSDimitry Andric template <class _UIntType, _UIntType __a, _UIntType __c, _UIntType __m>
3484824e7fdSDimitry Andric template <class _Sseq>
349cb14a3feSDimitry Andric void linear_congruential_engine<_UIntType, __a, __c, __m>::__seed(_Sseq& __q, integral_constant<unsigned, 2>) {
3504824e7fdSDimitry Andric   const unsigned __k = 2;
3514824e7fdSDimitry Andric   uint32_t __ar[__k + 3];
3524824e7fdSDimitry Andric   __q.generate(__ar, __ar + __k + 3);
353cb14a3feSDimitry Andric   result_type __s = static_cast<result_type>((__ar[3] + ((uint64_t)__ar[4] << 32)) % __m);
3544824e7fdSDimitry Andric   __x_            = __c == 0 && __s == 0 ? result_type(1) : __s;
3554824e7fdSDimitry Andric }
3564824e7fdSDimitry Andric 
357cb14a3feSDimitry Andric template <class _CharT, class _Traits, class _UIntType, _UIntType __a, _UIntType __c, _UIntType __m>
358cb14a3feSDimitry Andric inline _LIBCPP_HIDE_FROM_ABI basic_ostream<_CharT, _Traits>&
359cb14a3feSDimitry Andric operator<<(basic_ostream<_CharT, _Traits>& __os, const linear_congruential_engine<_UIntType, __a, __c, __m>& __x) {
3604824e7fdSDimitry Andric   __save_flags<_CharT, _Traits> __lx(__os);
3614824e7fdSDimitry Andric   typedef basic_ostream<_CharT, _Traits> _Ostream;
3624824e7fdSDimitry Andric   __os.flags(_Ostream::dec | _Ostream::left);
3634824e7fdSDimitry Andric   __os.fill(__os.widen(' '));
3644824e7fdSDimitry Andric   return __os << __x.__x_;
3654824e7fdSDimitry Andric }
3664824e7fdSDimitry Andric 
367cb14a3feSDimitry Andric template <class _CharT, class _Traits, class _UIntType, _UIntType __a, _UIntType __c, _UIntType __m>
368bdd1243dSDimitry Andric _LIBCPP_HIDE_FROM_ABI basic_istream<_CharT, _Traits>&
369cb14a3feSDimitry Andric operator>>(basic_istream<_CharT, _Traits>& __is, linear_congruential_engine<_UIntType, __a, __c, __m>& __x) {
3704824e7fdSDimitry Andric   __save_flags<_CharT, _Traits> __lx(__is);
3714824e7fdSDimitry Andric   typedef basic_istream<_CharT, _Traits> _Istream;
3724824e7fdSDimitry Andric   __is.flags(_Istream::dec | _Istream::skipws);
3734824e7fdSDimitry Andric   _UIntType __t;
3744824e7fdSDimitry Andric   __is >> __t;
3754824e7fdSDimitry Andric   if (!__is.fail())
3764824e7fdSDimitry Andric     __x.__x_ = __t;
3774824e7fdSDimitry Andric   return __is;
3784824e7fdSDimitry Andric }
3794824e7fdSDimitry Andric 
380cb14a3feSDimitry Andric typedef linear_congruential_engine<uint_fast32_t, 16807, 0, 2147483647> minstd_rand0;
381cb14a3feSDimitry Andric typedef linear_congruential_engine<uint_fast32_t, 48271, 0, 2147483647> minstd_rand;
3824824e7fdSDimitry Andric 
3834824e7fdSDimitry Andric _LIBCPP_END_NAMESPACE_STD
3844824e7fdSDimitry Andric 
3854824e7fdSDimitry Andric _LIBCPP_POP_MACROS
3864824e7fdSDimitry Andric 
3874824e7fdSDimitry Andric #endif // _LIBCPP___RANDOM_LINEAR_CONGRUENTIAL_ENGINE_H
388