32 #ifndef VSMC_RNG_THREEFRY_HPP 33 #define VSMC_RNG_THREEFRY_HPP 38 #define VSMC_DEFINE_RNG_THREEFRY_ROTATE_CONSTANT(T, K, N, I, val) \ 40 class ThreefryRotateConstant<T, K, N, I> \ 41 : public std::integral_constant<int, val> \ 43 }; // class ThreefryRotateConstant 47 #ifndef VSMC_RNG_THREEFRY_ROUNDS 48 #define VSMC_RNG_THREEFRY_ROUNDS 20 53 #ifndef VSMC_RNG_THREEFRY_VECTOR_LENGTH 54 #define VSMC_RNG_THREEFRY_VECTOR_LENGTH 4 66 template <
typename T,
template <
typename>
class SIMD>
73 :
public std::integral_constant<std::uint32_t, UINT32_C(0x1BD11BDA)>
79 :
public std::integral_constant<std::uint64_t,
80 UINT64_C(0x1BD11BDAA9FC1A22)>
84 template <
typename, std::
size_t, std::
size_t, std::
size_t>
87 template <
typename T,
template <
typename>
class SIMD, std::size_t K,
88 std::size_t N, std::size_t I>
148 template <typename T, std::
size_t K>
152 static void eval(
const std::array<T, K> &key, std::array<T, K + 1> &par)
155 par_xor<0>(key, par, std::integral_constant<bool, 0 < K>());
159 template <std::
size_t>
161 const std::array<T, K> &, std::array<T, K + 1> &, std::false_type)
165 template <std::
size_t N>
167 const std::array<T, K> &key, std::array<T, K + 1> &par, std::true_type)
169 std::get<N>(par) = std::get<N>(key);
170 par.back() ^= std::get<N>(key);
171 par_xor<N + 1>(key, par, std::integral_constant<bool, N + 1 < K>());
175 template <
typename T>
180 template <
typename T,
template <
typename>
class SIMD>
185 template <
typename T,
int R>
195 template <
typename T, std::
size_t K, std::
size_t N,
bool = (N > 0)>
199 static void eval(std::array<T, K> &) {}
202 template <
typename T, std::
size_t N>
206 static void eval(std::array<T, 2> &state)
208 std::get<0>(state) += std::get<1>(state);
211 0>::value>::eval(std::get<1>(state));
212 std::get<1>(state) ^= std::get<0>(state);
216 static constexpr std::size_t r_ = (N - 1) % 8;
219 template <
typename T, std::
size_t N>
223 static void eval(std::array<T, 4> &state)
225 std::get<0>(state) += std::get<i0_>(state);
226 std::get<i0_>(state) =
228 0>::value>::eval(std::get<i0_>(state));
229 std::get<i0_>(state) ^= std::get<0>(state);
231 std::get<2>(state) += std::get<i2_>(state);
232 std::get<i2_>(state) =
234 1>::value>::eval(std::get<i2_>(state));
235 std::get<i2_>(state) ^= std::get<2>(state);
239 static constexpr std::size_t i0_ = N % 2 ? 1 : 3;
240 static constexpr std::size_t i2_ = N % 2 ? 3 : 1;
241 static constexpr std::size_t r_ = (N - 1) % 8;
244 template <
typename T, std::
size_t Inc>
246 :
public std::integral_constant<T, static_cast<T>(Inc)>
250 template <
typename T,
template <
typename>
class SIMD, std::size_t Inc>
255 template <
typename T, std::
size_t K, std::
size_t N,
bool = (N % 4 == 0)>
259 static void eval(std::array<T, K> &,
const std::array<T, K + 1> &) {}
262 template <
typename T, std::
size_t N>
266 static void eval(std::array<T, 2> &state,
const std::array<T, 3> &par)
268 std::get<0>(state) += std::get<i0_>(par);
269 std::get<1>(state) += std::get<i1_>(par);
274 static constexpr std::size_t inc_ = N / 4;
275 static constexpr std::size_t i0_ = (inc_ + 0) % 3;
276 static constexpr std::size_t i1_ = (inc_ + 1) % 3;
279 template <
typename T, std::
size_t N>
283 static void eval(std::array<T, 4> &state,
const std::array<T, 5> &par)
285 std::get<0>(state) += std::get<i0_>(par);
286 std::get<1>(state) += std::get<i1_>(par);
287 std::get<2>(state) += std::get<i2_>(par);
288 std::get<3>(state) += std::get<i3_>(par);
293 static constexpr std::size_t inc_ = N / 4;
294 static constexpr std::size_t i0_ = (inc_ + 0) % 5;
295 static constexpr std::size_t i1_ = (inc_ + 1) % 5;
296 static constexpr std::size_t i2_ = (inc_ + 2) % 5;
297 static constexpr std::size_t i3_ = (inc_ + 3) % 5;
308 static_assert(std::is_unsigned<ResultType>::value,
309 "**ThreefryGenerator** USED WITH ResultType OTHER THAN UNSIGNED " 314 "**ThreefryGenerator** USED WITH ResultType OF SIZE OTHER THAN 32 OR " 317 static_assert(K == 2 || K == 4,
318 "**ThreefryGenerator** USED WITH K OTHER THAN 2 OR 4");
325 static constexpr std::size_t
size() {
return K; }
331 std::array<ResultType, K + 1> par;
335 generate<0>(buffer, par, std::true_type());
344 std::array<ResultType, K + 1> par;
347 for (std::size_t i = 0; i != n; ++i)
348 generate<0>(buffer[i], par, std::true_type());
352 template <std::
size_t>
353 void generate(std::array<ResultType, K> &,
354 const std::array<ResultType, K + 1> &, std::false_type)
const 358 template <std::
size_t N>
359 void generate(std::array<ResultType, K> &state,
360 const std::array<ResultType, K + 1> &par, std::true_type)
const 365 state, par, std::integral_constant<bool, (N < Rounds)>());
404 template <
typename ResultType, std::
size_t K>
408 static void eval(
const std::array<ResultType, K + 1> &p,
411 pack<0>(p, par, std::integral_constant<bool, 0 < K + 1>());
415 template <std::
size_t>
416 static void pack(
const std::array<ResultType, K + 1> &,
421 template <std::
size_t N>
422 static void pack(
const std::array<ResultType, K + 1> &p,
425 std::get<N>(par).set1(std::get<N>(p));
426 pack<N + 1>(p, par, std::integral_constant<bool, N + 1 < K + 1>());
430 template <
typename ResultType, std::
size_t K>
434 static void eval(std::array<ResultType, K> &ctr,
440 pack<0>(ctr_block, state, std::integral_constant<bool, 0 < K>());
444 template <std::
size_t N>
445 static void pack(
const std::array<std::array<ResultType, K>,
451 template <std::
size_t N>
452 static void pack(
const std::array<std::array<ResultType, K>,
456 set<N>(ctr_block, state,
457 std::integral_constant<std::size_t, sizeof(ResultType)>());
459 ctr_block, state, std::integral_constant<bool, N + 1 < K>());
462 template <std::
size_t N>
463 static void set(
const std::array<std::array<ResultType, K>,
465 std::array<M128I<ResultType>, K> &state,
466 std::integral_constant<std::size_t, 4>)
468 std::get<N>(state).
set(std::get<N>(std::get<0>(ctr_block)),
469 std::get<N>(std::get<1>(ctr_block)),
470 std::get<N>(std::get<2>(ctr_block)),
471 std::get<N>(std::get<3>(ctr_block)));
474 template <std::
size_t N>
475 static void set(
const std::array<std::array<ResultType, K>,
477 std::array<M128I<ResultType>, K> &state,
478 std::integral_constant<std::size_t, 8>)
480 std::get<N>(state).
set(std::get<N>(std::get<0>(ctr_block)),
481 std::get<N>(std::get<1>(ctr_block)));
493 static_assert(std::is_unsigned<ResultType>::value,
494 "**ThreefryGeneratorSSE2** USED WITH ResultType OTHER THAN UNSIGNED " 499 "**ThreefryGeneratorSSE2** USED WITH ResultType OF SIZE OTHER THAN " 502 static_assert(K == 2 || K == 4,
503 "**ThreefryGeneratorSSE2** USED WITH K OTHER THAN 2 OR 4");
510 static constexpr std::size_t
size()
518 std::array<ResultType, size()> &buffer)
const 521 std::array<M128I<ResultType>, K> state;
522 std::array<ResultType, size()> result;
525 std::array<ResultType, K + 1> p;
526 std::array<M128I<ResultType>, K + 1> par;
530 generate<0>(buf.state, par, std::true_type());
535 std::array<ResultType, size()> *buffer)
const 541 std::array<M128I<ResultType>, K> state;
542 std::array<ResultType, size()> result;
545 std::array<ResultType, K + 1> p;
546 std::array<M128I<ResultType>, K + 1> par;
549 for (std::size_t i = 0; i != n; ++i) {
551 generate<0>(buf.state, par, std::true_type());
552 buffer[i] = buf.result;
557 template <std::
size_t>
563 template <std::
size_t N>
570 state, par, std::integral_constant<bool, (N < Rounds)>());
605 #endif // VSMC_HAS_SSE2 612 template <
typename ResultType, std::
size_t K>
616 static void eval(
const std::array<ResultType, K + 1> &p,
619 pack<0>(p, par, std::integral_constant<bool, 0 < K + 1>());
623 template <std::
size_t>
624 static void pack(
const std::array<ResultType, K + 1> &,
629 template <std::
size_t N>
630 static void pack(
const std::array<ResultType, K + 1> &p,
633 std::get<N>(par).set1(std::get<N>(p));
634 pack<N + 1>(p, par, std::integral_constant<bool, N + 1 < K + 1>());
638 template <
typename ResultType, std::
size_t K>
642 static void eval(std::array<ResultType, K> &ctr,
648 pack<0>(ctr_block, state, std::integral_constant<bool, 0 < K>());
652 template <std::
size_t N>
653 static void pack(
const std::array<std::array<ResultType, K>,
659 template <std::
size_t N>
660 static void pack(
const std::array<std::array<ResultType, K>,
664 set<N>(ctr_block, state,
665 std::integral_constant<std::size_t, sizeof(ResultType)>());
667 ctr_block, state, std::integral_constant<bool, N + 1 < K>());
670 template <std::
size_t N>
671 static void set(
const std::array<std::array<ResultType, K>,
673 std::array<M256I<ResultType>, K> &state,
674 std::integral_constant<std::size_t, 4>)
676 std::get<N>(state).
set(std::get<N>(std::get<0>(ctr_block)),
677 std::get<N>(std::get<1>(ctr_block)),
678 std::get<N>(std::get<2>(ctr_block)),
679 std::get<N>(std::get<3>(ctr_block)),
680 std::get<N>(std::get<4>(ctr_block)),
681 std::get<N>(std::get<5>(ctr_block)),
682 std::get<N>(std::get<6>(ctr_block)),
683 std::get<N>(std::get<7>(ctr_block)));
686 template <std::
size_t N>
687 static void set(
const std::array<std::array<ResultType, K>,
689 std::array<M256I<ResultType>, K> &state,
690 std::integral_constant<std::size_t, 8>)
692 std::get<N>(state).
set(std::get<N>(std::get<0>(ctr_block)),
693 std::get<N>(std::get<1>(ctr_block)),
694 std::get<N>(std::get<2>(ctr_block)),
695 std::get<N>(std::get<3>(ctr_block)));
707 static_assert(std::is_unsigned<ResultType>::value,
708 "**ThreefryGeneratorAVX2** USED WITH ResultType OTHER THAN UNSIGNED " 713 "**ThreefryGeneratorAVX2** USED WITH ResultType OF SIZE OTHER THAN " 716 static_assert(K == 2 || K == 4,
717 "**ThreefryGeneratorAVX2** USED WITH K OTHER THAN 2 OR 4");
724 static constexpr std::size_t
size()
732 std::array<ResultType, size()> &buffer)
const 735 std::array<M256I<ResultType>, K> state;
736 std::array<ResultType, size()> result;
739 std::array<ResultType, K + 1> p;
740 std::array<M256I<ResultType>, K + 1> par;
744 generate<0>(buf.state, par, std::true_type());
749 std::array<ResultType, size()> *buffer)
const 755 std::array<M256I<ResultType>, K> state;
756 std::array<ResultType, size()> result;
759 std::array<ResultType, K + 1> p;
760 std::array<M256I<ResultType>, K + 1> par;
763 for (std::size_t i = 0; i != n; ++i) {
765 generate<0>(buf.state, par, std::true_type());
766 buffer[i] = buf.result;
771 template <std::
size_t>
777 template <std::
size_t N>
784 state, par, std::integral_constant<bool, (N < Rounds)>());
819 #endif // VSMC_HAS_AVX2 823 #endif // VSMC_RNG_THREEFRY_HPP static void eval(std::array< T, K > &, const std::array< T, K+1 > &)
std::array< ResultType, K > key_type
void operator()(ctr_type &ctr, const key_type &key, std::array< ResultType, size()> &buffer) const
void operator()(ctr_type &ctr, const key_type &key, std::size_t n, ctr_type *buffer) const
#define VSMC_RNG_THREEFRY_ROUNDS
ThreefryGenerator default rounds.
Using __mm256i as integer vector.
std::array< ResultType, K > ctr_type
static constexpr std::size_t size()
void increment(std::array< T, K > &ctr)
Increment a counter by one.
Using __m128i as integer vector.
static constexpr std::size_t size()
static T eval(const T &x)
Counter based RNG engine.
static void eval(std::array< ResultType, K > &ctr, std::array< M128I< ResultType >, K > &state)
Threefry RNG generator using AVX2.
static void eval(const std::array< T, K > &key, std::array< T, K+1 > &par)
static constexpr std::size_t size()
std::array< ResultType, K > ctr_type
static constexpr std::size_t size()
#define VSMC_RNG_THREEFRY_VECTOR_LENGTH
ThreefryGenerator default vector length.
std::array< ResultType, K > key_type
static void eval(std::array< T, K > &)
void operator()(ctr_type &ctr, const key_type &key, std::size_t n, std::array< ResultType, size()> *buffer) const
std::array< ResultType, K > ctr_type
void reset(const key_type &)
void operator()(ctr_type &ctr, const key_type &key, std::size_t n, std::array< ResultType, size()> *buffer) const
static constexpr std::size_t size()
void operator()(ctr_type &ctr, const key_type &key, std::array< ResultType, size()> &buffer) const
static void eval(std::array< T, 4 > &state)
static void eval(std::array< ResultType, K > &ctr, std::array< M256I< ResultType >, K > &state)
void reset(const key_type &)
static void eval(const std::array< ResultType, K+1 > &p, std::array< M128I< ResultType >, K+1 > &par)
static void eval(std::array< T, 2 > &state, const std::array< T, 3 > &par)
std::array< ResultType, K > key_type
void reset(const key_type &)
static void eval(std::array< T, 2 > &state)
void operator()(ctr_type &ctr, const key_type &key, ctr_type &buffer) const
Threefry RNG generator using SSE2.
#define VSMC_DEFINE_RNG_THREEFRY_ROTATE_CONSTANT(T, K, N, I, val)
static void eval(std::array< T, 4 > &state, const std::array< T, 5 > &par)
static void eval(const std::array< ResultType, K+1 > &p, std::array< M256I< ResultType >, K+1 > &par)