MCKL
Monte Carlo Kernel Library
threefry_generic_2x64.hpp
Go to the documentation of this file.
1 //============================================================================
2 // MCKL/include/mckl/random/internal/threefry_generic_2x64.hpp
3 //----------------------------------------------------------------------------
4 // MCKL: Monte Carlo Kernel Library
5 //----------------------------------------------------------------------------
6 // Copyright (c) 2013-2018, 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 MCKL_RANDOM_INTERNAL_THREEFRY_GENERIC_2X64_HPP
33 #define MCKL_RANDOM_INTERNAL_THREEFRY_GENERIC_2X64_HPP
34 
39 
40 #define MCKL_RANDOM_INTERNAL_THREEFRY_GENERIC_2X64_KBOX(N) \
41  s0 += ThreefryKBox<T, K, N>::template key<0>(par); \
42  s1 += ThreefryKBox<T, K, N>::template key<1>(par);
43 
44 #define MCKL_RANDOM_INTERNAL_THREEFRY_GENERIC_2X64_RBOX(N) \
45  { \
46  constexpr int L0 = Constants::rotate::value[0][(N - 1) % 8]; \
47  constexpr int R0 = 64 - L0; \
48  s0 += s1; \
49  s1 = (s1 << L0) | (s1 >> R0); \
50  s1 ^= s0; \
51  }
52 
53 #define MCKL_RANDOM_INTERNAL_THREEFRY_GENERIC_2X64_CYCLE_4(N) \
54  MCKL_RANDOM_INTERNAL_THREEFRY_GENERIC_2X64_RBOX(N * 8 + 1); \
55  MCKL_RANDOM_INTERNAL_THREEFRY_GENERIC_2X64_RBOX(N * 8 + 2); \
56  MCKL_RANDOM_INTERNAL_THREEFRY_GENERIC_2X64_RBOX(N * 8 + 3); \
57  MCKL_RANDOM_INTERNAL_THREEFRY_GENERIC_2X64_RBOX(N * 8 + 4); \
58  MCKL_RANDOM_INTERNAL_THREEFRY_GENERIC_2X64_KBOX(N * 8 + 4);
59 
60 #define MCKL_RANDOM_INTERNAL_THREEFRY_GENERIC_2X64_CYCLE_8(N) \
61  MCKL_RANDOM_INTERNAL_THREEFRY_GENERIC_2X64_RBOX(N * 8 + 1); \
62  MCKL_RANDOM_INTERNAL_THREEFRY_GENERIC_2X64_RBOX(N * 8 + 2); \
63  MCKL_RANDOM_INTERNAL_THREEFRY_GENERIC_2X64_RBOX(N * 8 + 3); \
64  MCKL_RANDOM_INTERNAL_THREEFRY_GENERIC_2X64_RBOX(N * 8 + 4); \
65  MCKL_RANDOM_INTERNAL_THREEFRY_GENERIC_2X64_KBOX(N * 8 + 4); \
66  MCKL_RANDOM_INTERNAL_THREEFRY_GENERIC_2X64_RBOX(N * 8 + 5); \
67  MCKL_RANDOM_INTERNAL_THREEFRY_GENERIC_2X64_RBOX(N * 8 + 6); \
68  MCKL_RANDOM_INTERNAL_THREEFRY_GENERIC_2X64_RBOX(N * 8 + 7); \
69  MCKL_RANDOM_INTERNAL_THREEFRY_GENERIC_2X64_RBOX(N * 8 + 8); \
70  MCKL_RANDOM_INTERNAL_THREEFRY_GENERIC_2X64_KBOX(N * 8 + 8);
71 
72 #define MCKL_RANDOM_INTERNAL_THREEFRY_GENERIC_2X64_ROUND_20 \
73  T s0 = std::get<0>(buf.s); \
74  T s1 = std::get<1>(buf.s); \
75  MCKL_RANDOM_INTERNAL_THREEFRY_GENERIC_2X64_KBOX(0) \
76  MCKL_RANDOM_INTERNAL_THREEFRY_GENERIC_2X64_CYCLE_8(0) \
77  MCKL_RANDOM_INTERNAL_THREEFRY_GENERIC_2X64_CYCLE_8(1) \
78  MCKL_RANDOM_INTERNAL_THREEFRY_GENERIC_2X64_CYCLE_4(2) \
79  std::get<0>(buf.s) = s0; \
80  std::get<1>(buf.s) = s1;
81 
82 namespace mckl {
83 
84 namespace internal {
85 
86 template <typename T>
88 {
89  static_assert(std::numeric_limits<T>::digits == 64,
90  "**Threefry2x64GeneratorGenericImpl** used with T other than a "
91  "64-bit unsigned integers");
92 
93  static constexpr std::size_t K = 2;
94  static constexpr std::size_t Rounds = 20;
96 
97  public:
98  static void eval(
99  const void *plain, void *cipher, const std::array<T, K + 4> &par)
100  {
101  alignas(MCKL_ALIGNMENT) union {
102  std::array<T, K> s;
103  std::array<char, sizeof(T) * K> r;
104  } buf;
105 
106  std::memcpy(buf.s.data(), plain, sizeof(T) * K);
107  union_le<char>(buf.s);
109  union_le<T>(buf.r);
110  std::memcpy(cipher, buf.s.data(), sizeof(T) * K);
111  }
112 
113  template <typename ResultType>
114  static void eval(
115  Counter<T, K> &ctr, ResultType *r, const std::array<T, K + 4> &par)
116  {
117  alignas(MCKL_ALIGNMENT) union {
118  std::array<T, K> s;
119  Counter<T, K> c;
120  std::array<ResultType, sizeof(T) * K / sizeof(ResultType)> r;
121  } buf;
122 
124  buf.c = ctr;
125 #if MCKL_REQUIRE_ENDIANNESS_NEUTURAL
126  union_le<typename Counter<T, K>::value_type>(buf.s);
127 #endif
129 #if MCKL_REQUIRE_ENDIANNESS_NEUTURAL
130  union_le<T>(buf.r);
131 #endif
132  std::memcpy(r, buf.r.data(), sizeof(T) * K);
133  }
134 
135  template <typename ResultType>
136  static void eval(Counter<T, K> &ctr, std::size_t n, ResultType *r,
137  const std::array<T, K + 4> &par)
138  {
139  constexpr std::size_t R = sizeof(T) * K / sizeof(ResultType);
140 
141  for (std::size_t i = 0; i != n; ++i, r += R) {
142  eval(ctr, r, par);
143  }
144  }
145 }; // class Threefry2x64GeneratorGenericImpl
146 
147 } // namespace internal
148 
149 } // namespace mckl
150 
151 #endif // MCKL_RANDOM_INTERNAL_THREEFRY_GENERIC_2X64_HPP
#define MCKL_INLINE_CALL
Definition: intel.h:142
typename internal::CounterImpl< T, K >::type Counter
A counter type with the same width as std::array<T, K> but with possibly fewer elements.
Definition: increment.hpp:104
static void eval(Counter< T, K > &ctr, std::size_t n, ResultType *r, const std::array< T, K+4 > &par)
static void eval(Counter< T, K > &ctr, ResultType *r, const std::array< T, K+4 > &par)
Default Threefry constants.
void increment(std::array< T, K > &ctr, std::integral_constant< T, NSkip >)
Increment a counter by given steps.
Definition: mcmc.hpp:40
#define MCKL_ALIGNMENT
The default alignment for scalar type.
Definition: config.h:187
#define MCKL_RANDOM_INTERNAL_THREEFRY_GENERIC_2X64_ROUND_20
static void eval(const void *plain, void *cipher, const std::array< T, K+4 > &par)