1344cef66SArthur O'Dwyer //===----------------------------------------------------------------------===// 2344cef66SArthur O'Dwyer // 3344cef66SArthur O'Dwyer // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4344cef66SArthur O'Dwyer // See https://llvm.org/LICENSE.txt for license information. 5344cef66SArthur O'Dwyer // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6344cef66SArthur O'Dwyer // 7344cef66SArthur O'Dwyer //===----------------------------------------------------------------------===// 8344cef66SArthur O'Dwyer 9344cef66SArthur O'Dwyer #ifndef _LIBCPP___RANDOM_SEED_SEQ_H 10344cef66SArthur O'Dwyer #define _LIBCPP___RANDOM_SEED_SEQ_H 11344cef66SArthur O'Dwyer 12344cef66SArthur O'Dwyer #include <__algorithm/copy.h> 13344cef66SArthur O'Dwyer #include <__algorithm/fill.h> 14344cef66SArthur O'Dwyer #include <__algorithm/max.h> 15344cef66SArthur O'Dwyer #include <__config> 16d6cd4257SMark de Wever #include <__iterator/iterator_traits.h> 17d6832a61SLouis Dionne #include <__type_traits/enable_if.h> 18d6832a61SLouis Dionne #include <__type_traits/is_integral.h> 19ca48d4dfSLouis Dionne #include <__type_traits/is_unsigned.h> 20*2e43a304SNikolas Klauser #include <__vector/vector.h> 210a4aa8a1SNikolas Klauser #include <cstdint> 22344cef66SArthur O'Dwyer #include <initializer_list> 23344cef66SArthur O'Dwyer 24344cef66SArthur O'Dwyer #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) 25344cef66SArthur O'Dwyer # pragma GCC system_header 26344cef66SArthur O'Dwyer #endif 27344cef66SArthur O'Dwyer 28344cef66SArthur O'Dwyer _LIBCPP_PUSH_MACROS 29344cef66SArthur O'Dwyer #include <__undef_macros> 30344cef66SArthur O'Dwyer 31344cef66SArthur O'Dwyer _LIBCPP_BEGIN_NAMESPACE_STD 32344cef66SArthur O'Dwyer 339783f28cSLouis Dionne class _LIBCPP_TEMPLATE_VIS seed_seq { 34344cef66SArthur O'Dwyer public: 35344cef66SArthur O'Dwyer // types 36344cef66SArthur O'Dwyer typedef uint32_t result_type; 37344cef66SArthur O'Dwyer 38344cef66SArthur O'Dwyer // constructors 399783f28cSLouis Dionne _LIBCPP_HIDE_FROM_ABI seed_seq() _NOEXCEPT {} 40344cef66SArthur O'Dwyer #ifndef _LIBCPP_CXX03_LANG 4176a24727SNikolas Klauser template <class _Tp, __enable_if_t<is_integral<_Tp>::value, int> = 0> 429783f28cSLouis Dionne _LIBCPP_HIDE_FROM_ABI seed_seq(initializer_list<_Tp> __il) { 438b29b84cSArthur O'Dwyer __init(__il.begin(), __il.end()); 448b29b84cSArthur O'Dwyer } 45344cef66SArthur O'Dwyer #endif // _LIBCPP_CXX03_LANG 46344cef66SArthur O'Dwyer 47344cef66SArthur O'Dwyer template <class _InputIterator> 489783f28cSLouis Dionne _LIBCPP_HIDE_FROM_ABI seed_seq(_InputIterator __first, _InputIterator __last) { 498b29b84cSArthur O'Dwyer static_assert(is_integral<typename iterator_traits<_InputIterator>::value_type>::value, 508b29b84cSArthur O'Dwyer "Mandates: iterator_traits<InputIterator>::value_type is an integer type"); 518b29b84cSArthur O'Dwyer __init(__first, __last); 528b29b84cSArthur O'Dwyer } 53344cef66SArthur O'Dwyer 54344cef66SArthur O'Dwyer // generating functions 55344cef66SArthur O'Dwyer template <class _RandomAccessIterator> 5683ce1397SNikolas Klauser _LIBCPP_HIDE_FROM_ABI void generate(_RandomAccessIterator __first, _RandomAccessIterator __last); 57344cef66SArthur O'Dwyer 58344cef66SArthur O'Dwyer // property functions 599783f28cSLouis Dionne _LIBCPP_HIDE_FROM_ABI size_t size() const _NOEXCEPT { return __v_.size(); } 60344cef66SArthur O'Dwyer template <class _OutputIterator> 619783f28cSLouis Dionne _LIBCPP_HIDE_FROM_ABI void param(_OutputIterator __dest) const { 629783f28cSLouis Dionne std::copy(__v_.begin(), __v_.end(), __dest); 639783f28cSLouis Dionne } 64344cef66SArthur O'Dwyer 65feb80aa9SNikolas Klauser seed_seq(const seed_seq&) = delete; 66feb80aa9SNikolas Klauser void operator=(const seed_seq&) = delete; 67344cef66SArthur O'Dwyer 689783f28cSLouis Dionne _LIBCPP_HIDE_FROM_ABI static result_type _Tp(result_type __x) { return __x ^ (__x >> 27); } 698b29b84cSArthur O'Dwyer 708b29b84cSArthur O'Dwyer private: 718b29b84cSArthur O'Dwyer template <class _InputIterator> 7283ce1397SNikolas Klauser _LIBCPP_HIDE_FROM_ABI void __init(_InputIterator __first, _InputIterator __last); 738b29b84cSArthur O'Dwyer 748b29b84cSArthur O'Dwyer vector<result_type> __v_; 75344cef66SArthur O'Dwyer }; 76344cef66SArthur O'Dwyer 77344cef66SArthur O'Dwyer template <class _InputIterator> 789783f28cSLouis Dionne void seed_seq::__init(_InputIterator __first, _InputIterator __last) { 79344cef66SArthur O'Dwyer for (_InputIterator __s = __first; __s != __last; ++__s) 80344cef66SArthur O'Dwyer __v_.push_back(*__s & 0xFFFFFFFF); 81344cef66SArthur O'Dwyer } 82344cef66SArthur O'Dwyer 83344cef66SArthur O'Dwyer template <class _RandomAccessIterator> 849783f28cSLouis Dionne void seed_seq::generate(_RandomAccessIterator __first, _RandomAccessIterator __last) { 85ca48d4dfSLouis Dionne using _ValueType = typename iterator_traits<_RandomAccessIterator>::value_type; 86ca48d4dfSLouis Dionne static_assert(is_unsigned<_ValueType>::value && sizeof(_ValueType) >= sizeof(uint32_t), 87ca48d4dfSLouis Dionne "[rand.util.seedseq]/7 requires the value_type of the iterator to be an unsigned " 88ca48d4dfSLouis Dionne "integer capable of accommodating 32-bit quantities."); 89ca48d4dfSLouis Dionne 909783f28cSLouis Dionne if (__first != __last) { 9177a00c0dSLouis Dionne std::fill(__first, __last, 0x8b8b8b8b); 92344cef66SArthur O'Dwyer const size_t __n = static_cast<size_t>(__last - __first); 93344cef66SArthur O'Dwyer const size_t __s = __v_.size(); 949783f28cSLouis Dionne const size_t __t = (__n >= 623) ? 11 : (__n >= 68) ? 7 : (__n >= 39) ? 5 : (__n >= 7) ? 3 : (__n - 1) / 2; 95344cef66SArthur O'Dwyer const size_t __p = (__n - __t) / 2; 96344cef66SArthur O'Dwyer const size_t __q = __p + __t; 9777a00c0dSLouis Dionne const size_t __m = std::max(__s + 1, __n); 98344cef66SArthur O'Dwyer // __k = 0; 99344cef66SArthur O'Dwyer { 1009783f28cSLouis Dionne result_type __r = 1664525 * _Tp(__first[0] ^ __first[__p] ^ __first[__n - 1]); 101344cef66SArthur O'Dwyer __first[__p] += __r; 102344cef66SArthur O'Dwyer __r += __s; 103344cef66SArthur O'Dwyer __first[__q] += __r; 104344cef66SArthur O'Dwyer __first[0] = __r; 105344cef66SArthur O'Dwyer } 106b0788045SLaramie Leavitt // Initialize indexing terms used with if statements as an optimization to 107b0788045SLaramie Leavitt // avoid calculating modulo n on every loop iteration for each term. 108b0788045SLaramie Leavitt size_t __kmodn = 0; // __k % __n 109b0788045SLaramie Leavitt size_t __k1modn = __n - 1; // (__k - 1) % __n 110b0788045SLaramie Leavitt size_t __kpmodn = __p % __n; // (__k + __p) % __n 111b0788045SLaramie Leavitt size_t __kqmodn = __q % __n; // (__k + __q) % __n 112b0788045SLaramie Leavitt 1139783f28cSLouis Dionne for (size_t __k = 1; __k <= __s; ++__k) { 114b0788045SLaramie Leavitt if (++__kmodn == __n) 115b0788045SLaramie Leavitt __kmodn = 0; 116b0788045SLaramie Leavitt if (++__k1modn == __n) 117b0788045SLaramie Leavitt __k1modn = 0; 118b0788045SLaramie Leavitt if (++__kpmodn == __n) 119b0788045SLaramie Leavitt __kpmodn = 0; 120b0788045SLaramie Leavitt if (++__kqmodn == __n) 121b0788045SLaramie Leavitt __kqmodn = 0; 122b0788045SLaramie Leavitt 123b0788045SLaramie Leavitt result_type __r = 1664525 * _Tp(__first[__kmodn] ^ __first[__kpmodn] ^ __first[__k1modn]); 124344cef66SArthur O'Dwyer __first[__kpmodn] += __r; 125344cef66SArthur O'Dwyer __r += __kmodn + __v_[__k - 1]; 126b0788045SLaramie Leavitt __first[__kqmodn] += __r; 127344cef66SArthur O'Dwyer __first[__kmodn] = __r; 128344cef66SArthur O'Dwyer } 1299783f28cSLouis Dionne for (size_t __k = __s + 1; __k < __m; ++__k) { 130b0788045SLaramie Leavitt if (++__kmodn == __n) 131b0788045SLaramie Leavitt __kmodn = 0; 132b0788045SLaramie Leavitt if (++__k1modn == __n) 133b0788045SLaramie Leavitt __k1modn = 0; 134b0788045SLaramie Leavitt if (++__kpmodn == __n) 135b0788045SLaramie Leavitt __kpmodn = 0; 136b0788045SLaramie Leavitt if (++__kqmodn == __n) 137b0788045SLaramie Leavitt __kqmodn = 0; 138b0788045SLaramie Leavitt 139b0788045SLaramie Leavitt result_type __r = 1664525 * _Tp(__first[__kmodn] ^ __first[__kpmodn] ^ __first[__k1modn]); 140344cef66SArthur O'Dwyer __first[__kpmodn] += __r; 141344cef66SArthur O'Dwyer __r += __kmodn; 142b0788045SLaramie Leavitt __first[__kqmodn] += __r; 143344cef66SArthur O'Dwyer __first[__kmodn] = __r; 144344cef66SArthur O'Dwyer } 1459783f28cSLouis Dionne for (size_t __k = __m; __k < __m + __n; ++__k) { 146b0788045SLaramie Leavitt if (++__kmodn == __n) 147b0788045SLaramie Leavitt __kmodn = 0; 148b0788045SLaramie Leavitt if (++__k1modn == __n) 149b0788045SLaramie Leavitt __k1modn = 0; 150b0788045SLaramie Leavitt if (++__kpmodn == __n) 151b0788045SLaramie Leavitt __kpmodn = 0; 152b0788045SLaramie Leavitt if (++__kqmodn == __n) 153b0788045SLaramie Leavitt __kqmodn = 0; 154b0788045SLaramie Leavitt 155b0788045SLaramie Leavitt result_type __r = 1566083941 * _Tp(__first[__kmodn] + __first[__kpmodn] + __first[__k1modn]); 156344cef66SArthur O'Dwyer __first[__kpmodn] ^= __r; 157344cef66SArthur O'Dwyer __r -= __kmodn; 158b0788045SLaramie Leavitt __first[__kqmodn] ^= __r; 159344cef66SArthur O'Dwyer __first[__kmodn] = __r; 160344cef66SArthur O'Dwyer } 161344cef66SArthur O'Dwyer } 162344cef66SArthur O'Dwyer } 163344cef66SArthur O'Dwyer 164344cef66SArthur O'Dwyer _LIBCPP_END_NAMESPACE_STD 165344cef66SArthur O'Dwyer 166344cef66SArthur O'Dwyer _LIBCPP_POP_MACROS 167344cef66SArthur O'Dwyer 168344cef66SArthur O'Dwyer #endif // _LIBCPP___RANDOM_SEED_SEQ_H 169