32 #ifndef VSMC_RNG_COUNTER_HPP    33 #define VSMC_RNG_COUNTER_HPP    43 template <std::
size_t, 
typename T, std::
size_t K>
    48 template <std::
size_t N, 
typename T, std::
size_t K>
    51     if (++std::get<N>(ctr) != 0)
    54     increment_single<N + 1>(ctr, std::integral_constant<bool, N + 1 < K>());
    61 template <
typename T, std::
size_t K>
    64     internal::increment_single<0>(ctr, std::true_type());
    69 template <
typename T, std::
size_t K, T NSkip>
    70 inline void increment(std::array<T, K> &ctr, std::integral_constant<T, NSkip>)
    72     if (ctr.front() < std::numeric_limits<T>::max 
VSMC_MNE() - NSkip) {
    76         internal::increment_single<1>(
    77             ctr, std::integral_constant<bool, 1 < K>());
    83 template <
typename T, std::
size_t K>
    84 inline void increment(std::array<T, K> &ctr, T nskip)
    86     if (ctr.front() < std::numeric_limits<T>::max 
VSMC_MNE() - nskip) {
    90         internal::increment_single<1>(
    91             ctr, std::integral_constant<bool, 1 < K>());
    98 template <std::
size_t, 
typename T, std::
size_t K, std::
size_t Blocks>
   100     std::array<std::array<T, K>, Blocks> &, std::false_type)
   104 template <std::
size_t B, 
typename T, std::
size_t K, std::
size_t Blocks>
   106     std::array<std::array<T, K>, Blocks> &ctr_block, std::true_type)
   108     std::get<B>(ctr_block) = ctr;
   109     increment_block_set<B + 1>(
   110         ctr, ctr_block, std::integral_constant<bool, B + 1 < Blocks>());
   113 template <std::
size_t, 
typename T, std::
size_t K, std::
size_t Blocks>
   115     std::array<std::array<T, K>, Blocks> &, std::false_type)
   119 template <std::
size_t B, 
typename T, std::
size_t K, std::
size_t Blocks>
   121     std::array<std::array<T, K>, Blocks> &ctr_block, std::true_type)
   123     increment(std::get<B>(ctr_block), std::integral_constant<T, B + 1>());
   124     increment_block<B + 1>(
   125         ctr, ctr_block, std::integral_constant<bool, B + 1 < Blocks>());
   128 template <std::
size_t, 
typename T, std::
size_t K, std::
size_t Blocks>
   130     std::array<std::array<T, K>, Blocks> &, std::false_type)
   134 template <std::
size_t B, 
typename T, std::
size_t K, std::
size_t Blocks>
   136     std::array<std::array<T, K>, Blocks> &ctr_block, std::true_type)
   138     std::get<B>(ctr_block).front() += B + 1;
   139     increment_block_safe<B + 1>(
   140         ctr, ctr_block, std::integral_constant<bool, B + 1 < Blocks>());
   148 template <
typename T, std::
size_t K, std::
size_t Blocks>
   150     std::array<T, K> &ctr, std::array<std::array<T, K>, Blocks> &ctr_block)
   152     internal::increment_block_set<0>(
   153         ctr, ctr_block, std::integral_constant<bool, 0 < Blocks>());
   155         std::numeric_limits<T>::max 
VSMC_MNE() - 
static_cast<T
>(Blocks)) {
   156         internal::increment_block_safe<0>(
   157             ctr, ctr_block, std::integral_constant<bool, 0 < Blocks>());
   159         internal::increment_block<0>(
   160             ctr, ctr_block, std::integral_constant<bool, 0 < Blocks>());
   162     ctr = ctr_block.back();
   168 template <
typename T, std::
size_t K>
   170     std::array<T, K> *ctr_block, std::false_type)
   172     for (std::size_t i = 0; i != n; ++i)
   178 template <
typename T, std::
size_t K>
   180     std::array<T, K> *ctr_block, std::true_type)
   182     const std::size_t Blocks = M256I<T>::size() / K;
   183     const std::size_t m = n / Blocks;
   184     const std::size_t l = n % Blocks;
   186     std::array<std::array<T, K>, Blocks> cb;
   187     increment_block_set<0>(ctr, cb, std::true_type());
   189     if (reinterpret_cast<std::uintptr_t>(ctr_block) % 32 == 0) {
   190         for (std::size_t i = 0; i != m; ++i, ctr_block += Blocks)
   191             c.store_a(ctr_block);
   193         for (std::size_t i = 0; i != m; ++i, ctr_block += Blocks)
   194             c.store_u(ctr_block);
   196     for (std::size_t i = 0; i != l; ++i)
   200 template <
typename T, std::
size_t K>
   202     const std::array<T, K> &ctr, std::size_t n, std::array<T, K> *ctr_block)
   205         std::integral_constant<
bool, M256I<T>::size() % K == 0>());
   210 template <
typename T, std::
size_t K>
   212     std::array<T, K> *ctr_block, std::true_type)
   214     const std::size_t Blocks = M128I<T>::size() / K;
   215     const std::size_t m = n / Blocks;
   216     const std::size_t l = n % Blocks;
   218     std::array<std::array<T, K>, Blocks> cb;
   219     increment_block_set<0>(ctr, cb, std::true_type());
   221     if (reinterpret_cast<std::uintptr_t>(ctr_block) % 16 == 0) {
   222         for (std::size_t i = 0; i != m; ++i, ctr_block += Blocks)
   223             c.store_a(ctr_block);
   225         for (std::size_t i = 0; i != m; ++i, ctr_block += Blocks)
   226             c.store_u(ctr_block);
   228     for (std::size_t i = 0; i != l; ++i)
   232 template <
typename T, std::
size_t K>
   234     const std::array<T, K> &ctr, std::size_t n, std::array<T, K> *ctr_block)
   237         std::integral_constant<
bool, M128I<T>::size() % K == 0>());
   240 #else // VSMC_HAS_SSE2   242 template <
typename T, std::
size_t K>
   244     const std::array<T, K> &ctr, std::size_t n, std::array<T, K> *ctr_block)
   249 #endif // VSMC_HAS_SSE2   256 template <
typename T, std::
size_t K>
   258     std::array<T, K> &ctr, std::size_t n, std::array<T, K> *ctr_block)
   268     if (k < m && l < m - k) {
   270         const T p = 
static_cast<T
>(n);
   271         for (T i = 0; i != p; ++i)
   272             ctr_block[i].front() += i;
   275         const T p = 
static_cast<T
>(n);
   276         for (T i = 0; i != p; ++i)
   279         for (std::size_t i = 0; i != n; ++i) {
   284     ctr = ctr_block[n - 1];
   289 template <
typename Generator>
   299     template <
typename SeedSeq>
   317     template <
typename SeedSeq>
   322         seq.generator(key_.begin(), key_.end());
   351             generator_(ctr_, key_, buffer_);
   355         return buffer_[index_++];
   361             for (std::size_t i = 0; i != n; ++i)
   367             static_cast<std::size_t
>(
reinterpret_cast<std::uintptr_t
>(r) % 32);
   370             for (std::size_t i = 0; i != p; ++i)
   376         const std::size_t q = generator_(ctr_, key_, n, r);
   380         const std::size_t m = n / M_;
   381         std::array<result_type, M_> *s =
   382             reinterpret_cast<std::array<result_type, M_> *
>(r);
   383         for (std::size_t i = 0; i != m; ++i)
   384             generator_(ctr_, key_, s[i]);
   388         for (std::size_t i = 0; i != n; ++i)
   394         std::size_t n = 
static_cast<std::size_t
>(nskip);
   395         if (index_ + n <= M_) {
   408         increment(ctr_, static_cast<result_type>(n / M_));
   416         return std::numeric_limits<result_type>::min 
VSMC_MNE();
   421         return std::numeric_limits<result_type>::max 
VSMC_MNE();
   427         if (eng1.buffer_ != eng2.buffer_)
   429         if (eng1.ctr_ != eng2.ctr_)
   431         if (eng1.key_ != eng2.key_)
   433         if (eng1.index_ != eng2.index_)
   441         return !(eng1 == eng2);
   444     template <
typename CharT, 
typename Traits>
   446         std::basic_ostream<CharT, Traits> &os,
   452         os << eng.buffer_ << 
' ';
   453         os << eng.ctr_ << 
' ';
   454         os << eng.key_ << 
' ';
   460     template <
typename CharT, 
typename Traits>
   468         is >> std::ws >> eng_tmp.buffer_;
   469         is >> std::ws >> eng_tmp.ctr_;
   470         is >> std::ws >> eng_tmp.key_;
   471         is >> std::ws >> eng_tmp.index_;
   474             eng_tmp.generator_.reset(eng_tmp.key_);
   475             eng = std::move(eng_tmp);
   482     static constexpr std::size_t M_ = Generator::size();
   484     std::array<result_type, M_> buffer_;
   487     Generator generator_;
   493         generator_.reset(key_);
   498 template <
typename Generator>
   507 #endif // VSMC_RNG_COUNTER_HPP 
const ctr_type & ctr() const 
 
const key_type & key() const 
 
friend bool operator==(const CounterEngine< Generator > &eng1, const CounterEngine< Generator > &eng2)
 
void increment(std::array< T, K > &ctr)
Increment a counter by one. 
 
typename Generator::key_type key_type
 
typename Generator::ctr_type ctr_type
 
void increment_block(std::array< T, K > &, std::array< std::array< T, K >, Blocks > &, std::false_type)
 
Counter based RNG engine. 
 
CounterEngine(SeedSeq &seq, typename std::enable_if< internal::is_seed_seq< SeedSeq, result_type, key_type, CounterEngine< Generator >>::value >::type *=nullptr)
 
void rng_rand(RNGType &rng, BernoulliDistribution< IntType > &dist, std::size_t n, IntType *r)
 
void increment_block_set(const std::array< T, K > &, std::array< std::array< T, K >, Blocks > &, std::false_type)
 
void operator()(std::size_t n, result_type *r)
 
CounterEngine(result_type s=0)
 
void key(const key_type &k)
 
friend std::basic_ostream< CharT, Traits > & operator<<(std::basic_ostream< CharT, Traits > &os, const CounterEngine< Generator > &eng)
 
typename Generator::result_type result_type
 
void ctr(const ctr_type &c)
 
void seed(SeedSeq &seq, typename std::enable_if< internal::is_seed_seq< SeedSeq, result_type, key_type >::value >::type *=nullptr)
 
friend bool operator!=(const CounterEngine< Generator > &eng1, const CounterEngine< Generator > &eng2)
 
CounterEngine(const key_type &k)
 
void seed(const key_type &k)
 
void discard(result_type nskip)
 
friend std::basic_istream< CharT, Traits > & operator>>(std::basic_istream< CharT, Traits > &is, CounterEngine< Generator > &eng)
 
void increment_block_safe(std::array< T, K > &, std::array< std::array< T, K >, Blocks > &, std::false_type)
 
void increment_single(std::array< T, K > &, std::false_type)