32 #ifndef VSMC_RNG_PHILOX_HPP
33 #define VSMC_RNG_PHILOX_HPP
41 #define VSMC_STATIC_ASSERT_RNG_PHILOX_RESULT_TYPE(ResultType) \
43 (cxx11::is_same<ResultType, uint32_t>::value || \
44 cxx11::is_same<ResultType, uint64_t>::value), \
45 USE_PhiloxEngine_WITH_INTEGER_TYPE_OTHER_THAN_uint32_t_OR_uint64_t)
47 #define VSMC_STATIC_ASSERT_RNG_PHILOX_SIZE(K) \
48 VSMC_STATIC_ASSERT((K == 2 || K == 4), \
49 USE_PhiloxEngine_WITH_SIZE_OTHER_THAN_2_OR_4)
51 #define VSMC_STATIC_ASSERT_RNG_PHILOX \
52 VSMC_STATIC_ASSERT_RNG_PHILOX_RESULT_TYPE(ResultType); \
53 VSMC_STATIC_ASSERT_RNG_PHILOX_SIZE(K);
55 #define VSMC_DEFINE_RNG_PHILOX_WELY_CONSTANT(T, I, val) \
56 template <> struct PhiloxWeylConstantValue < T, I > : \
57 public cxx11::integral_constant< T, val > {};
59 #define VSMC_DEFINE_RNG_PHILOX_ROUND_CONSTANT(T, K, I, val) \
60 template <> struct PhiloxRoundConstantValue < T, K, I > : \
61 public cxx11::integral_constant< T, val > {};
65 #ifndef VSMC_RNG_PHILOX_ROUNDS
66 #define VSMC_RNG_PHILOX_ROUNDS 10
83 UINT64_C(0x9E3779B97F4A7C15))
85 UINT64_C(0xBB67AE8584CAA73B))
98 UINT64_C(0xD2B74407B1CE6E93))
101 UINT64_C(0xD2E7470EE14C6C93))
103 UINT64_C(0xCA5A826395121157))
116 template <typename ResultType,
std::
size_t I>
118 public internal::PhiloxWeylConstantValue<ResultType, I> {};
129 template <
typename ResultType, std::
size_t K, std::
size_t I>
137 template <
typename ResultType, std::
size_t K, std::
size_t N,
bool = (N > 1)>
140 template <
typename ResultType, std::
size_t N>
150 template <
typename ResultType, std::
size_t N>
162 template <std::
size_t K, std::
size_t I>
166 static_cast<uint64_t
>(b) *
167 static_cast<uint64_t>(
169 hi =
static_cast<uint32_t
>(prod >> 32);
170 lo =
static_cast<uint32_t
>(prod);
175 template <std::
size_t K, std::
size_t I>
178 unsigned VSMC_INT128 prod =
179 static_cast<unsigned VSMC_INT128
>(b) *
180 static_cast<unsigned VSMC_INT128>(
182 hi =
static_cast<uint64_t
>(prod >> 64);
183 lo =
static_cast<uint64_t
>(prod);
186 #elif defined(VSMC_MSVC) // VSMC_HAS_INT128
188 template <std::
size_t K, std::
size_t I>
189 inline void philox_hilo (uint64_t b, uint64_t &hi, uint64_t &lo)
195 #else // VSMC_HAS_INT128
197 template <std::
size_t K, std::
size_t I>
198 inline void philox_hilo (uint64_t b, uint64_t &hi, uint64_t &lo)
201 traits::PhiloxRoundConstantTrait<uint64_t, K, I>::value;
202 const unsigned whalf = 32;
203 const uint64_t lomask = (
static_cast<uint64_t
>(1) << whalf) - 1;
205 lo =
static_cast<uint64_t
>(a * b);
207 const uint64_t ahi = a >> whalf;
208 const uint64_t alo = a & lomask;
209 const uint64_t bhi = b >> whalf;
210 const uint64_t blo = b & lomask;
212 const uint64_t ahbl = ahi * blo;
213 const uint64_t albh = alo * bhi;
215 const uint64_t ahbl_albh = ((ahbl & lomask) + (albh & lomask));
217 hi = ahi * bhi + (ahbl >> whalf) + (albh >> whalf);
218 hi += ahbl_albh >> whalf;
219 hi += ((lo >> whalf) < (ahbl_albh & lomask));
222 #endif // VSMC_HAS_INT128
224 template <
typename ResultType, std::
size_t K, std::
size_t N,
bool = (N > 0)>
231 template <
typename ResultType, std::
size_t N>
245 template <
typename ResultType, std::
size_t N>
305 template <
typename ResultType, std::size_t K,
328 template <
typename SeedSeq>
346 counter::reset(ctr_);
352 template <
typename SeedSeq>
358 counter::reset(ctr_);
359 seq.generate(key_.begin(), key_.end());
365 counter::reset(ctr_);
370 ctr_type
ctr ()
const {
return ctr_;}
374 void ctr (
const ctr_type &c)
376 counter::set(ctr_, c);
386 result_type operator() ()
389 counter::increment(ctr_);
390 generate_buffer(ctr_, buffer_);
394 return buffer_[index_++];
399 buffer_type operator() (
const ctr_type &c)
const
402 generate_buffer(c, buf);
409 void operator() (
const ctr_type &c, buffer_type &buf)
const
410 {generate_buffer(c, buf);}
414 std::size_t n =
static_cast<std::size_t
>(nskip);
415 if (index_ + n <= K) {
428 counter::increment(ctr_, static_cast<result_type>(n / K));
436 ~(
static_cast<result_type
>(0)));
441 friend inline bool operator== (
446 eng1.index_ == eng2.index_ &&
447 eng1.ctr_ == eng2.ctr_ &&
448 eng1.key_ == eng2.key_;
451 friend inline bool operator!= (
454 {
return !(eng1 == eng2);}
456 template <
typename CharT,
typename Traits>
457 friend inline std::basic_ostream<CharT, Traits> &
operator<< (
458 std::basic_ostream<CharT, Traits> &os,
464 os << eng.ctr_ <<
' ';
465 os << eng.key_ <<
' ';
466 os << eng.buffer_ <<
' ';
472 template <
typename CharT,
typename Traits>
473 friend inline std::basic_istream<CharT, Traits> &operator>> (
474 std::basic_istream<CharT, Traits> &is,
481 is >> std::ws >> eng_tmp.buffer_;
482 is >> std::ws >> eng_tmp.ctr_;
483 is >> std::ws >> eng_tmp.key_;
484 is >> std::ws >> eng_tmp.index_;
487 #if VSMC_HAS_CXX11_RVALUE_REFERENCES
504 void generate_buffer (
const ctr_type c, buffer_type &buf)
const
511 template <std::
size_t>
512 void generate_buffer (buffer_type &, key_type &,
515 template <std::
size_t N>
516 void generate_buffer (buffer_type &buf, key_type &par,
521 generate_buffer<N + 1>(buf, par,
522 cxx11::integral_constant<bool, N < Rounds>());
552 #endif // VSMC_RNG_PHILOX_HPP
static void eval(Array< ResultType, K/2 > &)
void discard(result_type nskip)
#define VSMC_CONSTEXPR
constexpr
PhiloxEngine< uint32_t, 2 > Philox2x32
Philox2x32 RNG engine reimplemented.
PhiloxEngine< uint32_t, 4 > Philox4x32
Philox4x32 RNG engine reimplemented.
PhiloxEngine(const key_type &k)
static void eval(Array< ResultType, K > &, const Array< ResultType, K/2 > &)
Array< ResultType, K > ctr_type
PhiloxEngine(SeedSeq &seq, typename cxx11::enable_if< internal::is_seed_seq< SeedSeq, result_type, key_type, PhiloxEngine< ResultType, K, Rounds > >::value >::type *=nullptr)
PhiloxEngine< uint64_t, 2 > Philox2x64
Philox2x64 RNG engine reimplemented.
integral_constant< bool, false > false_type
Function template argument used for position.
void seed(SeedSeq &seq, typename cxx11::enable_if< internal::is_seed_seq< SeedSeq, result_type, key_type, PhiloxEngine< ResultType, K, Rounds > >::value >::type *=nullptr)
PhiloxEngine(result_type s=0)
static void eval(Array< ResultType, 1 > &par)
#define VSMC_DEFINE_RNG_PHILOX_WELY_CONSTANT(T, I, val)
#define VSMC_MNE
Avoid MSVC stupid behavior: MNE = Macro No Expansion.
Array< ResultType, K/2 > key_type
void key(const key_type &k)
#define VSMC_RNG_PHILOX_ROUNDS
PhiloxEngine default rounds.
remove_reference< T >::type && move(T &&t) noexcept
std::basic_ostream< CharT, Traits > & operator<<(std::basic_ostream< CharT, Traits > &os, const Sampler< T > &sampler)
void philox_hilo(uint64_t b, uint64_t &hi, uint64_t &lo)
Traits of PhiloxEngine constants for bumping the key (Weyl sequence)
Philox4x32 Philox
The default 32-bits Philox engine.
static void eval(Array< ResultType, 2 > &state, const Array< ResultType, 1 > &par)
void ctr(const ctr_type &c)
void seed(const key_type &k)
#define VSMC_NULLPTR
nullptr
static void eval(Array< ResultType, 4 > &state, const Array< ResultType, 2 > &par)
integral_constant< bool, true > true_type
Philox4x64 Philox_64
The default 64-bits Philox engine.
#define VSMC_DEFINE_RNG_PHILOX_ROUND_CONSTANT(T, K, I, val)
Traits of PhiloxEngine constants for rounding.
PhiloxEngine< uint64_t, 4 > Philox4x64
Philox4x64 RNG engine reimplemented.
static void eval(Array< ResultType, 2 > &par)
Array< ResultType, K > buffer_type
Philox RNG engine reimplemented.
#define VSMC_STATIC_ASSERT_RNG_PHILOX