xref: /freebsd-src/contrib/llvm-project/libcxx/include/__random/seed_seq.h (revision 4824e7fd18a1223177218d4aec1b3c6c5c4a444e)
1*4824e7fdSDimitry Andric //===----------------------------------------------------------------------===//
2*4824e7fdSDimitry Andric //
3*4824e7fdSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4*4824e7fdSDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
5*4824e7fdSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6*4824e7fdSDimitry Andric //
7*4824e7fdSDimitry Andric //===----------------------------------------------------------------------===//
8*4824e7fdSDimitry Andric 
9*4824e7fdSDimitry Andric #ifndef _LIBCPP___RANDOM_SEED_SEQ_H
10*4824e7fdSDimitry Andric #define _LIBCPP___RANDOM_SEED_SEQ_H
11*4824e7fdSDimitry Andric 
12*4824e7fdSDimitry Andric #include <__algorithm/copy.h>
13*4824e7fdSDimitry Andric #include <__algorithm/fill.h>
14*4824e7fdSDimitry Andric #include <__algorithm/max.h>
15*4824e7fdSDimitry Andric #include <__config>
16*4824e7fdSDimitry Andric #include <initializer_list>
17*4824e7fdSDimitry Andric #include <vector>
18*4824e7fdSDimitry Andric 
19*4824e7fdSDimitry Andric #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
20*4824e7fdSDimitry Andric #pragma GCC system_header
21*4824e7fdSDimitry Andric #endif
22*4824e7fdSDimitry Andric 
23*4824e7fdSDimitry Andric _LIBCPP_PUSH_MACROS
24*4824e7fdSDimitry Andric #include <__undef_macros>
25*4824e7fdSDimitry Andric 
26*4824e7fdSDimitry Andric _LIBCPP_BEGIN_NAMESPACE_STD
27*4824e7fdSDimitry Andric 
28*4824e7fdSDimitry Andric class _LIBCPP_TEMPLATE_VIS seed_seq
29*4824e7fdSDimitry Andric {
30*4824e7fdSDimitry Andric public:
31*4824e7fdSDimitry Andric     // types
32*4824e7fdSDimitry Andric     typedef uint32_t result_type;
33*4824e7fdSDimitry Andric 
34*4824e7fdSDimitry Andric private:
35*4824e7fdSDimitry Andric     vector<result_type> __v_;
36*4824e7fdSDimitry Andric 
37*4824e7fdSDimitry Andric     template<class _InputIterator>
38*4824e7fdSDimitry Andric         void init(_InputIterator __first, _InputIterator __last);
39*4824e7fdSDimitry Andric public:
40*4824e7fdSDimitry Andric     // constructors
41*4824e7fdSDimitry Andric     _LIBCPP_INLINE_VISIBILITY
42*4824e7fdSDimitry Andric     seed_seq() _NOEXCEPT {}
43*4824e7fdSDimitry Andric #ifndef _LIBCPP_CXX03_LANG
44*4824e7fdSDimitry Andric     template<class _Tp>
45*4824e7fdSDimitry Andric         _LIBCPP_INLINE_VISIBILITY
46*4824e7fdSDimitry Andric         seed_seq(initializer_list<_Tp> __il) {init(__il.begin(), __il.end());}
47*4824e7fdSDimitry Andric #endif // _LIBCPP_CXX03_LANG
48*4824e7fdSDimitry Andric 
49*4824e7fdSDimitry Andric     template<class _InputIterator>
50*4824e7fdSDimitry Andric         _LIBCPP_INLINE_VISIBILITY
51*4824e7fdSDimitry Andric         seed_seq(_InputIterator __first, _InputIterator __last)
52*4824e7fdSDimitry Andric              {init(__first, __last);}
53*4824e7fdSDimitry Andric 
54*4824e7fdSDimitry Andric     // generating functions
55*4824e7fdSDimitry Andric     template<class _RandomAccessIterator>
56*4824e7fdSDimitry Andric         void generate(_RandomAccessIterator __first, _RandomAccessIterator __last);
57*4824e7fdSDimitry Andric 
58*4824e7fdSDimitry Andric     // property functions
59*4824e7fdSDimitry Andric     _LIBCPP_INLINE_VISIBILITY
60*4824e7fdSDimitry Andric     size_t size() const _NOEXCEPT {return __v_.size();}
61*4824e7fdSDimitry Andric     template<class _OutputIterator>
62*4824e7fdSDimitry Andric         _LIBCPP_INLINE_VISIBILITY
63*4824e7fdSDimitry Andric         void param(_OutputIterator __dest) const
64*4824e7fdSDimitry Andric             {_VSTD::copy(__v_.begin(), __v_.end(), __dest);}
65*4824e7fdSDimitry Andric 
66*4824e7fdSDimitry Andric private:
67*4824e7fdSDimitry Andric     // no copy functions
68*4824e7fdSDimitry Andric     seed_seq(const seed_seq&); // = delete;
69*4824e7fdSDimitry Andric     void operator=(const seed_seq&); // = delete;
70*4824e7fdSDimitry Andric 
71*4824e7fdSDimitry Andric     _LIBCPP_INLINE_VISIBILITY
72*4824e7fdSDimitry Andric     static result_type _Tp(result_type __x) {return __x ^ (__x >> 27);}
73*4824e7fdSDimitry Andric };
74*4824e7fdSDimitry Andric 
75*4824e7fdSDimitry Andric template<class _InputIterator>
76*4824e7fdSDimitry Andric void
77*4824e7fdSDimitry Andric seed_seq::init(_InputIterator __first, _InputIterator __last)
78*4824e7fdSDimitry Andric {
79*4824e7fdSDimitry Andric     for (_InputIterator __s = __first; __s != __last; ++__s)
80*4824e7fdSDimitry Andric         __v_.push_back(*__s & 0xFFFFFFFF);
81*4824e7fdSDimitry Andric }
82*4824e7fdSDimitry Andric 
83*4824e7fdSDimitry Andric template<class _RandomAccessIterator>
84*4824e7fdSDimitry Andric void
85*4824e7fdSDimitry Andric seed_seq::generate(_RandomAccessIterator __first, _RandomAccessIterator __last)
86*4824e7fdSDimitry Andric {
87*4824e7fdSDimitry Andric     if (__first != __last)
88*4824e7fdSDimitry Andric     {
89*4824e7fdSDimitry Andric         _VSTD::fill(__first, __last, 0x8b8b8b8b);
90*4824e7fdSDimitry Andric         const size_t __n = static_cast<size_t>(__last - __first);
91*4824e7fdSDimitry Andric         const size_t __s = __v_.size();
92*4824e7fdSDimitry Andric         const size_t __t = (__n >= 623) ? 11
93*4824e7fdSDimitry Andric                          : (__n >= 68) ? 7
94*4824e7fdSDimitry Andric                          : (__n >= 39) ? 5
95*4824e7fdSDimitry Andric                          : (__n >= 7)  ? 3
96*4824e7fdSDimitry Andric                          : (__n - 1) / 2;
97*4824e7fdSDimitry Andric         const size_t __p = (__n - __t) / 2;
98*4824e7fdSDimitry Andric         const size_t __q = __p + __t;
99*4824e7fdSDimitry Andric         const size_t __m = _VSTD::max(__s + 1, __n);
100*4824e7fdSDimitry Andric         // __k = 0;
101*4824e7fdSDimitry Andric         {
102*4824e7fdSDimitry Andric             result_type __r = 1664525 * _Tp(__first[0] ^ __first[__p]
103*4824e7fdSDimitry Andric                                                       ^  __first[__n - 1]);
104*4824e7fdSDimitry Andric             __first[__p] += __r;
105*4824e7fdSDimitry Andric             __r += __s;
106*4824e7fdSDimitry Andric             __first[__q] += __r;
107*4824e7fdSDimitry Andric             __first[0] = __r;
108*4824e7fdSDimitry Andric         }
109*4824e7fdSDimitry Andric         for (size_t __k = 1; __k <= __s; ++__k)
110*4824e7fdSDimitry Andric         {
111*4824e7fdSDimitry Andric             const size_t __kmodn = __k % __n;
112*4824e7fdSDimitry Andric             const size_t __kpmodn = (__k + __p) % __n;
113*4824e7fdSDimitry Andric             result_type __r = 1664525 * _Tp(__first[__kmodn] ^ __first[__kpmodn]
114*4824e7fdSDimitry Andric                                            ^ __first[(__k - 1) % __n]);
115*4824e7fdSDimitry Andric             __first[__kpmodn] += __r;
116*4824e7fdSDimitry Andric             __r +=  __kmodn + __v_[__k-1];
117*4824e7fdSDimitry Andric             __first[(__k + __q) % __n] += __r;
118*4824e7fdSDimitry Andric             __first[__kmodn] = __r;
119*4824e7fdSDimitry Andric         }
120*4824e7fdSDimitry Andric         for (size_t __k = __s + 1; __k < __m; ++__k)
121*4824e7fdSDimitry Andric         {
122*4824e7fdSDimitry Andric             const size_t __kmodn = __k % __n;
123*4824e7fdSDimitry Andric             const size_t __kpmodn = (__k + __p) % __n;
124*4824e7fdSDimitry Andric             result_type __r = 1664525 * _Tp(__first[__kmodn] ^ __first[__kpmodn]
125*4824e7fdSDimitry Andric                                            ^ __first[(__k - 1) % __n]);
126*4824e7fdSDimitry Andric             __first[__kpmodn] += __r;
127*4824e7fdSDimitry Andric             __r +=  __kmodn;
128*4824e7fdSDimitry Andric             __first[(__k + __q) % __n] += __r;
129*4824e7fdSDimitry Andric             __first[__kmodn] = __r;
130*4824e7fdSDimitry Andric         }
131*4824e7fdSDimitry Andric         for (size_t __k = __m; __k < __m + __n; ++__k)
132*4824e7fdSDimitry Andric         {
133*4824e7fdSDimitry Andric             const size_t __kmodn = __k % __n;
134*4824e7fdSDimitry Andric             const size_t __kpmodn = (__k + __p) % __n;
135*4824e7fdSDimitry Andric             result_type __r = 1566083941 * _Tp(__first[__kmodn] +
136*4824e7fdSDimitry Andric                                               __first[__kpmodn] +
137*4824e7fdSDimitry Andric                                               __first[(__k - 1) % __n]);
138*4824e7fdSDimitry Andric             __first[__kpmodn] ^= __r;
139*4824e7fdSDimitry Andric             __r -= __kmodn;
140*4824e7fdSDimitry Andric             __first[(__k + __q) % __n] ^= __r;
141*4824e7fdSDimitry Andric             __first[__kmodn] = __r;
142*4824e7fdSDimitry Andric         }
143*4824e7fdSDimitry Andric     }
144*4824e7fdSDimitry Andric }
145*4824e7fdSDimitry Andric 
146*4824e7fdSDimitry Andric _LIBCPP_END_NAMESPACE_STD
147*4824e7fdSDimitry Andric 
148*4824e7fdSDimitry Andric _LIBCPP_POP_MACROS
149*4824e7fdSDimitry Andric 
150*4824e7fdSDimitry Andric #endif // _LIBCPP___RANDOM_SEED_SEQ_H
151