32 #ifndef VSMC_RNG_PHILOX_HPP 33 #define VSMC_RNG_PHILOX_HPP 42 #define VSMC_STATIC_ASSERT_RNG_PHILOX_RESULT_TYPE(ResultType) \ 43 VSMC_STATIC_ASSERT(((sizeof(ResultType) == sizeof(std::uint32_t) && \ 44 std::is_unsigned<ResultType>::value) || \ 45 (sizeof(ResultType) == sizeof(std::uint64_t) && \ 46 std::is_unsigned<ResultType>::value)), \ 47 "**PhiloxGenerator** USED WITH ResultType OTHER THAN UNSIGNED 32/64 " \ 50 #define VSMC_STATIC_ASSERT_RNG_PHILOX_SIZE(K) \ 51 VSMC_STATIC_ASSERT((K == 2 || K == 4), \ 52 "**PhiloxGenerator** USED WITH SIZE OTHER THAN 2 OR 4") 54 #define VSMC_STATIC_ASSERT_RNG_PHILOX \ 55 VSMC_STATIC_ASSERT_RNG_PHILOX_RESULT_TYPE(ResultType); \ 56 VSMC_STATIC_ASSERT_RNG_PHILOX_SIZE(K); 58 #define VSMC_DEFINE_RNG_PHILOX_WELY_CONSTANT(T, I, val) \ 60 class PhiloxWeylConstant<T, I> : public std::integral_constant<T, val> \ 62 }; // class PhiloxWeylConstant 64 #define VSMC_DEFINE_RNG_PHILOX_ROUND_CONSTANT(T, K, I, val) \ 66 class PhiloxRoundConstant<T, K, I> \ 67 : public std::integral_constant<T, val> \ 69 }; // PhiloxRoundConstant 73 #ifndef VSMC_RNG_PHILOX_ROUNDS 74 #define VSMC_RNG_PHILOX_ROUNDS 10 79 #ifndef VSMC_RNG_PHILOX_VECTOR_LENGTH 80 #define VSMC_RNG_PHILOX_VECTOR_LENGTH 4 89 template <
typename, std::
size_t>
100 template <typename,
std::
size_t,
std::
size_t>
119 template <
std::
size_t K,
std::
size_t I>
123 static_cast<std::uint64_t>(
131 template <std::
size_t K, std::
size_t I>
134 unsigned VSMC_INT128 prod =
135 static_cast<unsigned VSMC_INT128
>(b) *
136 static_cast<unsigned VSMC_INT128>(
142 #elif defined(VSMC_MSVC) // VSMC_HAS_INT128 144 template <std::
size_t K, std::
size_t I>
150 #else // VSMC_HAS_INT128 152 template <std::
size_t K, std::
size_t I>
156 const unsigned whalf = 32;
169 const std::uint64_t ahbl_albh = ((ahbl & lomask) + (albh & lomask));
171 hi = ahi * bhi + (ahbl >> whalf) + (albh >> whalf);
172 hi += ahbl_albh >> whalf;
173 hi += ((lo >> whalf) < (ahbl_albh & lomask));
176 #endif // VSMC_HAS_INT128 178 template <
typename T, std::
size_t K, std::
size_t N,
bool = (N > 1)>
182 static void eval(std::array<T, K / 2> &) {}
185 template <
typename T, std::
size_t N>
189 static void eval(std::array<T, 1> &par)
195 template <
typename T, std::
size_t N>
199 static void eval(std::array<T, 2> &par)
206 template <
typename T, std::
size_t K, std::
size_t N,
bool = (N > 0)>
210 static void eval(std::array<T, K> &,
const std::array<T, K / 2> &) {}
213 template <
typename T, std::
size_t N>
217 static void eval(std::array<T, 2> &state,
const std::array<T, 1> &par)
221 philox_hilo<2, 0>(std::get<0>(state), hi, lo);
222 hi ^= std::get<0>(par);
223 std::get<0>(state) = hi ^ std::get<1>(state);
224 std::get<1>(state) = lo;
228 template <
typename T, std::
size_t N>
232 static void eval(std::array<T, 4> &state,
const std::array<T, 2> &par)
238 philox_hilo<4, 1>(std::get<2>(state), hi0, lo1);
239 philox_hilo<4, 0>(std::get<0>(state), hi2, lo3);
241 hi0 ^= std::get<0>(par);
242 hi2 ^= std::get<1>(par);
243 std::get<0>(state) = hi0 ^ std::get<1>(state);
244 std::get<1>(state) = lo1;
245 std::get<2>(state) = hi2 ^ std::get<3>(state);
246 std::get<3>(state) = lo3;
265 static constexpr std::size_t
size() {
return K; }
270 std::array<result_type, K> &buffer)
const 273 std::array<ctr_type, 1> state;
274 std::array<result_type, size()> result;
278 buf.state.front() = ctr;
280 generate<0>(buf.state, par, std::true_type());
287 const std::size_t Blocks = 8;
288 const std::size_t M = size() * Blocks;
289 const std::size_t m = n / M;
290 increment(ctr, m, reinterpret_cast<ctr_type *>(r));
291 std::array<ctr_type, Blocks> *s =
292 reinterpret_cast<std::array<ctr_type, Blocks> *
>(r);
293 for (std::size_t i = 0; i != m; ++i) {
295 generate<0>(s[i], par, std::true_type());
302 template <std::
size_t, std::
size_t Blocks>
304 std::array<ctr_type, Blocks> &,
key_type &, std::false_type)
const 308 template <std::
size_t N, std::
size_t Blocks>
309 void generate(std::array<ctr_type, Blocks> &state,
key_type &par,
310 std::true_type)
const 313 round<N, 0>(state, par, std::true_type());
315 state, par, std::integral_constant < bool, N<Rounds>());
318 template <std::
size_t, std::
size_t, std::
size_t Blocks>
320 std::array<ctr_type, Blocks> &,
key_type &, std::false_type)
const 324 template <std::
size_t N, std::
size_t B, std::
size_t Blocks>
325 void round(std::array<ctr_type, Blocks> &state,
key_type &par,
326 std::true_type)
const 330 state, par, std::integral_constant<bool, B + 1 < Blocks>());
366 #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 > &)
void operator()(ctr_type &ctr, const key_type &key, std::array< result_type, K > &buffer) const
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)
std::array< ResultType, K > ctr_type
std::size_t operator()(ctr_type &ctr, const key_type &key, std::size_t n, result_type *r) const
std::array< ResultType, K/2 > key_type
static void eval(std::array< T, K/2 > &)
#define VSMC_STATIC_ASSERT_RNG_PHILOX