1 //===----------------------------------------------------------------------===//
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
7 //===----------------------------------------------------------------------===//
9 #ifndef _LIBCPP___RANDOM_SEED_SEQ_H
10 #define _LIBCPP___RANDOM_SEED_SEQ_H
12 #include <__algorithm/copy.h>
13 #include <__algorithm/fill.h>
14 #include <__algorithm/max.h>
16 #include <__iterator/iterator_traits.h>
17 #include <__type_traits/enable_if.h>
18 #include <__type_traits/is_integral.h>
19 #include <__type_traits/is_unsigned.h>
20 #include <__vector/vector.h>
22 #include <initializer_list>
24 #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
25 # pragma GCC system_header
29 #include <__undef_macros>
31 _LIBCPP_BEGIN_NAMESPACE_STD
33 class _LIBCPP_TEMPLATE_VIS seed_seq
{
36 typedef uint32_t result_type
;
39 _LIBCPP_HIDE_FROM_ABI
seed_seq() _NOEXCEPT
{}
40 #ifndef _LIBCPP_CXX03_LANG
41 template <class _Tp
, __enable_if_t
<is_integral
<_Tp
>::value
, int> = 0>
42 _LIBCPP_HIDE_FROM_ABI
seed_seq(initializer_list
<_Tp
> __il
) {
43 __init(__il
.begin(), __il
.end());
45 #endif // _LIBCPP_CXX03_LANG
47 template <class _InputIterator
>
48 _LIBCPP_HIDE_FROM_ABI
seed_seq(_InputIterator __first
, _InputIterator __last
) {
49 static_assert(is_integral
<typename iterator_traits
<_InputIterator
>::value_type
>::value
,
50 "Mandates: iterator_traits<InputIterator>::value_type is an integer type");
51 __init(__first
, __last
);
54 // generating functions
55 template <class _RandomAccessIterator
>
56 _LIBCPP_HIDE_FROM_ABI
void generate(_RandomAccessIterator __first
, _RandomAccessIterator __last
);
59 _LIBCPP_HIDE_FROM_ABI
size_t size() const _NOEXCEPT
{ return __v_
.size(); }
60 template <class _OutputIterator
>
61 _LIBCPP_HIDE_FROM_ABI
void param(_OutputIterator __dest
) const {
62 std::copy(__v_
.begin(), __v_
.end(), __dest
);
65 seed_seq(const seed_seq
&) = delete;
66 void operator=(const seed_seq
&) = delete;
68 _LIBCPP_HIDE_FROM_ABI
static result_type
_Tp(result_type __x
) { return __x
^ (__x
>> 27); }
71 template <class _InputIterator
>
72 _LIBCPP_HIDE_FROM_ABI
void __init(_InputIterator __first
, _InputIterator __last
);
74 vector
<result_type
> __v_
;
77 template <class _InputIterator
>
78 void seed_seq::__init(_InputIterator __first
, _InputIterator __last
) {
79 for (_InputIterator __s
= __first
; __s
!= __last
; ++__s
)
80 __v_
.push_back(*__s
& 0xFFFFFFFF);
83 template <class _RandomAccessIterator
>
84 void seed_seq::generate(_RandomAccessIterator __first
, _RandomAccessIterator __last
) {
85 using _ValueType
= typename iterator_traits
<_RandomAccessIterator
>::value_type
;
86 static_assert(is_unsigned
<_ValueType
>::value
&& sizeof(_ValueType
) >= sizeof(uint32_t),
87 "[rand.util.seedseq]/7 requires the value_type of the iterator to be an unsigned "
88 "integer capable of accommodating 32-bit quantities.");
90 if (__first
!= __last
) {
91 std::fill(__first
, __last
, 0x8b8b8b8b);
92 const size_t __n
= static_cast<size_t>(__last
- __first
);
93 const size_t __s
= __v_
.size();
94 const size_t __t
= (__n
>= 623) ? 11 : (__n
>= 68) ? 7 : (__n
>= 39) ? 5 : (__n
>= 7) ? 3 : (__n
- 1) / 2;
95 const size_t __p
= (__n
- __t
) / 2;
96 const size_t __q
= __p
+ __t
;
97 const size_t __m
= std::max(__s
+ 1, __n
);
100 result_type __r
= 1664525 * _Tp(__first
[0] ^ __first
[__p
] ^ __first
[__n
- 1]);
106 // Initialize indexing terms used with if statements as an optimization to
107 // avoid calculating modulo n on every loop iteration for each term.
108 size_t __kmodn
= 0; // __k % __n
109 size_t __k1modn
= __n
- 1; // (__k - 1) % __n
110 size_t __kpmodn
= __p
% __n
; // (__k + __p) % __n
111 size_t __kqmodn
= __q
% __n
; // (__k + __q) % __n
113 for (size_t __k
= 1; __k
<= __s
; ++__k
) {
114 if (++__kmodn
== __n
)
116 if (++__k1modn
== __n
)
118 if (++__kpmodn
== __n
)
120 if (++__kqmodn
== __n
)
123 result_type __r
= 1664525 * _Tp(__first
[__kmodn
] ^ __first
[__kpmodn
] ^ __first
[__k1modn
]);
124 __first
[__kpmodn
] += __r
;
125 __r
+= __kmodn
+ __v_
[__k
- 1];
126 __first
[__kqmodn
] += __r
;
127 __first
[__kmodn
] = __r
;
129 for (size_t __k
= __s
+ 1; __k
< __m
; ++__k
) {
130 if (++__kmodn
== __n
)
132 if (++__k1modn
== __n
)
134 if (++__kpmodn
== __n
)
136 if (++__kqmodn
== __n
)
139 result_type __r
= 1664525 * _Tp(__first
[__kmodn
] ^ __first
[__kpmodn
] ^ __first
[__k1modn
]);
140 __first
[__kpmodn
] += __r
;
142 __first
[__kqmodn
] += __r
;
143 __first
[__kmodn
] = __r
;
145 for (size_t __k
= __m
; __k
< __m
+ __n
; ++__k
) {
146 if (++__kmodn
== __n
)
148 if (++__k1modn
== __n
)
150 if (++__kpmodn
== __n
)
152 if (++__kqmodn
== __n
)
155 result_type __r
= 1566083941 * _Tp(__first
[__kmodn
] + __first
[__kpmodn
] + __first
[__k1modn
]);
156 __first
[__kpmodn
] ^= __r
;
158 __first
[__kqmodn
] ^= __r
;
159 __first
[__kmodn
] = __r
;
164 _LIBCPP_END_NAMESPACE_STD
168 #endif // _LIBCPP___RANDOM_SEED_SEQ_H