vSMC  v3.0.0
Scalable Monte Carlo
threefry.hpp
Go to the documentation of this file.
1 //============================================================================
2 // vSMC/include/vsmc/rng/threefry.hpp
3 //----------------------------------------------------------------------------
4 // vSMC: Scalable Monte Carlo
5 //----------------------------------------------------------------------------
6 // Copyright (c) 2013-2016, Yan Zhou
7 // All rights reserved.
8 //
9 // Redistribution and use in source and binary forms, with or without
10 // modification, are permitted provided that the following conditions are met:
11 //
12 // Redistributions of source code must retain the above copyright notice,
13 // this list of conditions and the following disclaimer.
14 //
15 // Redistributions in binary form must reproduce the above copyright notice,
16 // this list of conditions and the following disclaimer in the documentation
17 // and/or other materials provided with the distribution.
18 //
19 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS AS IS
20 // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
23 // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 // POSSIBILITY OF SUCH DAMAGE.
30 //============================================================================
31 
32 #ifndef VSMC_RNG_THREEFRY_HPP
33 #define VSMC_RNG_THREEFRY_HPP
34 
36 #include <vsmc/rng/counter.hpp>
37 
38 #define VSMC_DEFINE_RNG_THREEFRY_PARITY_CONSTANT(W, val) \
39  template <typename T> \
40  class ThreefryParityConstant<T, W> \
41  : public std::integral_constant<T, UINT##W##_C(val)> \
42  { \
43  }; // class ThreefryParityConstant
44 
45 #define VSMC_DEFINE_RNG_THREEFRY_ROTATE_CONSTANT(W, K, N, I, val) \
46  template <typename T> \
47  class ThreefryRotateConstant<T, K, N, I, W> \
48  : public std::integral_constant<int, val> \
49  { \
50  }; // class ThreefryRotateConstant
51 
52 #define VSMC_DEFINE_RNG_THREEFRY_PERMUTE_CONSTANT(K, I, val) \
53  template <> \
54  class ThreefryPermuteConstant<K, I> \
55  : public std::integral_constant<std::size_t, val> \
56  { \
57  }; // class ThreefryPermuteConstant
58 
61 #ifndef VSMC_RNG_THREEFRY_ROUNDS
62 #define VSMC_RNG_THREEFRY_ROUNDS 20
63 #endif
64 
67 #ifndef VSMC_RNG_THREEFRY_VECTOR_LENGTH
68 #define VSMC_RNG_THREEFRY_VECTOR_LENGTH 4
69 #endif
70 
71 namespace vsmc
72 {
73 
74 namespace internal
75 {
76 
77 template <typename T, int = std::numeric_limits<T>::digits>
79 
82 
83 template <typename T, std::size_t, std::size_t, std::size_t,
84  int = std::numeric_limits<T>::digits>
86 
95 
112 
121 
138 
171 
236 
237 template <std::size_t, std::size_t>
239 
242 
247 
256 
273 
274 } // namespace internal
275 
278 template <typename T, std::size_t K>
280 {
281  public:
284 
286  template <std::size_t N, std::size_t I>
288 }; // class ThreefryConstants
289 
290 namespace internal
291 {
292 
293 template <typename T, std::size_t K, std::size_t N, bool = (N % 4 == 0)>
295 {
296  public:
297  static void eval(std::array<T, K> &, const std::array<T, K + 1> &) {}
298 }; // class ThreefryInsertKey
299 
300 template <typename T, std::size_t K, std::size_t N>
301 class ThreefryInsertKey<T, K, N, true>
302 {
303  public:
304  static void eval(std::array<T, K> &state, const std::array<T, K + 1> &par)
305  {
306  eval<0>(state, par, std::integral_constant<bool, 0 < K>());
307  state.back() += static_cast<T>(s_);
308  }
309 
310  private:
311  static constexpr std::size_t s_ = N / 4;
312 
313  template <std::size_t>
314  static void eval(
315  std::array<T, K> &, const std::array<T, K + 1> &, std::false_type)
316  {
317  }
318 
319  template <std::size_t I>
320  static void eval(std::array<T, K> &state, const std::array<T, K + 1> &par,
321  std::true_type)
322  {
323  std::get<I>(state) += std::get<(s_ + I) % (K + 1)>(par);
324  eval<I + 1>(state, par, std::integral_constant<bool, I + 1 < K>());
325  }
326 }; // class ThreefryInsertKey
327 
328 template <typename T, std::size_t K, std::size_t N, typename, bool = (N > 0)>
330 {
331  public:
332  static void eval(std::array<T, K> &) {}
333 }; // class ThreefrySBox
334 
335 template <typename T, std::size_t K, std::size_t N, typename Constants>
336 class ThreefrySBox<T, K, N, Constants, true>
337 {
338  public:
339  static void eval(std::array<T, K> &state)
340  {
341  eval<0>(state, std::integral_constant<bool, 1 < K>());
342  }
343 
344  private:
345  template <std::size_t I>
346  using rotate = typename Constants::template rotate<(N - 1) % 8, I>;
347 
348  template <std::size_t>
349  static void eval(std::array<T, K> &, std::false_type)
350  {
351  }
352 
353  template <std::size_t I>
354  static void eval(std::array<T, K> &state, std::true_type)
355  {
356  static constexpr int L = rotate<I / 2>::value;
357  static constexpr int R = std::numeric_limits<T>::digits - L;
358 
359  T x = std::get<I + 1>(state);
360  std::get<I>(state) += x;
361  std::get<I + 1>(state) = (x << L) | (x >> R);
362  std::get<I + 1>(state) ^= std::get<I>(state);
363  eval<I + 2>(state, std::integral_constant<bool, I + 3 < K>());
364  }
365 }; // class ThreefrySBox
366 
367 template <typename T, std::size_t K, std::size_t N, bool = (N > 0)>
369 {
370  public:
371  static void eval(std::array<T, K> &) {}
372 }; // class ThreefryPBox
373 
374 template <typename T, std::size_t K, std::size_t N>
375 class ThreefryPBox<T, K, N, true>
376 {
377  public:
378  static void eval(std::array<T, K> &state)
379  {
380  std::array<T, K> tmp;
381  eval<0>(state, tmp, std::integral_constant<bool, 0 < K>());
382  std::memcpy(state.data(), tmp.data(), sizeof(T) * K);
383  }
384 
385  private:
386  template <std::size_t>
387  static void eval(
388  const std::array<T, K> &, std::array<T, K> &, std::false_type)
389  {
390  }
391 
392  template <std::size_t I>
393  static void eval(
394  const std::array<T, K> &state, std::array<T, K> &tmp, std::true_type)
395  {
396  static constexpr std::size_t J = ThreefryPermuteConstant<K, I>::value;
397 
398  std::get<I>(tmp) = std::get<J>(state);
399  eval<I + 1>(state, tmp, std::integral_constant<bool, I + 1 < K>());
400  }
401 }; // class ThreefryPBox
402 
403 template <typename T, std::size_t N>
404 class ThreefryPBox<T, 2, N, true>
405 {
406  public:
407  static void eval(std::array<T, 2> &) {}
408 }; // class ThreefryPBox
409 
410 template <typename T, std::size_t N>
411 class ThreefryPBox<T, 4, N, true>
412 {
413  public:
414  static void eval(std::array<T, 4> &state)
415  {
416  std::swap(std::get<1>(state), std::get<3>(state));
417  }
418 }; // class ThreefryPBox
419 
420 template <typename T, std::size_t N>
421 class ThreefryPBox<T, 8, N, true>
422 {
423  public:
424  static void eval(std::array<T, 8> &state)
425  {
426  std::swap(std::get<3>(state), std::get<7>(state));
427  T x = std::get<0>(state);
428  std::get<0>(state) = std::get<2>(state);
429  std::get<2>(state) = std::get<4>(state);
430  std::get<4>(state) = std::get<6>(state);
431  std::get<6>(state) = x;
432  }
433 }; // class ThreefryPBox
434 
435 } // namespace vsmc::internal
436 
451 template <typename T, std::size_t K = VSMC_RNG_THREEFRY_VECTOR_LENGTH,
452  std::size_t Rounds = VSMC_RNG_THREEFRY_ROUNDS,
453  typename Constants = ThreefryConstants<T, K>>
455 {
456  static_assert(std::is_unsigned<T>::value,
457  "**ThreefryGenerator** USED WITH T OTHER THAN UNSIGNED INTEGER TYPES");
458 
459  static_assert(K != 0 && K % 2 == 0,
460  "**ThreefryGenerator** USED WITH K OTHER THAN MULTIPLES OF 2");
461 
462  static_assert(
463  Rounds != 0, "**ThreefryGenerator** USED WITH ROUNDS EQUAL TO ZERO");
464 
465  public:
466  using ctr_type = std::array<T, K>;
467  using key_type = std::array<T, K>;
468 
469  static constexpr std::size_t size() { return sizeof(T) * K; }
470 
471  void reset(const key_type &key)
472  {
473  std::copy(key.begin(), key.end(), par_.begin());
474  par_.back() = Constants::parity::value;
475  for (std::size_t i = 0; i != key.size(); ++i)
476  par_.back() ^= par_[i];
477  }
478 
479  template <typename ResultType>
480  void operator()(ctr_type &ctr,
481  std::array<ResultType, size() / sizeof(ResultType)> &buffer) const
482  {
483  union {
484  std::array<T, K> state;
485  ctr_type ctr;
486  std::array<ResultType, size() / sizeof(ResultType)> result;
487  } buf;
488 
489  increment(ctr);
490  buf.ctr = ctr;
491  generate<0>(buf.state, par_, std::true_type());
492  buffer = buf.result;
493  }
494 
495  template <typename ResultType>
496  void operator()(ctr_type &ctr, std::size_t n,
497  std::array<ResultType, size() / sizeof(ResultType)> *buffer) const
498  {
499  union {
500  std::array<T, K> state;
501  ctr_type ctr;
502  std::array<ResultType, size() / sizeof(ResultType)> result;
503  } buf;
504 
505  for (std::size_t i = 0; i != n; ++i) {
506  increment(ctr);
507  buf.ctr = ctr;
508  generate<0>(buf.state, par_, std::true_type());
509  buffer[i] = buf.result;
510  }
511  }
512 
515  {
516  return gen1.par_ == gen2.par_;
517  }
518 
521  {
522  return !(gen1 == gen2);
523  }
524 
525  template <typename CharT, typename Traits>
526  friend std::basic_ostream<CharT, Traits> &operator<<(
527  std::basic_ostream<CharT, Traits> &os,
529  {
530  if (!os)
531  return os;
532 
533  os << gen.par_;
534 
535  return os;
536  }
537 
538  template <typename CharT, typename Traits>
539  friend std::basic_istream<CharT, Traits> &operator>>(
540  std::basic_istream<CharT, Traits> &is,
542  {
543  if (!is)
544  return is;
545 
547  is >> std::ws >> gen_tmp.par_;
548 
549  if (is)
550  gen = std::move(gen_tmp);
551 
552  return is;
553  }
554 
555  private:
556  template <std::size_t>
557  void generate(std::array<T, K> &, const std::array<T, K + 1> &,
558  std::false_type) const
559  {
560  }
561 
562  template <std::size_t N>
563  void generate(std::array<T, K> &state, const std::array<T, K + 1> &par,
564  std::true_type) const
565  {
569  generate<N + 1>(
570  state, par, std::integral_constant<bool, (N < Rounds)>());
571  }
572 
573  private:
574  std::array<T, K + 1> par_;
575 }; // class ThreefryGenerator
576 
579 template <typename ResultType, typename T = ResultType,
580  std::size_t K = VSMC_RNG_THREEFRY_VECTOR_LENGTH,
581  std::size_t Rounds = VSMC_RNG_THREEFRY_ROUNDS,
582  typename Constants = ThreefryConstants<T, K>>
583 using ThreefryEngine =
585 
588 template <typename ResultType>
590 
593 template <typename ResultType>
595 
598 template <typename ResultType>
600 
603 template <typename ResultType>
605 
608 template <typename ResultType>
610 
613 template <typename ResultType>
615 
619 
623 
627 
631 
635 
639 
643 
647 
651 
655 
659 
663 
667 
671 
672 } // namespace vsmc
673 
674 #endif // VSMC_RNG_THREEFRY_HPP
static void eval(std::array< T, K > &state)
Definition: threefry.hpp:378
static void eval(std::array< T, K > &, const std::array< T, K+1 > &)
Definition: threefry.hpp:297
Definition: monitor.hpp:48
friend std::basic_ostream< CharT, Traits > & operator<<(std::basic_ostream< CharT, Traits > &os, const ThreefryGenerator< T, K, Rounds > &gen)
Definition: threefry.hpp:526
std::array< T, K > key_type
Definition: threefry.hpp:467
#define VSMC_RNG_THREEFRY_ROUNDS
ThreefryGenerator default rounds.
Definition: threefry.hpp:62
void increment(std::array< T, K > &ctr)
Increment a counter by one.
Definition: counter.hpp:62
static void eval(std::array< T, 2 > &)
Definition: threefry.hpp:407
friend std::basic_istream< CharT, Traits > & operator>>(std::basic_istream< CharT, Traits > &is, ThreefryGenerator< T, K, Rounds > &gen)
Definition: threefry.hpp:539
STL namespace.
Counter based RNG engine.
Definition: counter.hpp:187
static void eval(std::array< T, 4 > &state)
Definition: threefry.hpp:414
#define VSMC_DEFINE_RNG_THREEFRY_PARITY_CONSTANT(W, val)
Definition: threefry.hpp:38
friend bool operator!=(const ThreefryGenerator< T, K, Rounds > &gen1, const ThreefryGenerator< T, K, Rounds > &gen2)
Definition: threefry.hpp:519
friend bool operator==(const ThreefryGenerator< T, K, Rounds > &gen1, const ThreefryGenerator< T, K, Rounds > &gen2)
Definition: threefry.hpp:513
static void eval(std::array< T, K > &)
Definition: threefry.hpp:332
Threefry RNG generator.
Definition: threefry.hpp:454
Default Threefry constants.
Definition: threefry.hpp:279
void reset(const key_type &key)
Definition: threefry.hpp:471
#define VSMC_RNG_THREEFRY_VECTOR_LENGTH
ThreefryGenerator default vector length.
Definition: threefry.hpp:68
static void eval(std::array< T, 8 > &state)
Definition: threefry.hpp:424
static void eval(std::array< T, K > &)
Definition: threefry.hpp:371
#define VSMC_DEFINE_RNG_THREEFRY_ROTATE_CONSTANT(W, K, N, I, val)
Definition: threefry.hpp:45
void operator()(ctr_type &ctr, std::array< ResultType, size()/sizeof(ResultType)> &buffer) const
Definition: threefry.hpp:480
static void eval(std::array< T, K > &state)
Definition: threefry.hpp:339
void operator()(ctr_type &ctr, std::size_t n, std::array< ResultType, size()/sizeof(ResultType)> *buffer) const
Definition: threefry.hpp:496
static void eval(std::array< T, K > &state, const std::array< T, K+1 > &par)
Definition: threefry.hpp:304
static constexpr std::size_t size()
Definition: threefry.hpp:469
void swap(StateMatrixBase< Layout, Dim, T > &state1, StateMatrixBase< Layout, Dim, T > &state2) noexcept
Swap two StateMatrixBase objects.
std::array< T, K > ctr_type
Definition: threefry.hpp:466
#define VSMC_DEFINE_RNG_THREEFRY_PERMUTE_CONSTANT(K, I, val)
Definition: threefry.hpp:52