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___CXX03___RANDOM_SEED_SEQ_H
10 #define _LIBCPP___CXX03___RANDOM_SEED_SEQ_H
12 #include <__cxx03/__algorithm/copy.h>
13 #include <__cxx03/__algorithm/fill.h>
14 #include <__cxx03/__algorithm/max.h>
15 #include <__cxx03/__config>
16 #include <__cxx03/__iterator/iterator_traits.h>
17 #include <__cxx03/__type_traits/is_unsigned.h>
18 #include <__cxx03/cstdint>
19 #include <__cxx03/initializer_list>
20 #include <__cxx03/vector>
22 #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
23 # pragma GCC system_header
27 #include <__cxx03/__undef_macros>
29 _LIBCPP_BEGIN_NAMESPACE_STD
31 class _LIBCPP_TEMPLATE_VIS seed_seq
{
34 typedef uint32_t result_type
;
37 _LIBCPP_HIDE_FROM_ABI
seed_seq() _NOEXCEPT
{}
38 #ifndef _LIBCPP_CXX03_LANG
39 template <class _Tp
, __enable_if_t
<is_integral
<_Tp
>::value
, int> = 0>
40 _LIBCPP_HIDE_FROM_ABI
seed_seq(initializer_list
<_Tp
> __il
) {
41 __init(__il
.begin(), __il
.end());
43 #endif // _LIBCPP_CXX03_LANG
45 template <class _InputIterator
>
46 _LIBCPP_HIDE_FROM_ABI
seed_seq(_InputIterator __first
, _InputIterator __last
) {
47 static_assert(is_integral
<typename iterator_traits
<_InputIterator
>::value_type
>::value
,
48 "Mandates: iterator_traits<InputIterator>::value_type is an integer type");
49 __init(__first
, __last
);
52 // generating functions
53 template <class _RandomAccessIterator
>
54 _LIBCPP_HIDE_FROM_ABI
void generate(_RandomAccessIterator __first
, _RandomAccessIterator __last
);
57 _LIBCPP_HIDE_FROM_ABI
size_t size() const _NOEXCEPT
{ return __v_
.size(); }
58 template <class _OutputIterator
>
59 _LIBCPP_HIDE_FROM_ABI
void param(_OutputIterator __dest
) const {
60 std::copy(__v_
.begin(), __v_
.end(), __dest
);
63 seed_seq(const seed_seq
&) = delete;
64 void operator=(const seed_seq
&) = delete;
66 _LIBCPP_HIDE_FROM_ABI
static result_type
_Tp(result_type __x
) { return __x
^ (__x
>> 27); }
69 template <class _InputIterator
>
70 _LIBCPP_HIDE_FROM_ABI
void __init(_InputIterator __first
, _InputIterator __last
);
72 vector
<result_type
> __v_
;
75 template <class _InputIterator
>
76 void seed_seq::__init(_InputIterator __first
, _InputIterator __last
) {
77 for (_InputIterator __s
= __first
; __s
!= __last
; ++__s
)
78 __v_
.push_back(*__s
& 0xFFFFFFFF);
81 template <class _RandomAccessIterator
>
82 void seed_seq::generate(_RandomAccessIterator __first
, _RandomAccessIterator __last
) {
83 using _ValueType
= typename iterator_traits
<_RandomAccessIterator
>::value_type
;
84 static_assert(is_unsigned
<_ValueType
>::value
&& sizeof(_ValueType
) >= sizeof(uint32_t),
85 "[rand.util.seedseq]/7 requires the value_type of the iterator to be an unsigned "
86 "integer capable of accommodating 32-bit quantities.");
88 if (__first
!= __last
) {
89 std::fill(__first
, __last
, 0x8b8b8b8b);
90 const size_t __n
= static_cast<size_t>(__last
- __first
);
91 const size_t __s
= __v_
.size();
92 const size_t __t
= (__n
>= 623) ? 11 : (__n
>= 68) ? 7 : (__n
>= 39) ? 5 : (__n
>= 7) ? 3 : (__n
- 1) / 2;
93 const size_t __p
= (__n
- __t
) / 2;
94 const size_t __q
= __p
+ __t
;
95 const size_t __m
= std::max(__s
+ 1, __n
);
98 result_type __r
= 1664525 * _Tp(__first
[0] ^ __first
[__p
] ^ __first
[__n
- 1]);
104 // Initialize indexing terms used with if statements as an optimization to
105 // avoid calculating modulo n on every loop iteration for each term.
106 size_t __kmodn
= 0; // __k % __n
107 size_t __k1modn
= __n
- 1; // (__k - 1) % __n
108 size_t __kpmodn
= __p
% __n
; // (__k + __p) % __n
109 size_t __kqmodn
= __q
% __n
; // (__k + __q) % __n
111 for (size_t __k
= 1; __k
<= __s
; ++__k
) {
112 if (++__kmodn
== __n
)
114 if (++__k1modn
== __n
)
116 if (++__kpmodn
== __n
)
118 if (++__kqmodn
== __n
)
121 result_type __r
= 1664525 * _Tp(__first
[__kmodn
] ^ __first
[__kpmodn
] ^ __first
[__k1modn
]);
122 __first
[__kpmodn
] += __r
;
123 __r
+= __kmodn
+ __v_
[__k
- 1];
124 __first
[__kqmodn
] += __r
;
125 __first
[__kmodn
] = __r
;
127 for (size_t __k
= __s
+ 1; __k
< __m
; ++__k
) {
128 if (++__kmodn
== __n
)
130 if (++__k1modn
== __n
)
132 if (++__kpmodn
== __n
)
134 if (++__kqmodn
== __n
)
137 result_type __r
= 1664525 * _Tp(__first
[__kmodn
] ^ __first
[__kpmodn
] ^ __first
[__k1modn
]);
138 __first
[__kpmodn
] += __r
;
140 __first
[__kqmodn
] += __r
;
141 __first
[__kmodn
] = __r
;
143 for (size_t __k
= __m
; __k
< __m
+ __n
; ++__k
) {
144 if (++__kmodn
== __n
)
146 if (++__k1modn
== __n
)
148 if (++__kpmodn
== __n
)
150 if (++__kqmodn
== __n
)
153 result_type __r
= 1566083941 * _Tp(__first
[__kmodn
] + __first
[__kpmodn
] + __first
[__k1modn
]);
154 __first
[__kpmodn
] ^= __r
;
156 __first
[__kqmodn
] ^= __r
;
157 __first
[__kmodn
] = __r
;
162 _LIBCPP_END_NAMESPACE_STD
166 #endif // _LIBCPP___CXX03___RANDOM_SEED_SEQ_H