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