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_DISCARD_BLOCK_ENGINE_H 104824e7fdSDimitry Andric #define _LIBCPP___RANDOM_DISCARD_BLOCK_ENGINE_H 114824e7fdSDimitry Andric 124824e7fdSDimitry Andric #include <__config> 134824e7fdSDimitry Andric #include <__random/is_seed_sequence.h> 1406c3fb27SDimitry Andric #include <__type_traits/enable_if.h> 1506c3fb27SDimitry Andric #include <__type_traits/is_convertible.h> 164824e7fdSDimitry Andric #include <__utility/move.h> 1706c3fb27SDimitry Andric #include <cstddef> 184824e7fdSDimitry Andric #include <iosfwd> 19bdd1243dSDimitry Andric #include <limits> 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 template <class _Engine, size_t __p, size_t __r> 31cb14a3feSDimitry Andric class _LIBCPP_TEMPLATE_VIS discard_block_engine { 324824e7fdSDimitry Andric _Engine __e_; 334824e7fdSDimitry Andric int __n_; 344824e7fdSDimitry Andric 354824e7fdSDimitry Andric static_assert(0 < __r, "discard_block_engine invalid parameters"); 364824e7fdSDimitry Andric static_assert(__r <= __p, "discard_block_engine invalid parameters"); 37bdd1243dSDimitry Andric #ifndef _LIBCPP_CXX03_LANG // numeric_limits::max() is not constexpr in C++03 38bdd1243dSDimitry Andric static_assert(__r <= numeric_limits<int>::max(), "discard_block_engine invalid parameters"); 39bdd1243dSDimitry Andric #endif 40cb14a3feSDimitry Andric 414824e7fdSDimitry Andric public: 424824e7fdSDimitry Andric // types 434824e7fdSDimitry Andric typedef typename _Engine::result_type result_type; 444824e7fdSDimitry Andric 454824e7fdSDimitry Andric // engine characteristics 464824e7fdSDimitry Andric static _LIBCPP_CONSTEXPR const size_t block_size = __p; 474824e7fdSDimitry Andric static _LIBCPP_CONSTEXPR const size_t used_block = __r; 484824e7fdSDimitry Andric 494824e7fdSDimitry Andric #ifdef _LIBCPP_CXX03_LANG 504824e7fdSDimitry Andric static const result_type _Min = _Engine::_Min; 514824e7fdSDimitry Andric static const result_type _Max = _Engine::_Max; 524824e7fdSDimitry Andric #else 53*0fca6ea1SDimitry Andric static constexpr result_type _Min = _Engine::min(); 54*0fca6ea1SDimitry Andric static constexpr result_type _Max = _Engine::max(); 554824e7fdSDimitry Andric #endif 564824e7fdSDimitry Andric 57cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI static _LIBCPP_CONSTEXPR result_type min() { return _Engine::min(); } 58cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI static _LIBCPP_CONSTEXPR result_type max() { return _Engine::max(); } 594824e7fdSDimitry Andric 604824e7fdSDimitry Andric // constructors and seeding functions 61cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI discard_block_engine() : __n_(0) {} 62cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI explicit discard_block_engine(const _Engine& __e) : __e_(__e), __n_(0) {} 634824e7fdSDimitry Andric #ifndef _LIBCPP_CXX03_LANG 64cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI explicit discard_block_engine(_Engine&& __e) : __e_(std::move(__e)), __n_(0) {} 654824e7fdSDimitry Andric #endif // _LIBCPP_CXX03_LANG 66cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI explicit discard_block_engine(result_type __sd) : __e_(__sd), __n_(0) {} 67cb14a3feSDimitry Andric template < 68cb14a3feSDimitry Andric class _Sseq, 69cb14a3feSDimitry Andric __enable_if_t<__is_seed_sequence<_Sseq, discard_block_engine>::value && !is_convertible<_Sseq, _Engine>::value, 70cb14a3feSDimitry Andric int> = 0> 71cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI explicit discard_block_engine(_Sseq& __q) : __e_(__q), __n_(0) {} 72cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI void seed() { 73cb14a3feSDimitry Andric __e_.seed(); 74cb14a3feSDimitry Andric __n_ = 0; 75cb14a3feSDimitry Andric } 76cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI void seed(result_type __sd) { 77cb14a3feSDimitry Andric __e_.seed(__sd); 78cb14a3feSDimitry Andric __n_ = 0; 79cb14a3feSDimitry Andric } 805f757f3fSDimitry Andric template <class _Sseq, __enable_if_t<__is_seed_sequence<_Sseq, discard_block_engine>::value, int> = 0> 81cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI void seed(_Sseq& __q) { 82cb14a3feSDimitry Andric __e_.seed(__q); 83cb14a3feSDimitry Andric __n_ = 0; 84cb14a3feSDimitry Andric } 854824e7fdSDimitry Andric 864824e7fdSDimitry Andric // generating functions 8706c3fb27SDimitry Andric _LIBCPP_HIDE_FROM_ABI result_type operator()(); 88cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI void discard(unsigned long long __z) { 89cb14a3feSDimitry Andric for (; __z; --__z) 90cb14a3feSDimitry Andric operator()(); 91cb14a3feSDimitry Andric } 924824e7fdSDimitry Andric 934824e7fdSDimitry Andric // property functions 94cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI const _Engine& base() const _NOEXCEPT { return __e_; } 954824e7fdSDimitry Andric 964824e7fdSDimitry Andric template <class _Eng, size_t _Pp, size_t _Rp> 97cb14a3feSDimitry Andric friend bool 98cb14a3feSDimitry Andric operator==(const discard_block_engine<_Eng, _Pp, _Rp>& __x, const discard_block_engine<_Eng, _Pp, _Rp>& __y); 994824e7fdSDimitry Andric 1004824e7fdSDimitry Andric template <class _Eng, size_t _Pp, size_t _Rp> 101cb14a3feSDimitry Andric friend bool 102cb14a3feSDimitry Andric operator!=(const discard_block_engine<_Eng, _Pp, _Rp>& __x, const discard_block_engine<_Eng, _Pp, _Rp>& __y); 1034824e7fdSDimitry Andric 104cb14a3feSDimitry Andric template <class _CharT, class _Traits, class _Eng, size_t _Pp, size_t _Rp> 105cb14a3feSDimitry Andric friend basic_ostream<_CharT, _Traits>& 106cb14a3feSDimitry Andric operator<<(basic_ostream<_CharT, _Traits>& __os, const discard_block_engine<_Eng, _Pp, _Rp>& __x); 1074824e7fdSDimitry Andric 108cb14a3feSDimitry Andric template <class _CharT, class _Traits, class _Eng, size_t _Pp, size_t _Rp> 109cb14a3feSDimitry Andric friend basic_istream<_CharT, _Traits>& 110cb14a3feSDimitry Andric operator>>(basic_istream<_CharT, _Traits>& __is, discard_block_engine<_Eng, _Pp, _Rp>& __x); 1114824e7fdSDimitry Andric }; 1124824e7fdSDimitry Andric 1134824e7fdSDimitry Andric template <class _Engine, size_t __p, size_t __r> 1144824e7fdSDimitry Andric _LIBCPP_CONSTEXPR const size_t discard_block_engine<_Engine, __p, __r>::block_size; 1154824e7fdSDimitry Andric 1164824e7fdSDimitry Andric template <class _Engine, size_t __p, size_t __r> 1174824e7fdSDimitry Andric _LIBCPP_CONSTEXPR const size_t discard_block_engine<_Engine, __p, __r>::used_block; 1184824e7fdSDimitry Andric 1194824e7fdSDimitry Andric template <class _Engine, size_t __p, size_t __r> 120cb14a3feSDimitry Andric typename discard_block_engine<_Engine, __p, __r>::result_type discard_block_engine<_Engine, __p, __r>::operator()() { 121cb14a3feSDimitry Andric if (__n_ >= static_cast<int>(__r)) { 1224824e7fdSDimitry Andric __e_.discard(__p - __r); 1234824e7fdSDimitry Andric __n_ = 0; 1244824e7fdSDimitry Andric } 1254824e7fdSDimitry Andric ++__n_; 1264824e7fdSDimitry Andric return __e_(); 1274824e7fdSDimitry Andric } 1284824e7fdSDimitry Andric 1294824e7fdSDimitry Andric template <class _Eng, size_t _Pp, size_t _Rp> 130cb14a3feSDimitry Andric inline _LIBCPP_HIDE_FROM_ABI bool 131cb14a3feSDimitry Andric operator==(const discard_block_engine<_Eng, _Pp, _Rp>& __x, const discard_block_engine<_Eng, _Pp, _Rp>& __y) { 1324824e7fdSDimitry Andric return __x.__n_ == __y.__n_ && __x.__e_ == __y.__e_; 1334824e7fdSDimitry Andric } 1344824e7fdSDimitry Andric 1354824e7fdSDimitry Andric template <class _Eng, size_t _Pp, size_t _Rp> 136cb14a3feSDimitry Andric inline _LIBCPP_HIDE_FROM_ABI bool 137cb14a3feSDimitry Andric operator!=(const discard_block_engine<_Eng, _Pp, _Rp>& __x, const discard_block_engine<_Eng, _Pp, _Rp>& __y) { 1384824e7fdSDimitry Andric return !(__x == __y); 1394824e7fdSDimitry Andric } 1404824e7fdSDimitry Andric 141cb14a3feSDimitry Andric template <class _CharT, class _Traits, class _Eng, size_t _Pp, size_t _Rp> 142bdd1243dSDimitry Andric _LIBCPP_HIDE_FROM_ABI basic_ostream<_CharT, _Traits>& 143cb14a3feSDimitry Andric operator<<(basic_ostream<_CharT, _Traits>& __os, const discard_block_engine<_Eng, _Pp, _Rp>& __x) { 1444824e7fdSDimitry Andric __save_flags<_CharT, _Traits> __lx(__os); 1454824e7fdSDimitry Andric typedef basic_ostream<_CharT, _Traits> _Ostream; 1464824e7fdSDimitry Andric __os.flags(_Ostream::dec | _Ostream::left); 1474824e7fdSDimitry Andric _CharT __sp = __os.widen(' '); 1484824e7fdSDimitry Andric __os.fill(__sp); 1494824e7fdSDimitry Andric return __os << __x.__e_ << __sp << __x.__n_; 1504824e7fdSDimitry Andric } 1514824e7fdSDimitry Andric 152cb14a3feSDimitry Andric template <class _CharT, class _Traits, class _Eng, size_t _Pp, size_t _Rp> 153bdd1243dSDimitry Andric _LIBCPP_HIDE_FROM_ABI basic_istream<_CharT, _Traits>& 154cb14a3feSDimitry Andric operator>>(basic_istream<_CharT, _Traits>& __is, discard_block_engine<_Eng, _Pp, _Rp>& __x) { 1554824e7fdSDimitry Andric __save_flags<_CharT, _Traits> __lx(__is); 1564824e7fdSDimitry Andric typedef basic_istream<_CharT, _Traits> _Istream; 1574824e7fdSDimitry Andric __is.flags(_Istream::dec | _Istream::skipws); 1584824e7fdSDimitry Andric _Eng __e; 1594824e7fdSDimitry Andric int __n; 1604824e7fdSDimitry Andric __is >> __e >> __n; 161cb14a3feSDimitry Andric if (!__is.fail()) { 1624824e7fdSDimitry Andric __x.__e_ = __e; 1634824e7fdSDimitry Andric __x.__n_ = __n; 1644824e7fdSDimitry Andric } 1654824e7fdSDimitry Andric return __is; 1664824e7fdSDimitry Andric } 1674824e7fdSDimitry Andric 1684824e7fdSDimitry Andric _LIBCPP_END_NAMESPACE_STD 1694824e7fdSDimitry Andric 1704824e7fdSDimitry Andric _LIBCPP_POP_MACROS 1714824e7fdSDimitry Andric 1724824e7fdSDimitry Andric #endif // _LIBCPP___RANDOM_DISCARD_BLOCK_ENGINE_H 173