32 #ifndef VSMC_RNG_THREEFRY_HPP 33 #define VSMC_RNG_THREEFRY_HPP 38 #define VSMC_DEFINE_RNG_THREEFRY_PARITY_CONSTANT(W, val) \ 39 template <typename T> \ 40 class ThreefryParityConstant<T, W> \ 41 : public std::integral_constant<T, UINT##W##_C(val)> \ 43 }; // class ThreefryParityConstant 45 #define VSMC_DEFINE_RNG_THREEFRY_ROTATE_CONSTANT(W, K, N, I, val) \ 46 template <typename T> \ 47 class ThreefryRotateConstant<T, K, N, I, W> \ 48 : public std::integral_constant<int, val> \ 50 }; // class ThreefryRotateConstant 52 #define VSMC_DEFINE_RNG_THREEFRY_PERMUTE_CONSTANT(K, I, val) \ 54 class ThreefryPermuteConstant<K, I> \ 55 : public std::integral_constant<std::size_t, val> \ 57 }; // class ThreefryPermuteConstant 61 #ifndef VSMC_RNG_THREEFRY_ROUNDS 62 #define VSMC_RNG_THREEFRY_ROUNDS 20 67 #ifndef VSMC_RNG_THREEFRY_VECTOR_LENGTH 68 #define VSMC_RNG_THREEFRY_VECTOR_LENGTH 4 77 template <typename T, int = std::numeric_limits<T>::digits>
83 template <typename T,
std::
size_t,
std::
size_t,
std::
size_t,
84 int =
std::numeric_limits<T>::digits>
237 template <
std::
size_t,
std::
size_t>
278 template <typename T,
std::
size_t K>
286 template <std::
size_t N, std::
size_t I>
293 template <
typename T, std::
size_t K, std::
size_t N,
bool = (N % 4 == 0)>
297 static void eval(std::array<T, K> &,
const std::array<T, K + 1> &) {}
300 template <
typename T, std::
size_t K, std::
size_t N>
304 static void eval(std::array<T, K> &state,
const std::array<T, K + 1> &par)
306 eval<0>(state, par, std::integral_constant<bool, 0 < K>());
307 state.back() +=
static_cast<T
>(s_);
311 static constexpr std::size_t s_ = N / 4;
313 template <std::
size_t>
315 std::array<T, K> &,
const std::array<T, K + 1> &, std::false_type)
319 template <std::
size_t I>
320 static void eval(std::array<T, K> &state,
const std::array<T, K + 1> &par,
323 std::get<I>(state) += std::get<(s_ + I) % (K + 1)>(par);
324 eval<I + 1>(state, par, std::integral_constant<bool, I + 1 < K>());
328 template <
typename T, std::
size_t K, std::
size_t N,
typename,
bool = (N > 0)>
332 static void eval(std::array<T, K> &) {}
335 template <
typename T, std::
size_t K, std::
size_t N,
typename Constants>
339 static void eval(std::array<T, K> &state)
341 eval<0>(state, std::integral_constant<bool, 1 < K>());
345 template <std::
size_t I>
346 using rotate =
typename Constants::template rotate<(N - 1) % 8, I>;
348 template <std::
size_t>
349 static void eval(std::array<T, K> &, std::false_type)
353 template <std::
size_t I>
354 static void eval(std::array<T, K> &state, std::true_type)
356 static constexpr
int L = rotate<I / 2>::value;
357 static constexpr
int R = std::numeric_limits<T>::digits - L;
359 T x = std::get<I + 1>(state);
360 std::get<I>(state) += x;
361 std::get<I + 1>(state) = (x << L) | (x >> R);
362 std::get<I + 1>(state) ^= std::get<I>(state);
363 eval<I + 2>(state, std::integral_constant<bool, I + 3 < K>());
367 template <
typename T, std::
size_t K, std::
size_t N,
bool = (N > 0)>
371 static void eval(std::array<T, K> &) {}
374 template <
typename T, std::
size_t K, std::
size_t N>
378 static void eval(std::array<T, K> &state)
380 std::array<T, K> tmp;
381 eval<0>(state, tmp, std::integral_constant<bool, 0 < K>());
382 std::memcpy(state.data(), tmp.data(),
sizeof(T) * K);
386 template <std::
size_t>
388 const std::array<T, K> &, std::array<T, K> &, std::false_type)
392 template <std::
size_t I>
394 const std::array<T, K> &state, std::array<T, K> &tmp, std::true_type)
398 std::get<I>(tmp) = std::get<J>(state);
399 eval<I + 1>(state, tmp, std::integral_constant<bool, I + 1 < K>());
403 template <
typename T, std::
size_t N>
407 static void eval(std::array<T, 2> &) {}
410 template <
typename T, std::
size_t N>
414 static void eval(std::array<T, 4> &state)
416 std::swap(std::get<1>(state), std::get<3>(state));
420 template <
typename T, std::
size_t N>
424 static void eval(std::array<T, 8> &state)
426 std::swap(std::get<3>(state), std::get<7>(state));
427 T x = std::get<0>(state);
428 std::get<0>(state) = std::get<2>(state);
429 std::get<2>(state) = std::get<4>(state);
430 std::get<4>(state) = std::get<6>(state);
431 std::get<6>(state) = x;
456 static_assert(std::is_unsigned<T>::value,
457 "**ThreefryGenerator** USED WITH T OTHER THAN UNSIGNED INTEGER TYPES");
459 static_assert(K != 0 && K % 2 == 0,
460 "**ThreefryGenerator** USED WITH K OTHER THAN MULTIPLES OF 2");
463 Rounds != 0,
"**ThreefryGenerator** USED WITH ROUNDS EQUAL TO ZERO");
469 static constexpr std::size_t
size() {
return sizeof(T) * K; }
473 std::copy(key.begin(), key.end(), par_.begin());
474 par_.back() = Constants::parity::value;
475 for (std::size_t i = 0; i != key.size(); ++i)
476 par_.back() ^= par_[i];
479 template <
typename ResultType>
481 std::array<ResultType, size() /
sizeof(ResultType)> &buffer)
const 484 std::array<T, K> state;
486 std::array<ResultType, size() /
sizeof(ResultType)> result;
491 generate<0>(buf.state, par_, std::true_type());
495 template <
typename ResultType>
497 std::array<ResultType, size() /
sizeof(ResultType)> *buffer)
const 500 std::array<T, K> state;
502 std::array<ResultType, size() /
sizeof(ResultType)> result;
505 for (std::size_t i = 0; i != n; ++i) {
508 generate<0>(buf.state, par_, std::true_type());
509 buffer[i] = buf.result;
516 return gen1.par_ == gen2.par_;
522 return !(gen1 == gen2);
525 template <
typename CharT,
typename Traits>
527 std::basic_ostream<CharT, Traits> &os,
538 template <
typename CharT,
typename Traits>
540 std::basic_istream<CharT, Traits> &is,
547 is >> std::ws >> gen_tmp.par_;
550 gen = std::move(gen_tmp);
556 template <std::
size_t>
557 void generate(std::array<T, K> &,
const std::array<T, K + 1> &,
558 std::false_type)
const 562 template <std::
size_t N>
563 void generate(std::array<T, K> &state,
const std::array<T, K + 1> &par,
564 std::true_type)
const 570 state, par, std::integral_constant<bool, (N < Rounds)>());
574 std::array<T, K + 1> par_;
579 template <
typename ResultType,
typename T = ResultType,
588 template <
typename ResultType>
593 template <
typename ResultType>
598 template <
typename ResultType>
603 template <
typename ResultType>
608 template <
typename ResultType>
613 template <
typename ResultType>
674 #endif // VSMC_RNG_THREEFRY_HPP static void eval(std::array< T, K > &state)
static void eval(std::array< T, K > &, const std::array< T, K+1 > &)
friend std::basic_ostream< CharT, Traits > & operator<<(std::basic_ostream< CharT, Traits > &os, const ThreefryGenerator< T, K, Rounds > &gen)
std::array< T, K > key_type
#define VSMC_RNG_THREEFRY_ROUNDS
ThreefryGenerator default rounds.
void increment(std::array< T, K > &ctr)
Increment a counter by one.
static void eval(std::array< T, 2 > &)
friend std::basic_istream< CharT, Traits > & operator>>(std::basic_istream< CharT, Traits > &is, ThreefryGenerator< T, K, Rounds > &gen)
Counter based RNG engine.
static void eval(std::array< T, 4 > &state)
#define VSMC_DEFINE_RNG_THREEFRY_PARITY_CONSTANT(W, val)
friend bool operator!=(const ThreefryGenerator< T, K, Rounds > &gen1, const ThreefryGenerator< T, K, Rounds > &gen2)
friend bool operator==(const ThreefryGenerator< T, K, Rounds > &gen1, const ThreefryGenerator< T, K, Rounds > &gen2)
static void eval(std::array< T, K > &)
Default Threefry constants.
void reset(const key_type &key)
#define VSMC_RNG_THREEFRY_VECTOR_LENGTH
ThreefryGenerator default vector length.
static void eval(std::array< T, 8 > &state)
static void eval(std::array< T, K > &)
#define VSMC_DEFINE_RNG_THREEFRY_ROTATE_CONSTANT(W, K, N, I, val)
void operator()(ctr_type &ctr, std::array< ResultType, size()/sizeof(ResultType)> &buffer) const
static void eval(std::array< T, K > &state)
void operator()(ctr_type &ctr, std::size_t n, std::array< ResultType, size()/sizeof(ResultType)> *buffer) const
static void eval(std::array< T, K > &state, const std::array< T, K+1 > &par)
static constexpr std::size_t size()
void swap(StateMatrixBase< Layout, Dim, T > &state1, StateMatrixBase< Layout, Dim, T > &state2) noexcept
Swap two StateMatrixBase objects.
std::array< T, K > ctr_type
#define VSMC_DEFINE_RNG_THREEFRY_PERMUTE_CONSTANT(K, I, val)