14824e7fdSDimitry Andric //===----------------------------------------------------------------------===// 24824e7fdSDimitry Andric // 34824e7fdSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 44824e7fdSDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 54824e7fdSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 64824e7fdSDimitry Andric // 74824e7fdSDimitry Andric //===----------------------------------------------------------------------===// 84824e7fdSDimitry Andric 94824e7fdSDimitry Andric #ifndef _LIBCPP___RANDOM_SEED_SEQ_H 104824e7fdSDimitry Andric #define _LIBCPP___RANDOM_SEED_SEQ_H 114824e7fdSDimitry Andric 124824e7fdSDimitry Andric #include <__algorithm/copy.h> 134824e7fdSDimitry Andric #include <__algorithm/fill.h> 144824e7fdSDimitry Andric #include <__algorithm/max.h> 154824e7fdSDimitry Andric #include <__config> 1606c3fb27SDimitry Andric #include <__iterator/iterator_traits.h> 1706c3fb27SDimitry Andric #include <cstdint> 184824e7fdSDimitry Andric #include <initializer_list> 194824e7fdSDimitry Andric #include <vector> 204824e7fdSDimitry Andric 214824e7fdSDimitry Andric #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) 224824e7fdSDimitry Andric # pragma GCC system_header 234824e7fdSDimitry Andric #endif 244824e7fdSDimitry Andric 254824e7fdSDimitry Andric _LIBCPP_PUSH_MACROS 264824e7fdSDimitry Andric #include <__undef_macros> 274824e7fdSDimitry Andric 284824e7fdSDimitry Andric _LIBCPP_BEGIN_NAMESPACE_STD 294824e7fdSDimitry Andric 304824e7fdSDimitry Andric class _LIBCPP_TEMPLATE_VIS seed_seq 314824e7fdSDimitry Andric { 324824e7fdSDimitry Andric public: 334824e7fdSDimitry Andric // types 344824e7fdSDimitry Andric typedef uint32_t result_type; 354824e7fdSDimitry Andric 364824e7fdSDimitry Andric // constructors 37*5f757f3fSDimitry Andric _LIBCPP_HIDE_FROM_ABI 384824e7fdSDimitry Andric seed_seq() _NOEXCEPT {} 394824e7fdSDimitry Andric #ifndef _LIBCPP_CXX03_LANG 4004eeddc0SDimitry Andric template<class _Tp, __enable_if_t<is_integral<_Tp>::value>* = nullptr> 41*5f757f3fSDimitry Andric _LIBCPP_HIDE_FROM_ABI 4204eeddc0SDimitry Andric seed_seq(initializer_list<_Tp> __il) { 4304eeddc0SDimitry Andric __init(__il.begin(), __il.end()); 4404eeddc0SDimitry Andric } 454824e7fdSDimitry Andric #endif // _LIBCPP_CXX03_LANG 464824e7fdSDimitry Andric 474824e7fdSDimitry Andric template<class _InputIterator> 48*5f757f3fSDimitry Andric _LIBCPP_HIDE_FROM_ABI 4904eeddc0SDimitry Andric seed_seq(_InputIterator __first, _InputIterator __last) { 5004eeddc0SDimitry Andric static_assert(is_integral<typename iterator_traits<_InputIterator>::value_type>::value, 5104eeddc0SDimitry Andric "Mandates: iterator_traits<InputIterator>::value_type is an integer type"); 5204eeddc0SDimitry Andric __init(__first, __last); 5304eeddc0SDimitry Andric } 544824e7fdSDimitry Andric 554824e7fdSDimitry Andric // generating functions 564824e7fdSDimitry Andric template<class _RandomAccessIterator> 5706c3fb27SDimitry Andric _LIBCPP_HIDE_FROM_ABI void generate(_RandomAccessIterator __first, _RandomAccessIterator __last); 584824e7fdSDimitry Andric 594824e7fdSDimitry Andric // property functions 60*5f757f3fSDimitry Andric _LIBCPP_HIDE_FROM_ABI 614824e7fdSDimitry Andric size_t size() const _NOEXCEPT {return __v_.size();} 624824e7fdSDimitry Andric template<class _OutputIterator> 63*5f757f3fSDimitry Andric _LIBCPP_HIDE_FROM_ABI 644824e7fdSDimitry Andric void param(_OutputIterator __dest) const 65*5f757f3fSDimitry Andric {std::copy(__v_.begin(), __v_.end(), __dest);} 664824e7fdSDimitry Andric 670eae32dcSDimitry Andric seed_seq(const seed_seq&) = delete; 680eae32dcSDimitry Andric void operator=(const seed_seq&) = delete; 694824e7fdSDimitry Andric 70*5f757f3fSDimitry Andric _LIBCPP_HIDE_FROM_ABI 714824e7fdSDimitry Andric static result_type _Tp(result_type __x) {return __x ^ (__x >> 27);} 7204eeddc0SDimitry Andric 7304eeddc0SDimitry Andric private: 7404eeddc0SDimitry Andric template<class _InputIterator> 7506c3fb27SDimitry Andric _LIBCPP_HIDE_FROM_ABI void __init(_InputIterator __first, _InputIterator __last); 7604eeddc0SDimitry Andric 7704eeddc0SDimitry Andric vector<result_type> __v_; 784824e7fdSDimitry Andric }; 794824e7fdSDimitry Andric 804824e7fdSDimitry Andric template<class _InputIterator> 814824e7fdSDimitry Andric void 8204eeddc0SDimitry Andric seed_seq::__init(_InputIterator __first, _InputIterator __last) 834824e7fdSDimitry Andric { 844824e7fdSDimitry Andric for (_InputIterator __s = __first; __s != __last; ++__s) 854824e7fdSDimitry Andric __v_.push_back(*__s & 0xFFFFFFFF); 864824e7fdSDimitry Andric } 874824e7fdSDimitry Andric 884824e7fdSDimitry Andric template<class _RandomAccessIterator> 894824e7fdSDimitry Andric void 904824e7fdSDimitry Andric seed_seq::generate(_RandomAccessIterator __first, _RandomAccessIterator __last) 914824e7fdSDimitry Andric { 924824e7fdSDimitry Andric if (__first != __last) 934824e7fdSDimitry Andric { 94*5f757f3fSDimitry Andric std::fill(__first, __last, 0x8b8b8b8b); 954824e7fdSDimitry Andric const size_t __n = static_cast<size_t>(__last - __first); 964824e7fdSDimitry Andric const size_t __s = __v_.size(); 974824e7fdSDimitry Andric const size_t __t = (__n >= 623) ? 11 984824e7fdSDimitry Andric : (__n >= 68) ? 7 994824e7fdSDimitry Andric : (__n >= 39) ? 5 1004824e7fdSDimitry Andric : (__n >= 7) ? 3 1014824e7fdSDimitry Andric : (__n - 1) / 2; 1024824e7fdSDimitry Andric const size_t __p = (__n - __t) / 2; 1034824e7fdSDimitry Andric const size_t __q = __p + __t; 104*5f757f3fSDimitry Andric const size_t __m = std::max(__s + 1, __n); 1054824e7fdSDimitry Andric // __k = 0; 1064824e7fdSDimitry Andric { 1074824e7fdSDimitry Andric result_type __r = 1664525 * _Tp(__first[0] ^ __first[__p] 1084824e7fdSDimitry Andric ^ __first[__n - 1]); 1094824e7fdSDimitry Andric __first[__p] += __r; 1104824e7fdSDimitry Andric __r += __s; 1114824e7fdSDimitry Andric __first[__q] += __r; 1124824e7fdSDimitry Andric __first[0] = __r; 1134824e7fdSDimitry Andric } 11481ad6265SDimitry Andric // Initialize indexing terms used with if statements as an optimization to 11581ad6265SDimitry Andric // avoid calculating modulo n on every loop iteration for each term. 11681ad6265SDimitry Andric size_t __kmodn = 0; // __k % __n 11781ad6265SDimitry Andric size_t __k1modn = __n - 1; // (__k - 1) % __n 11881ad6265SDimitry Andric size_t __kpmodn = __p % __n; // (__k + __p) % __n 11981ad6265SDimitry Andric size_t __kqmodn = __q % __n; // (__k + __q) % __n 12081ad6265SDimitry Andric 1214824e7fdSDimitry Andric for (size_t __k = 1; __k <= __s; ++__k) 1224824e7fdSDimitry Andric { 12381ad6265SDimitry Andric if (++__kmodn == __n) 12481ad6265SDimitry Andric __kmodn = 0; 12581ad6265SDimitry Andric if (++__k1modn == __n) 12681ad6265SDimitry Andric __k1modn = 0; 12781ad6265SDimitry Andric if (++__kpmodn == __n) 12881ad6265SDimitry Andric __kpmodn = 0; 12981ad6265SDimitry Andric if (++__kqmodn == __n) 13081ad6265SDimitry Andric __kqmodn = 0; 13181ad6265SDimitry Andric 13281ad6265SDimitry Andric result_type __r = 1664525 * _Tp(__first[__kmodn] ^ __first[__kpmodn] ^ __first[__k1modn]); 1334824e7fdSDimitry Andric __first[__kpmodn] += __r; 1344824e7fdSDimitry Andric __r += __kmodn + __v_[__k - 1]; 13581ad6265SDimitry Andric __first[__kqmodn] += __r; 1364824e7fdSDimitry Andric __first[__kmodn] = __r; 1374824e7fdSDimitry Andric } 1384824e7fdSDimitry Andric for (size_t __k = __s + 1; __k < __m; ++__k) 1394824e7fdSDimitry Andric { 14081ad6265SDimitry Andric if (++__kmodn == __n) 14181ad6265SDimitry Andric __kmodn = 0; 14281ad6265SDimitry Andric if (++__k1modn == __n) 14381ad6265SDimitry Andric __k1modn = 0; 14481ad6265SDimitry Andric if (++__kpmodn == __n) 14581ad6265SDimitry Andric __kpmodn = 0; 14681ad6265SDimitry Andric if (++__kqmodn == __n) 14781ad6265SDimitry Andric __kqmodn = 0; 14881ad6265SDimitry Andric 14981ad6265SDimitry Andric result_type __r = 1664525 * _Tp(__first[__kmodn] ^ __first[__kpmodn] ^ __first[__k1modn]); 1504824e7fdSDimitry Andric __first[__kpmodn] += __r; 1514824e7fdSDimitry Andric __r += __kmodn; 15281ad6265SDimitry Andric __first[__kqmodn] += __r; 1534824e7fdSDimitry Andric __first[__kmodn] = __r; 1544824e7fdSDimitry Andric } 1554824e7fdSDimitry Andric for (size_t __k = __m; __k < __m + __n; ++__k) 1564824e7fdSDimitry Andric { 15781ad6265SDimitry Andric if (++__kmodn == __n) 15881ad6265SDimitry Andric __kmodn = 0; 15981ad6265SDimitry Andric if (++__k1modn == __n) 16081ad6265SDimitry Andric __k1modn = 0; 16181ad6265SDimitry Andric if (++__kpmodn == __n) 16281ad6265SDimitry Andric __kpmodn = 0; 16381ad6265SDimitry Andric if (++__kqmodn == __n) 16481ad6265SDimitry Andric __kqmodn = 0; 16581ad6265SDimitry Andric 16681ad6265SDimitry Andric result_type __r = 1566083941 * _Tp(__first[__kmodn] + __first[__kpmodn] + __first[__k1modn]); 1674824e7fdSDimitry Andric __first[__kpmodn] ^= __r; 1684824e7fdSDimitry Andric __r -= __kmodn; 16981ad6265SDimitry Andric __first[__kqmodn] ^= __r; 1704824e7fdSDimitry Andric __first[__kmodn] = __r; 1714824e7fdSDimitry Andric } 1724824e7fdSDimitry Andric } 1734824e7fdSDimitry Andric } 1744824e7fdSDimitry Andric 1754824e7fdSDimitry Andric _LIBCPP_END_NAMESPACE_STD 1764824e7fdSDimitry Andric 1774824e7fdSDimitry Andric _LIBCPP_POP_MACROS 1784824e7fdSDimitry Andric 1794824e7fdSDimitry Andric #endif // _LIBCPP___RANDOM_SEED_SEQ_H 180