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() - 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() - 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>());
   154     if (ctr.front() < std::numeric_limits<T>::max() - 
static_cast<T
>(Blocks)) {
   155         internal::increment_block_safe<0>(
   156             ctr, ctr_block, std::integral_constant<bool, 0 < Blocks>());
   158         internal::increment_block<0>(
   159             ctr, ctr_block, std::integral_constant<bool, 0 < Blocks>());
   161     ctr = ctr_block.back();
   167 template <
typename T, std::
size_t K>
   169     std::array<T, K> *ctr_block, std::false_type)
   171     for (std::size_t i = 0; i != n; ++i)
   177 template <
typename T, std::
size_t K>
   179     std::array<T, K> *ctr_block, std::true_type)
   182     const std::size_t m = n / Blocks;
   183     const std::size_t l = n % Blocks;
   185     std::array<std::array<T, K>, Blocks> cb;
   186     increment_block_set<0>(ctr, cb, std::true_type());
   188     if (reinterpret_cast<std::uintptr_t>(ctr_block) % 32 == 0) {
   189         for (std::size_t i = 0; i != m; ++i, ctr_block += Blocks)
   192         for (std::size_t i = 0; i != m; ++i, ctr_block += Blocks)
   195     for (std::size_t i = 0; i != l; ++i)
   199 template <
typename T, std::
size_t K>
   201     const std::array<T, K> &ctr, std::size_t n, std::array<T, K> *ctr_block)
   209 template <
typename T, std::
size_t K>
   211     std::array<T, K> *ctr_block, std::true_type)
   214     const std::size_t m = n / Blocks;
   215     const std::size_t l = n % Blocks;
   217     std::array<std::array<T, K>, Blocks> cb;
   218     increment_block_set<0>(ctr, cb, std::true_type());
   220     if (reinterpret_cast<std::uintptr_t>(ctr_block) % 16 == 0) {
   221         for (std::size_t i = 0; i != m; ++i, ctr_block += Blocks)
   224         for (std::size_t i = 0; i != m; ++i, ctr_block += Blocks)
   227     for (std::size_t i = 0; i != l; ++i)
   231 template <
typename T, std::
size_t K>
   233     const std::array<T, K> &ctr, std::size_t n, std::array<T, K> *ctr_block)
   239 #else // VSMC_HAS_SSE2   241 template <
typename T, std::
size_t K>
   243     const std::array<T, K> &ctr, std::size_t n, std::array<T, K> *ctr_block)
   248 #endif // VSMC_HAS_SSE2   255 template <
typename T, std::
size_t K>
   257     std::array<T, K> &ctr, std::size_t n, std::array<T, K> *ctr_block)
   267     if (k < m && l < m - k) {
   269         const T p = 
static_cast<T
>(n);
   270         for (T i = 0; i != p; ++i)
   271             ctr_block[i].front() += i;
   274         const T p = 
static_cast<T
>(n);
   275         for (T i = 0; i != p; ++i)
   278         for (std::size_t i = 0; i != n; ++i) {
   283     ctr = ctr_block[n - 1];
   288 template <
typename Generator>
   298     template <
typename SeedSeq>
   316     template <
typename SeedSeq>
   321         seq.generator(key_.begin(), key_.end());
   350             generator_(ctr_, key_, buffer_);
   354         return buffer_[index_++];
   359         const std::size_t remain = M_ - index_;
   362             std::memcpy(r, buffer_.data() + index_, 
sizeof(
result_type) * n);
   367         std::memcpy(r, buffer_.data() + index_, 
sizeof(
result_type) * remain);
   372         const std::size_t k = 1024 / M_;
   374             const std::size_t m = (n / M_) / k;
   375             const std::size_t l = (n / M_) % k;
   376             alignas(32) std::array<result_type, M_> buffer[k];
   377             for (std::size_t i = 0; i != m; ++i) {
   378                 generator_(ctr_, key_, k, buffer);
   379                 std::memcpy(r, buffer, 
sizeof(
result_type) * M_ * k);
   383             generator_(ctr_, key_, l, buffer);
   384             std::memcpy(r, buffer, 
sizeof(
result_type) * M_ * l);
   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();
   421         return std::numeric_limits<result_type>::max();
   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     alignas(32) std::array<result_type, M_> buffer_;
   488     Generator generator_;
   493         generator_.reset(key_);
   498 template <
typename Generator>
   507 #endif // VSMC_RNG_COUNTER_HPP 
Using __mm256i as integer vector. 
 
const ctr_type & ctr() const 
 
const key_type & key() const 
 
friend bool operator==(const CounterEngine< Generator > &eng1, const CounterEngine< Generator > &eng2)
 
void store_a(T *mem) const 
 
void increment(std::array< T, K > &ctr)
Increment a counter by one. 
 
typename Generator::key_type key_type
 
static constexpr std::size_t size()
 
typename Generator::ctr_type ctr_type
 
void rng_rand(RNGType &rng, BetaDistribution< RealType > &dist, std::size_t n, RealType *r)
 
void increment_block(std::array< T, K > &, std::array< std::array< T, K >, Blocks > &, std::false_type)
 
Counter based RNG engine. 
 
void store_u(T *mem) const 
 
CounterEngine(SeedSeq &seq, typename std::enable_if< internal::is_seed_seq< SeedSeq, result_type, key_type, CounterEngine< Generator >>::value >::type *=nullptr)
 
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)
 
static constexpr result_type max()
 
friend std::basic_ostream< CharT, Traits > & operator<<(std::basic_ostream< CharT, Traits > &os, const CounterEngine< Generator > &eng)
 
static constexpr result_type min()
 
typename Generator::result_type result_type
 
static constexpr std::size_t size()
 
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 store_u(T *mem) const 
 
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 store_a(T *mem) const 
 
void increment_single(std::array< T, K > &, std::false_type)