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