32 #ifndef VSMC_RNG_PHILOX_HPP 33 #define VSMC_RNG_PHILOX_HPP 42 #define VSMC_DEFINE_RNG_PHILOX_WELY_CONSTANT(T, I, val) \ 44 class PhiloxWeylConstant<T, I> : public std::integral_constant<T, val> \ 46 }; // class PhiloxWeylConstant 48 #define VSMC_DEFINE_RNG_PHILOX_ROUND_CONSTANT(T, K, I, val) \ 50 class PhiloxRoundConstant<T, K, I> \ 51 : public std::integral_constant<T, val> \ 53 }; // PhiloxRoundConstant 57 #ifndef VSMC_RNG_PHILOX_ROUNDS 58 #define VSMC_RNG_PHILOX_ROUNDS 10 63 #ifndef VSMC_RNG_PHILOX_VECTOR_LENGTH 64 #define VSMC_RNG_PHILOX_VECTOR_LENGTH 4 73 template <
typename, std::
size_t>
84 template <typename,
std::
size_t,
std::
size_t>
103 template <
std::
size_t K,
std::
size_t I>
107 static_cast<std::uint64_t>(
115 template <std::
size_t K, std::
size_t I>
118 unsigned VSMC_INT128 prod =
119 static_cast<unsigned VSMC_INT128
>(b) *
120 static_cast<unsigned VSMC_INT128>(
126 #elif defined(VSMC_MSVC) // VSMC_HAS_INT128 128 template <std::
size_t K, std::
size_t I>
134 #else // VSMC_HAS_INT128 136 template <std::
size_t K, std::
size_t I>
140 const unsigned whalf = 32;
153 const std::uint64_t ahbl_albh = ((ahbl & lomask) + (albh & lomask));
155 hi = ahi * bhi + (ahbl >> whalf) + (albh >> whalf);
156 hi += ahbl_albh >> whalf;
157 hi += ((lo >> whalf) < (ahbl_albh & lomask));
160 #endif // VSMC_HAS_INT128 162 template <
typename T, std::
size_t K, std::
size_t N,
bool = (N > 1)>
166 static void eval(std::array<T, K / 2> &) {}
169 template <
typename T, std::
size_t N>
173 static void eval(std::array<T, 1> &par)
179 template <
typename T, std::
size_t N>
183 static void eval(std::array<T, 2> &par)
190 template <
typename T, std::
size_t K, std::
size_t N,
bool = (N > 0)>
194 static void eval(std::array<T, K> &,
const std::array<T, K / 2> &) {}
197 template <
typename T, std::
size_t N>
201 static void eval(std::array<T, 2> &state,
const std::array<T, 1> &par)
205 philox_hilo<2, 0>(std::get<0>(state), hi, lo);
206 hi ^= std::get<0>(par);
207 std::get<0>(state) = hi ^ std::get<1>(state);
208 std::get<1>(state) = lo;
212 template <
typename T, std::
size_t N>
216 static void eval(std::array<T, 4> &state,
const std::array<T, 2> &par)
222 philox_hilo<4, 1>(std::get<2>(state), hi0, lo1);
223 philox_hilo<4, 0>(std::get<0>(state), hi2, lo3);
225 hi0 ^= std::get<0>(par);
226 hi2 ^= std::get<1>(par);
227 std::get<0>(state) = hi0 ^ std::get<1>(state);
228 std::get<1>(state) = lo1;
229 std::get<2>(state) = hi2 ^ std::get<3>(state);
230 std::get<3>(state) = lo3;
242 static_assert(std::is_unsigned<ResultType>::value,
243 "**PhiloxGenerator** USED WITH ResultType OTHER THAN UNSIGNED INTEGER " 248 "**PhiloxGenerator** USED WITH ResultType OF SIZE OTHER THAN 32 OR 64 " 252 K == 2 || K == 4,
"**PhiloxGenerator** USED WITH K OTHER THAN 2 OR 4");
259 static constexpr std::size_t
size() {
return K; }
268 generate<0>(buffer, par, std::true_type());
275 for (std::size_t i = 0; i != n; ++i) {
277 generate<0>(buffer[i], par, std::true_type());
282 template <std::
size_t>
287 template <std::
size_t N>
293 state, par, std::integral_constant<bool, (N < Rounds)>());
329 #endif // VSMC_RNG_PHILOX_HPP
#define VSMC_DEFINE_RNG_PHILOX_ROUND_CONSTANT(T, K, I, val)
static void eval(std::array< T, 4 > &state, const std::array< T, 2 > &par)
static void eval(std::array< T, 2 > &state, const std::array< T, 1 > &par)
static constexpr std::size_t size()
void increment(std::array< T, K > &ctr)
Increment a counter by one.
static void eval(std::array< T, K > &, const std::array< T, K/2 > &)
Counter based RNG engine.
void reset(const key_type &)
void philox_hilo(std::uint32_t b, std::uint32_t &hi, std::uint32_t &lo)
#define VSMC_RNG_PHILOX_VECTOR_LENGTH
PhiloxGenerator default vector length.
static void eval(std::array< T, 2 > &par)
static void eval(std::array< T, 1 > &par)
#define VSMC_RNG_PHILOX_ROUNDS
PhiloxGenerator default rounds.
#define VSMC_DEFINE_RNG_PHILOX_WELY_CONSTANT(T, I, val)
void operator()(ctr_type &ctr, const key_type &key, ctr_type &buffer) const
std::array< ResultType, K > ctr_type
std::array< ResultType, K/2 > key_type
static void eval(std::array< T, K/2 > &)
void operator()(ctr_type &ctr, const key_type &key, std::size_t n, ctr_type *buffer) const