32 #ifndef MCKL_RANDOM_COUNTER_HPP 33 #define MCKL_RANDOM_COUNTER_HPP 61 template <typename ResultType, typename Generator>
64 static_assert(std::is_unsigned<ResultType>::value,
65 "**CounterEngine** used with ResultType other than unsigned intger " 68 static_assert(Generator::size() %
sizeof(ResultType) == 0,
69 "**CounterEngine** used with Generator::size() not divisible by " 70 "sizeof(ResultType)");
75 using ctr_type =
typename generator_type::ctr_type;
76 using key_type =
typename generator_type::key_type;
87 template <
typename SeedSeq>
89 std::enable_if_t<is_seed_seq<SeedSeq>::value> * =
nullptr)
100 std::fill(key.begin(), key.end(), 0);
101 key.front() =
static_cast<typename key_type::value_type
>(s);
105 template <
typename SeedSeq>
107 std::enable_if_t<is_seed_seq<SeedSeq>::value> * =
nullptr)
110 seq.generator(key.begin(), key.end());
114 void seed(
const key_type &key) { reset(key); }
116 key_type
key()
const {
return generator_.key(); }
120 void key(
const key_type &k) { reset(k); }
135 generator_(ctr_, result_.data());
139 return result_[index_++];
144 const std::size_t remain =
static_cast<std::size_t
>(M_ - index_);
147 std::memcpy(r, result_.data() + index_,
sizeof(
result_type) * n);
148 index_ +=
static_cast<unsigned>(n);
152 std::memcpy(r, result_.data() + index_,
sizeof(
result_type) * remain);
157 const std::size_t m = n / M_;
158 generator_(ctr_, m, r);
162 generator_(ctr_, result_.data());
163 std::memcpy(r, result_.data(),
sizeof(
result_type) * n);
164 index_ =
static_cast<unsigned>(n);
172 const std::size_t remain =
static_cast<std::size_t
>(M_ - index_);
185 if (nskip <= remain) {
186 index_ +=
static_cast<unsigned>(nskip);
194 std::size_t ctr_size =
sizeof(
ctr_type);
197 generator_(ctr_, result_.data());
198 index_ =
static_cast<unsigned>(nskip % M);
203 return std::numeric_limits<result_type>::min();
208 return std::numeric_limits<result_type>::max();
211 friend bool operator==(
const CounterEngine<ResultType, Generator> &eng1,
212 const CounterEngine<ResultType, Generator> &eng2)
214 if (eng1.result_ != eng2.result_) {
217 if (eng1.ctr_ != eng2.ctr_) {
220 if (eng1.generator_ != eng2.generator_) {
223 if (eng1.index_ != eng2.index_) {
229 friend bool operator!=(
const CounterEngine<ResultType, Generator> &eng1,
230 const CounterEngine<ResultType, Generator> &eng2)
232 return !(eng1 == eng2);
235 template <
typename CharT,
typename Traits>
237 std::basic_ostream<CharT, Traits> &os,
238 const CounterEngine<ResultType, Generator> &eng)
244 os << eng.result_ <<
' ';
245 os << eng.ctr_ <<
' ';
246 os << eng.generator_ <<
' ';
252 template <
typename CharT,
typename Traits>
254 std::basic_istream<CharT, Traits> &is,
255 CounterEngine<ResultType, Generator> &eng)
261 CounterEngine<ResultType, Generator> eng_tmp;
262 is >> std::ws >> eng_tmp.result_;
263 is >> std::ws >> eng_tmp.ctr_;
264 is >> std::ws >> eng_tmp.generator_;
265 is >> std::ws >> eng_tmp.index_;
268 eng = std::move(eng_tmp);
275 static constexpr
unsigned M_ = Generator::size() /
sizeof(ResultType);
277 std::array<result_type, M_> result_;
282 void reset(
const key_type key)
284 std::fill(ctr_.begin(), ctr_.end(), 0);
285 generator_.reset(key);
291 template <
typename ResultType,
typename Generator>
298 template <
typename ResultType,
typename Generator>
307 #endif // MCKL_RANDOM_COUNTER_HPP
void seed(SeedSeq &seq, std::enable_if_t< is_seed_seq< SeedSeq >::value > *=nullptr)
Counter based RNG engine.
void discard(skip_type nskip)
friend bool operator==(const CounterEngine< ResultType, Generator > &eng1, const CounterEngine< ResultType, Generator > &eng2)
void ctr(const ctr_type &c)
#define MCKL_PUSH_CLANG_WARNING(warning)
void operator()(std::size_t n, result_type *r)
typename generator_type::key_type key_type
void seed(const key_type &key)
friend bool operator!=(const CounterEngine< ResultType, Generator > &eng1, const CounterEngine< ResultType, Generator > &eng2)
void key(const key_type &k)
typename ctr_type::value_type skip_type
CounterEngine(const key_type &k)
static constexpr result_type min()
typename generator_type::ctr_type ctr_type
std::integral_constant< bool, std::is_class< T >::value &&!std::is_convertible< T, RNGType >::value &&!std::is_convertible< T, typename RNGType::result_type >::value &&!std::is_convertible< T, KeyType >::value > is_seed_seq
void increment(std::array< T, K > &ctr, std::integral_constant< T, NSkip >)
Increment a counter by given steps.
CounterEngine(SeedSeq &seq, std::enable_if_t< is_seed_seq< SeedSeq >::value > *=nullptr)
friend std::basic_ostream< CharT, Traits > & operator<<(std::basic_ostream< CharT, Traits > &os, const CounterEngine< ResultType, Generator > &eng)
void rand(RNGType &rng, ArcsineDistribution< RealType > &distribution, std::size_t N, RealType *r)
#define MCKL_POP_CLANG_WARNING
typename CounterEngine< ResultType, Generator >::key_type type
const generator_type & generator() const
CounterEngine(result_type s=1)
static constexpr result_type max()
generator_type & generator()
std::size_t discard()
Discard the result.
friend std::basic_istream< CharT, Traits > & operator>>(std::basic_istream< CharT, Traits > &is, CounterEngine< ResultType, Generator > &eng)