1*4bdff4beSrobert //===----------------------------------------------------------------------===// 2*4bdff4beSrobert // 3*4bdff4beSrobert // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4*4bdff4beSrobert // See https://llvm.org/LICENSE.txt for license information. 5*4bdff4beSrobert // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6*4bdff4beSrobert // 7*4bdff4beSrobert //===----------------------------------------------------------------------===// 8*4bdff4beSrobert 9*4bdff4beSrobert #ifndef _LIBCPP___RANDOM_SHUFFLE_ORDER_ENGINE_H 10*4bdff4beSrobert #define _LIBCPP___RANDOM_SHUFFLE_ORDER_ENGINE_H 11*4bdff4beSrobert 12*4bdff4beSrobert #include <__algorithm/equal.h> 13*4bdff4beSrobert #include <__config> 14*4bdff4beSrobert #include <__random/is_seed_sequence.h> 15*4bdff4beSrobert #include <__utility/move.h> 16*4bdff4beSrobert #include <cstdint> 17*4bdff4beSrobert #include <iosfwd> 18*4bdff4beSrobert #include <type_traits> 19*4bdff4beSrobert 20*4bdff4beSrobert #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) 21*4bdff4beSrobert # pragma GCC system_header 22*4bdff4beSrobert #endif 23*4bdff4beSrobert 24*4bdff4beSrobert _LIBCPP_PUSH_MACROS 25*4bdff4beSrobert #include <__undef_macros> 26*4bdff4beSrobert 27*4bdff4beSrobert _LIBCPP_BEGIN_NAMESPACE_STD 28*4bdff4beSrobert 29*4bdff4beSrobert template <uint64_t _Xp, uint64_t _Yp> 30*4bdff4beSrobert struct __ugcd 31*4bdff4beSrobert { 32*4bdff4beSrobert static _LIBCPP_CONSTEXPR const uint64_t value = __ugcd<_Yp, _Xp % _Yp>::value; 33*4bdff4beSrobert }; 34*4bdff4beSrobert 35*4bdff4beSrobert template <uint64_t _Xp> 36*4bdff4beSrobert struct __ugcd<_Xp, 0> 37*4bdff4beSrobert { 38*4bdff4beSrobert static _LIBCPP_CONSTEXPR const uint64_t value = _Xp; 39*4bdff4beSrobert }; 40*4bdff4beSrobert 41*4bdff4beSrobert template <uint64_t _Np, uint64_t _Dp> 42*4bdff4beSrobert class __uratio 43*4bdff4beSrobert { 44*4bdff4beSrobert static_assert(_Dp != 0, "__uratio divide by 0"); 45*4bdff4beSrobert static _LIBCPP_CONSTEXPR const uint64_t __gcd = __ugcd<_Np, _Dp>::value; 46*4bdff4beSrobert public: 47*4bdff4beSrobert static _LIBCPP_CONSTEXPR const uint64_t num = _Np / __gcd; 48*4bdff4beSrobert static _LIBCPP_CONSTEXPR const uint64_t den = _Dp / __gcd; 49*4bdff4beSrobert 50*4bdff4beSrobert typedef __uratio<num, den> type; 51*4bdff4beSrobert }; 52*4bdff4beSrobert 53*4bdff4beSrobert template<class _Engine, size_t __k> 54*4bdff4beSrobert class _LIBCPP_TEMPLATE_VIS shuffle_order_engine 55*4bdff4beSrobert { 56*4bdff4beSrobert static_assert(0 < __k, "shuffle_order_engine invalid parameters"); 57*4bdff4beSrobert public: 58*4bdff4beSrobert // types 59*4bdff4beSrobert typedef typename _Engine::result_type result_type; 60*4bdff4beSrobert 61*4bdff4beSrobert private: 62*4bdff4beSrobert _Engine __e_; 63*4bdff4beSrobert result_type __v_[__k]; 64*4bdff4beSrobert result_type __y_; 65*4bdff4beSrobert 66*4bdff4beSrobert public: 67*4bdff4beSrobert // engine characteristics 68*4bdff4beSrobert static _LIBCPP_CONSTEXPR const size_t table_size = __k; 69*4bdff4beSrobert 70*4bdff4beSrobert #ifdef _LIBCPP_CXX03_LANG 71*4bdff4beSrobert static const result_type _Min = _Engine::_Min; 72*4bdff4beSrobert static const result_type _Max = _Engine::_Max; 73*4bdff4beSrobert #else 74*4bdff4beSrobert static _LIBCPP_CONSTEXPR const result_type _Min = _Engine::min(); 75*4bdff4beSrobert static _LIBCPP_CONSTEXPR const result_type _Max = _Engine::max(); 76*4bdff4beSrobert #endif 77*4bdff4beSrobert static_assert(_Min < _Max, "shuffle_order_engine invalid parameters"); 78*4bdff4beSrobert _LIBCPP_INLINE_VISIBILITY 79*4bdff4beSrobert static _LIBCPP_CONSTEXPR result_type min() { return _Min; } 80*4bdff4beSrobert _LIBCPP_INLINE_VISIBILITY 81*4bdff4beSrobert static _LIBCPP_CONSTEXPR result_type max() { return _Max; } 82*4bdff4beSrobert 83*4bdff4beSrobert static _LIBCPP_CONSTEXPR const unsigned long long _Rp = _Max - _Min + 1ull; 84*4bdff4beSrobert 85*4bdff4beSrobert // constructors and seeding functions 86*4bdff4beSrobert _LIBCPP_INLINE_VISIBILITY 87*4bdff4beSrobert shuffle_order_engine() {__init();} 88*4bdff4beSrobert _LIBCPP_INLINE_VISIBILITY 89*4bdff4beSrobert explicit shuffle_order_engine(const _Engine& __e) 90*4bdff4beSrobert : __e_(__e) {__init();} 91*4bdff4beSrobert #ifndef _LIBCPP_CXX03_LANG 92*4bdff4beSrobert _LIBCPP_INLINE_VISIBILITY 93*4bdff4beSrobert explicit shuffle_order_engine(_Engine&& __e) 94*4bdff4beSrobert : __e_(_VSTD::move(__e)) {__init();} 95*4bdff4beSrobert #endif // _LIBCPP_CXX03_LANG 96*4bdff4beSrobert _LIBCPP_INLINE_VISIBILITY 97*4bdff4beSrobert explicit shuffle_order_engine(result_type __sd) : __e_(__sd) {__init();} 98*4bdff4beSrobert template<class _Sseq> 99*4bdff4beSrobert _LIBCPP_INLINE_VISIBILITY 100*4bdff4beSrobert explicit shuffle_order_engine(_Sseq& __q, 101*4bdff4beSrobert typename enable_if<__is_seed_sequence<_Sseq, shuffle_order_engine>::value && 102*4bdff4beSrobert !is_convertible<_Sseq, _Engine>::value>::type* = 0) 103*4bdff4beSrobert : __e_(__q) {__init();} 104*4bdff4beSrobert _LIBCPP_INLINE_VISIBILITY 105*4bdff4beSrobert void seed() {__e_.seed(); __init();} 106*4bdff4beSrobert _LIBCPP_INLINE_VISIBILITY 107*4bdff4beSrobert void seed(result_type __sd) {__e_.seed(__sd); __init();} 108*4bdff4beSrobert template<class _Sseq> 109*4bdff4beSrobert _LIBCPP_INLINE_VISIBILITY 110*4bdff4beSrobert typename enable_if 111*4bdff4beSrobert < 112*4bdff4beSrobert __is_seed_sequence<_Sseq, shuffle_order_engine>::value, 113*4bdff4beSrobert void 114*4bdff4beSrobert >::type 115*4bdff4beSrobert seed(_Sseq& __q) {__e_.seed(__q); __init();} 116*4bdff4beSrobert 117*4bdff4beSrobert // generating functions 118*4bdff4beSrobert _LIBCPP_INLINE_VISIBILITY 119*4bdff4beSrobert result_type operator()() {return __eval(integral_constant<bool, _Rp != 0>());} 120*4bdff4beSrobert _LIBCPP_INLINE_VISIBILITY 121*4bdff4beSrobert void discard(unsigned long long __z) {for (; __z; --__z) operator()();} 122*4bdff4beSrobert 123*4bdff4beSrobert // property functions 124*4bdff4beSrobert _LIBCPP_INLINE_VISIBILITY 125*4bdff4beSrobert const _Engine& base() const _NOEXCEPT {return __e_;} 126*4bdff4beSrobert 127*4bdff4beSrobert private: 128*4bdff4beSrobert template<class _Eng, size_t _Kp> 129*4bdff4beSrobert friend 130*4bdff4beSrobert bool 131*4bdff4beSrobert operator==( 132*4bdff4beSrobert const shuffle_order_engine<_Eng, _Kp>& __x, 133*4bdff4beSrobert const shuffle_order_engine<_Eng, _Kp>& __y); 134*4bdff4beSrobert 135*4bdff4beSrobert template<class _Eng, size_t _Kp> 136*4bdff4beSrobert friend 137*4bdff4beSrobert bool 138*4bdff4beSrobert operator!=( 139*4bdff4beSrobert const shuffle_order_engine<_Eng, _Kp>& __x, 140*4bdff4beSrobert const shuffle_order_engine<_Eng, _Kp>& __y); 141*4bdff4beSrobert 142*4bdff4beSrobert template <class _CharT, class _Traits, 143*4bdff4beSrobert class _Eng, size_t _Kp> 144*4bdff4beSrobert friend 145*4bdff4beSrobert basic_ostream<_CharT, _Traits>& 146*4bdff4beSrobert operator<<(basic_ostream<_CharT, _Traits>& __os, 147*4bdff4beSrobert const shuffle_order_engine<_Eng, _Kp>& __x); 148*4bdff4beSrobert 149*4bdff4beSrobert template <class _CharT, class _Traits, 150*4bdff4beSrobert class _Eng, size_t _Kp> 151*4bdff4beSrobert friend 152*4bdff4beSrobert basic_istream<_CharT, _Traits>& 153*4bdff4beSrobert operator>>(basic_istream<_CharT, _Traits>& __is, 154*4bdff4beSrobert shuffle_order_engine<_Eng, _Kp>& __x); 155*4bdff4beSrobert 156*4bdff4beSrobert _LIBCPP_INLINE_VISIBILITY 157*4bdff4beSrobert void __init() 158*4bdff4beSrobert { 159*4bdff4beSrobert for (size_t __i = 0; __i < __k; ++__i) 160*4bdff4beSrobert __v_[__i] = __e_(); 161*4bdff4beSrobert __y_ = __e_(); 162*4bdff4beSrobert } 163*4bdff4beSrobert 164*4bdff4beSrobert _LIBCPP_INLINE_VISIBILITY 165*4bdff4beSrobert result_type __eval(false_type) {return __eval2(integral_constant<bool, __k & 1>());} 166*4bdff4beSrobert _LIBCPP_INLINE_VISIBILITY 167*4bdff4beSrobert result_type __eval(true_type) {return __eval(__uratio<__k, _Rp>());} 168*4bdff4beSrobert 169*4bdff4beSrobert _LIBCPP_INLINE_VISIBILITY 170*4bdff4beSrobert result_type __eval2(false_type) {return __eval(__uratio<__k/2, 0x8000000000000000ull>());} 171*4bdff4beSrobert _LIBCPP_INLINE_VISIBILITY 172*4bdff4beSrobert result_type __eval2(true_type) {return __evalf<__k, 0>();} 173*4bdff4beSrobert 174*4bdff4beSrobert template <uint64_t _Np, uint64_t _Dp> 175*4bdff4beSrobert _LIBCPP_INLINE_VISIBILITY 176*4bdff4beSrobert typename enable_if 177*4bdff4beSrobert < 178*4bdff4beSrobert (__uratio<_Np, _Dp>::num > 0xFFFFFFFFFFFFFFFFull / (_Max - _Min)), 179*4bdff4beSrobert result_type 180*4bdff4beSrobert >::type 181*4bdff4beSrobert __eval(__uratio<_Np, _Dp>) 182*4bdff4beSrobert {return __evalf<__uratio<_Np, _Dp>::num, __uratio<_Np, _Dp>::den>();} 183*4bdff4beSrobert 184*4bdff4beSrobert template <uint64_t _Np, uint64_t _Dp> 185*4bdff4beSrobert _LIBCPP_INLINE_VISIBILITY 186*4bdff4beSrobert typename enable_if 187*4bdff4beSrobert < 188*4bdff4beSrobert __uratio<_Np, _Dp>::num <= 0xFFFFFFFFFFFFFFFFull / (_Max - _Min), 189*4bdff4beSrobert result_type 190*4bdff4beSrobert >::type 191*4bdff4beSrobert __eval(__uratio<_Np, _Dp>) 192*4bdff4beSrobert { 193*4bdff4beSrobert const size_t __j = static_cast<size_t>(__uratio<_Np, _Dp>::num * (__y_ - _Min) 194*4bdff4beSrobert / __uratio<_Np, _Dp>::den); 195*4bdff4beSrobert __y_ = __v_[__j]; 196*4bdff4beSrobert __v_[__j] = __e_(); 197*4bdff4beSrobert return __y_; 198*4bdff4beSrobert } 199*4bdff4beSrobert 200*4bdff4beSrobert template <uint64_t __n, uint64_t __d> 201*4bdff4beSrobert _LIBCPP_INLINE_VISIBILITY 202*4bdff4beSrobert result_type __evalf() 203*4bdff4beSrobert { 204*4bdff4beSrobert const double _Fp = __d == 0 ? 205*4bdff4beSrobert __n / (2. * 0x8000000000000000ull) : 206*4bdff4beSrobert __n / (double)__d; 207*4bdff4beSrobert const size_t __j = static_cast<size_t>(_Fp * (__y_ - _Min)); 208*4bdff4beSrobert __y_ = __v_[__j]; 209*4bdff4beSrobert __v_[__j] = __e_(); 210*4bdff4beSrobert return __y_; 211*4bdff4beSrobert } 212*4bdff4beSrobert }; 213*4bdff4beSrobert 214*4bdff4beSrobert template<class _Engine, size_t __k> 215*4bdff4beSrobert _LIBCPP_CONSTEXPR const size_t shuffle_order_engine<_Engine, __k>::table_size; 216*4bdff4beSrobert 217*4bdff4beSrobert template<class _Eng, size_t _Kp> 218*4bdff4beSrobert _LIBCPP_HIDE_FROM_ABI bool 219*4bdff4beSrobert operator==( 220*4bdff4beSrobert const shuffle_order_engine<_Eng, _Kp>& __x, 221*4bdff4beSrobert const shuffle_order_engine<_Eng, _Kp>& __y) 222*4bdff4beSrobert { 223*4bdff4beSrobert return __x.__y_ == __y.__y_ && _VSTD::equal(__x.__v_, __x.__v_ + _Kp, __y.__v_) && 224*4bdff4beSrobert __x.__e_ == __y.__e_; 225*4bdff4beSrobert } 226*4bdff4beSrobert 227*4bdff4beSrobert template<class _Eng, size_t _Kp> 228*4bdff4beSrobert inline _LIBCPP_INLINE_VISIBILITY 229*4bdff4beSrobert bool 230*4bdff4beSrobert operator!=( 231*4bdff4beSrobert const shuffle_order_engine<_Eng, _Kp>& __x, 232*4bdff4beSrobert const shuffle_order_engine<_Eng, _Kp>& __y) 233*4bdff4beSrobert { 234*4bdff4beSrobert return !(__x == __y); 235*4bdff4beSrobert } 236*4bdff4beSrobert 237*4bdff4beSrobert template <class _CharT, class _Traits, 238*4bdff4beSrobert class _Eng, size_t _Kp> 239*4bdff4beSrobert _LIBCPP_HIDE_FROM_ABI basic_ostream<_CharT, _Traits>& 240*4bdff4beSrobert operator<<(basic_ostream<_CharT, _Traits>& __os, 241*4bdff4beSrobert const shuffle_order_engine<_Eng, _Kp>& __x) 242*4bdff4beSrobert { 243*4bdff4beSrobert __save_flags<_CharT, _Traits> __lx(__os); 244*4bdff4beSrobert typedef basic_ostream<_CharT, _Traits> _Ostream; 245*4bdff4beSrobert __os.flags(_Ostream::dec | _Ostream::left); 246*4bdff4beSrobert _CharT __sp = __os.widen(' '); 247*4bdff4beSrobert __os.fill(__sp); 248*4bdff4beSrobert __os << __x.__e_ << __sp << __x.__v_[0]; 249*4bdff4beSrobert for (size_t __i = 1; __i < _Kp; ++__i) 250*4bdff4beSrobert __os << __sp << __x.__v_[__i]; 251*4bdff4beSrobert return __os << __sp << __x.__y_; 252*4bdff4beSrobert } 253*4bdff4beSrobert 254*4bdff4beSrobert template <class _CharT, class _Traits, 255*4bdff4beSrobert class _Eng, size_t _Kp> 256*4bdff4beSrobert _LIBCPP_HIDE_FROM_ABI basic_istream<_CharT, _Traits>& 257*4bdff4beSrobert operator>>(basic_istream<_CharT, _Traits>& __is, 258*4bdff4beSrobert shuffle_order_engine<_Eng, _Kp>& __x) 259*4bdff4beSrobert { 260*4bdff4beSrobert typedef typename shuffle_order_engine<_Eng, _Kp>::result_type result_type; 261*4bdff4beSrobert __save_flags<_CharT, _Traits> __lx(__is); 262*4bdff4beSrobert typedef basic_istream<_CharT, _Traits> _Istream; 263*4bdff4beSrobert __is.flags(_Istream::dec | _Istream::skipws); 264*4bdff4beSrobert _Eng __e; 265*4bdff4beSrobert result_type _Vp[_Kp+1]; 266*4bdff4beSrobert __is >> __e; 267*4bdff4beSrobert for (size_t __i = 0; __i < _Kp+1; ++__i) 268*4bdff4beSrobert __is >> _Vp[__i]; 269*4bdff4beSrobert if (!__is.fail()) 270*4bdff4beSrobert { 271*4bdff4beSrobert __x.__e_ = __e; 272*4bdff4beSrobert for (size_t __i = 0; __i < _Kp; ++__i) 273*4bdff4beSrobert __x.__v_[__i] = _Vp[__i]; 274*4bdff4beSrobert __x.__y_ = _Vp[_Kp]; 275*4bdff4beSrobert } 276*4bdff4beSrobert return __is; 277*4bdff4beSrobert } 278*4bdff4beSrobert 279*4bdff4beSrobert _LIBCPP_END_NAMESPACE_STD 280*4bdff4beSrobert 281*4bdff4beSrobert _LIBCPP_POP_MACROS 282*4bdff4beSrobert 283*4bdff4beSrobert #endif // _LIBCPP___RANDOM_SHUFFLE_ORDER_ENGINE_H 284