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_INDEPENDENT_BITS_ENGINE_H 104824e7fdSDimitry Andric #define _LIBCPP___RANDOM_INDEPENDENT_BITS_ENGINE_H 114824e7fdSDimitry Andric 124824e7fdSDimitry Andric #include <__config> 135f757f3fSDimitry Andric #include <__fwd/istream.h> 145f757f3fSDimitry Andric #include <__fwd/ostream.h> 154824e7fdSDimitry Andric #include <__random/is_seed_sequence.h> 164824e7fdSDimitry Andric #include <__random/log2.h> 1706c3fb27SDimitry Andric #include <__type_traits/conditional.h> 1806c3fb27SDimitry Andric #include <__type_traits/enable_if.h> 1906c3fb27SDimitry Andric #include <__type_traits/is_convertible.h> 204824e7fdSDimitry Andric #include <__utility/move.h> 2106c3fb27SDimitry Andric #include <cstddef> 224824e7fdSDimitry Andric #include <limits> 234824e7fdSDimitry Andric 244824e7fdSDimitry Andric #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) 254824e7fdSDimitry Andric # pragma GCC system_header 264824e7fdSDimitry Andric #endif 274824e7fdSDimitry Andric 284824e7fdSDimitry Andric _LIBCPP_PUSH_MACROS 294824e7fdSDimitry Andric #include <__undef_macros> 304824e7fdSDimitry Andric 314824e7fdSDimitry Andric _LIBCPP_BEGIN_NAMESPACE_STD 324824e7fdSDimitry Andric 334824e7fdSDimitry Andric template <class _Engine, size_t __w, class _UIntType> 34*cb14a3feSDimitry Andric class _LIBCPP_TEMPLATE_VIS independent_bits_engine { 354824e7fdSDimitry Andric template <class _UInt, _UInt _R0, size_t _Wp, size_t _Mp> 36*cb14a3feSDimitry Andric class __get_n { 374824e7fdSDimitry Andric static _LIBCPP_CONSTEXPR const size_t _Dt = numeric_limits<_UInt>::digits; 384824e7fdSDimitry Andric static _LIBCPP_CONSTEXPR const size_t _Np = _Wp / _Mp + (_Wp % _Mp != 0); 394824e7fdSDimitry Andric static _LIBCPP_CONSTEXPR const size_t _W0 = _Wp / _Np; 404824e7fdSDimitry Andric static _LIBCPP_CONSTEXPR const _UInt _Y0 = _W0 >= _Dt ? 0 : (_R0 >> _W0) << _W0; 41*cb14a3feSDimitry Andric 424824e7fdSDimitry Andric public: 434824e7fdSDimitry Andric static _LIBCPP_CONSTEXPR const size_t value = _R0 - _Y0 > _Y0 / _Np ? _Np + 1 : _Np; 444824e7fdSDimitry Andric }; 45*cb14a3feSDimitry Andric 464824e7fdSDimitry Andric public: 474824e7fdSDimitry Andric // types 484824e7fdSDimitry Andric typedef _UIntType result_type; 494824e7fdSDimitry Andric 504824e7fdSDimitry Andric private: 514824e7fdSDimitry Andric _Engine __e_; 524824e7fdSDimitry Andric 534824e7fdSDimitry Andric static _LIBCPP_CONSTEXPR const result_type _Dt = numeric_limits<result_type>::digits; 544824e7fdSDimitry Andric static_assert(0 < __w, "independent_bits_engine invalid parameters"); 554824e7fdSDimitry Andric static_assert(__w <= _Dt, "independent_bits_engine invalid parameters"); 564824e7fdSDimitry Andric 574824e7fdSDimitry Andric typedef typename _Engine::result_type _Engine_result_type; 58bdd1243dSDimitry Andric typedef __conditional_t<sizeof(_Engine_result_type) <= sizeof(result_type), result_type, _Engine_result_type> 59bdd1243dSDimitry Andric _Working_result_type; 604824e7fdSDimitry Andric #ifdef _LIBCPP_CXX03_LANG 61*cb14a3feSDimitry Andric static const _Working_result_type _Rp = _Engine::_Max - _Engine::_Min + _Working_result_type(1); 624824e7fdSDimitry Andric #else 63*cb14a3feSDimitry Andric static _LIBCPP_CONSTEXPR const _Working_result_type _Rp = _Engine::max() - _Engine::min() + _Working_result_type(1); 644824e7fdSDimitry Andric #endif 654824e7fdSDimitry Andric static _LIBCPP_CONSTEXPR const size_t __m = __log2<_Working_result_type, _Rp>::value; 664824e7fdSDimitry Andric static _LIBCPP_CONSTEXPR const size_t __n = __get_n<_Working_result_type, _Rp, __w, __m>::value; 674824e7fdSDimitry Andric static _LIBCPP_CONSTEXPR const size_t __w0 = __w / __n; 684824e7fdSDimitry Andric static _LIBCPP_CONSTEXPR const size_t __n0 = __n - __w % __n; 694824e7fdSDimitry Andric static _LIBCPP_CONSTEXPR const size_t _WDt = numeric_limits<_Working_result_type>::digits; 704824e7fdSDimitry Andric static _LIBCPP_CONSTEXPR const size_t _EDt = numeric_limits<_Engine_result_type>::digits; 71*cb14a3feSDimitry Andric static _LIBCPP_CONSTEXPR const _Working_result_type __y0 = __w0 >= _WDt ? 0 : (_Rp >> __w0) << __w0; 72*cb14a3feSDimitry Andric static _LIBCPP_CONSTEXPR const _Working_result_type __y1 = __w0 >= _WDt - 1 ? 0 : (_Rp >> (__w0 + 1)) << (__w0 + 1); 73*cb14a3feSDimitry Andric static _LIBCPP_CONSTEXPR const 74*cb14a3feSDimitry Andric _Engine_result_type __mask0 = __w0 > 0 ? _Engine_result_type(~0) >> (_EDt - __w0) : _Engine_result_type(0); 75*cb14a3feSDimitry Andric static _LIBCPP_CONSTEXPR const _Engine_result_type __mask1 = 76*cb14a3feSDimitry Andric __w0 < _EDt - 1 ? _Engine_result_type(~0) >> (_EDt - (__w0 + 1)) : _Engine_result_type(~0); 77*cb14a3feSDimitry Andric 784824e7fdSDimitry Andric public: 794824e7fdSDimitry Andric static _LIBCPP_CONSTEXPR const result_type _Min = 0; 80*cb14a3feSDimitry Andric static _LIBCPP_CONSTEXPR const result_type _Max = 81*cb14a3feSDimitry Andric __w == _Dt ? result_type(~0) : (result_type(1) << __w) - result_type(1); 824824e7fdSDimitry Andric static_assert(_Min < _Max, "independent_bits_engine invalid parameters"); 834824e7fdSDimitry Andric 844824e7fdSDimitry Andric // engine characteristics 85*cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI static _LIBCPP_CONSTEXPR result_type min() { return _Min; } 86*cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI static _LIBCPP_CONSTEXPR result_type max() { return _Max; } 874824e7fdSDimitry Andric 884824e7fdSDimitry Andric // constructors and seeding functions 89*cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI independent_bits_engine() {} 90*cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI explicit independent_bits_engine(const _Engine& __e) : __e_(__e) {} 914824e7fdSDimitry Andric #ifndef _LIBCPP_CXX03_LANG 92*cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI explicit independent_bits_engine(_Engine&& __e) : __e_(std::move(__e)) {} 934824e7fdSDimitry Andric #endif // _LIBCPP_CXX03_LANG 94*cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI explicit independent_bits_engine(result_type __sd) : __e_(__sd) {} 95*cb14a3feSDimitry Andric template < 96*cb14a3feSDimitry Andric class _Sseq, 97*cb14a3feSDimitry Andric __enable_if_t<__is_seed_sequence<_Sseq, independent_bits_engine>::value && !is_convertible<_Sseq, _Engine>::value, 98*cb14a3feSDimitry Andric int> = 0> 99*cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI explicit independent_bits_engine(_Sseq& __q) : __e_(__q) {} 100*cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI void seed() { __e_.seed(); } 101*cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI void seed(result_type __sd) { __e_.seed(__sd); } 1025f757f3fSDimitry Andric template <class _Sseq, __enable_if_t<__is_seed_sequence<_Sseq, independent_bits_engine>::value, int> = 0> 103*cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI void seed(_Sseq& __q) { 104*cb14a3feSDimitry Andric __e_.seed(__q); 105*cb14a3feSDimitry Andric } 1064824e7fdSDimitry Andric 1074824e7fdSDimitry Andric // generating functions 108*cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI result_type operator()() { return __eval(integral_constant<bool, _Rp != 0>()); } 109*cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI void discard(unsigned long long __z) { 110*cb14a3feSDimitry Andric for (; __z; --__z) 111*cb14a3feSDimitry Andric operator()(); 112*cb14a3feSDimitry Andric } 1134824e7fdSDimitry Andric 1144824e7fdSDimitry Andric // property functions 115*cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI const _Engine& base() const _NOEXCEPT { return __e_; } 1164824e7fdSDimitry Andric 1174824e7fdSDimitry Andric template <class _Eng, size_t _Wp, class _UInt> 118*cb14a3feSDimitry Andric friend bool operator==(const independent_bits_engine<_Eng, _Wp, _UInt>& __x, 1194824e7fdSDimitry Andric const independent_bits_engine<_Eng, _Wp, _UInt>& __y); 1204824e7fdSDimitry Andric 1214824e7fdSDimitry Andric template <class _Eng, size_t _Wp, class _UInt> 122*cb14a3feSDimitry Andric friend bool operator!=(const independent_bits_engine<_Eng, _Wp, _UInt>& __x, 1234824e7fdSDimitry Andric const independent_bits_engine<_Eng, _Wp, _UInt>& __y); 1244824e7fdSDimitry Andric 125*cb14a3feSDimitry Andric template <class _CharT, class _Traits, class _Eng, size_t _Wp, class _UInt> 126*cb14a3feSDimitry Andric friend basic_ostream<_CharT, _Traits>& 127*cb14a3feSDimitry Andric operator<<(basic_ostream<_CharT, _Traits>& __os, const independent_bits_engine<_Eng, _Wp, _UInt>& __x); 1284824e7fdSDimitry Andric 129*cb14a3feSDimitry Andric template <class _CharT, class _Traits, class _Eng, size_t _Wp, class _UInt> 130*cb14a3feSDimitry Andric friend basic_istream<_CharT, _Traits>& 131*cb14a3feSDimitry Andric operator>>(basic_istream<_CharT, _Traits>& __is, independent_bits_engine<_Eng, _Wp, _UInt>& __x); 1324824e7fdSDimitry Andric 1334824e7fdSDimitry Andric private: 134*cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI result_type __eval(false_type); 13506c3fb27SDimitry Andric _LIBCPP_HIDE_FROM_ABI result_type __eval(true_type); 1364824e7fdSDimitry Andric 137*cb14a3feSDimitry Andric template <size_t __count, 138*cb14a3feSDimitry Andric __enable_if_t<__count< _Dt, int> = 0> _LIBCPP_HIDE_FROM_ABI static result_type __lshift(result_type __x) { 139*cb14a3feSDimitry Andric return __x << __count; 140*cb14a3feSDimitry Andric } 1414824e7fdSDimitry Andric 1425f757f3fSDimitry Andric template <size_t __count, __enable_if_t<(__count >= _Dt), int> = 0> 143*cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI static result_type __lshift(result_type) { 144*cb14a3feSDimitry Andric return result_type(0); 145*cb14a3feSDimitry Andric } 1464824e7fdSDimitry Andric }; 1474824e7fdSDimitry Andric 1484824e7fdSDimitry Andric template <class _Engine, size_t __w, class _UIntType> 149*cb14a3feSDimitry Andric inline _UIntType independent_bits_engine<_Engine, __w, _UIntType>::__eval(false_type) { 1504824e7fdSDimitry Andric return static_cast<result_type>(__e_() & __mask0); 1514824e7fdSDimitry Andric } 1524824e7fdSDimitry Andric 1534824e7fdSDimitry Andric template <class _Engine, size_t __w, class _UIntType> 154*cb14a3feSDimitry Andric _UIntType independent_bits_engine<_Engine, __w, _UIntType>::__eval(true_type) { 15506c3fb27SDimitry Andric result_type __sp = 0; 156*cb14a3feSDimitry Andric for (size_t __k = 0; __k < __n0; ++__k) { 1574824e7fdSDimitry Andric _Engine_result_type __u; 158*cb14a3feSDimitry Andric do { 1594824e7fdSDimitry Andric __u = __e_() - _Engine::min(); 1604824e7fdSDimitry Andric } while (__u >= __y0); 16106c3fb27SDimitry Andric __sp = static_cast<result_type>(__lshift<__w0>(__sp) + (__u & __mask0)); 1624824e7fdSDimitry Andric } 163*cb14a3feSDimitry Andric for (size_t __k = __n0; __k < __n; ++__k) { 1644824e7fdSDimitry Andric _Engine_result_type __u; 165*cb14a3feSDimitry Andric do { 1664824e7fdSDimitry Andric __u = __e_() - _Engine::min(); 1674824e7fdSDimitry Andric } while (__u >= __y1); 16806c3fb27SDimitry Andric __sp = static_cast<result_type>(__lshift<__w0 + 1>(__sp) + (__u & __mask1)); 1694824e7fdSDimitry Andric } 17006c3fb27SDimitry Andric return __sp; 1714824e7fdSDimitry Andric } 1724824e7fdSDimitry Andric 1734824e7fdSDimitry Andric template <class _Eng, size_t _Wp, class _UInt> 174*cb14a3feSDimitry Andric inline _LIBCPP_HIDE_FROM_ABI bool 175*cb14a3feSDimitry Andric operator==(const independent_bits_engine<_Eng, _Wp, _UInt>& __x, const independent_bits_engine<_Eng, _Wp, _UInt>& __y) { 1764824e7fdSDimitry Andric return __x.base() == __y.base(); 1774824e7fdSDimitry Andric } 1784824e7fdSDimitry Andric 1794824e7fdSDimitry Andric template <class _Eng, size_t _Wp, class _UInt> 180*cb14a3feSDimitry Andric inline _LIBCPP_HIDE_FROM_ABI bool 181*cb14a3feSDimitry Andric operator!=(const independent_bits_engine<_Eng, _Wp, _UInt>& __x, const independent_bits_engine<_Eng, _Wp, _UInt>& __y) { 1824824e7fdSDimitry Andric return !(__x == __y); 1834824e7fdSDimitry Andric } 1844824e7fdSDimitry Andric 185*cb14a3feSDimitry Andric template <class _CharT, class _Traits, class _Eng, size_t _Wp, class _UInt> 186bdd1243dSDimitry Andric _LIBCPP_HIDE_FROM_ABI basic_ostream<_CharT, _Traits>& 187*cb14a3feSDimitry Andric operator<<(basic_ostream<_CharT, _Traits>& __os, const independent_bits_engine<_Eng, _Wp, _UInt>& __x) { 1884824e7fdSDimitry Andric return __os << __x.base(); 1894824e7fdSDimitry Andric } 1904824e7fdSDimitry Andric 191*cb14a3feSDimitry Andric template <class _CharT, class _Traits, class _Eng, size_t _Wp, class _UInt> 192bdd1243dSDimitry Andric _LIBCPP_HIDE_FROM_ABI basic_istream<_CharT, _Traits>& 193*cb14a3feSDimitry Andric operator>>(basic_istream<_CharT, _Traits>& __is, independent_bits_engine<_Eng, _Wp, _UInt>& __x) { 1944824e7fdSDimitry Andric _Eng __e; 1954824e7fdSDimitry Andric __is >> __e; 1964824e7fdSDimitry Andric if (!__is.fail()) 1974824e7fdSDimitry Andric __x.__e_ = __e; 1984824e7fdSDimitry Andric return __is; 1994824e7fdSDimitry Andric } 2004824e7fdSDimitry Andric 2014824e7fdSDimitry Andric _LIBCPP_END_NAMESPACE_STD 2024824e7fdSDimitry Andric 2034824e7fdSDimitry Andric _LIBCPP_POP_MACROS 2044824e7fdSDimitry Andric 2054824e7fdSDimitry Andric #endif // _LIBCPP___RANDOM_INDEPENDENT_BITS_ENGINE_H 206