MCKL
Monte Carlo Kernel Library
threefry_generic_4x64.hpp
Go to the documentation of this file.
1 //============================================================================
2 // MCKL/include/mckl/random/internal/threefry_generic_4x64.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_4X64_HPP
33 #define MCKL_RANDOM_INTERNAL_THREEFRY_GENERIC_4X64_HPP
34 
39 
40 #define MCKL_RANDOM_INTERNAL_THREEFRY_GENERIC_4X64_KBOX(N) \
41  s0 += ThreefryKBox<T, K, N>::template key<0>(par); \
42  s1 += ThreefryKBox<T, K, N>::template key<1>(par); \
43  s2 += ThreefryKBox<T, K, N>::template key<2>(par); \
44  s3 += ThreefryKBox<T, K, N>::template key<3>(par);
45 
46 #define MCKL_RANDOM_INTERNAL_THREEFRY_GENERIC_4X64_RBOX(N) \
47  { \
48  constexpr int L0 = Constants::rotate::value[0][(N - 1) % 8]; \
49  constexpr int L1 = Constants::rotate::value[1][(N - 1) % 8]; \
50  constexpr int R0 = 64 - L0; \
51  constexpr int R1 = 64 - L1; \
52  s0 += s1; \
53  s2 += s3; \
54  t1 = (s1 << L0) | (s1 >> R0); \
55  t3 = (s3 << L1) | (s3 >> R1); \
56  s1 = s2 ^ t3; \
57  s3 = s0 ^ t1; \
58  }
59 
60 #define MCKL_RANDOM_INTERNAL_THREEFRY_GENERIC_4X64_CYCLE_4(N) \
61  MCKL_RANDOM_INTERNAL_THREEFRY_GENERIC_4X64_RBOX(N * 8 + 1); \
62  MCKL_RANDOM_INTERNAL_THREEFRY_GENERIC_4X64_RBOX(N * 8 + 2); \
63  MCKL_RANDOM_INTERNAL_THREEFRY_GENERIC_4X64_RBOX(N * 8 + 3); \
64  MCKL_RANDOM_INTERNAL_THREEFRY_GENERIC_4X64_RBOX(N * 8 + 4); \
65  MCKL_RANDOM_INTERNAL_THREEFRY_GENERIC_4X64_KBOX(N * 8 + 4);
66 
67 #define MCKL_RANDOM_INTERNAL_THREEFRY_GENERIC_4X64_CYCLE_8(N) \
68  MCKL_RANDOM_INTERNAL_THREEFRY_GENERIC_4X64_RBOX(N * 8 + 1); \
69  MCKL_RANDOM_INTERNAL_THREEFRY_GENERIC_4X64_RBOX(N * 8 + 2); \
70  MCKL_RANDOM_INTERNAL_THREEFRY_GENERIC_4X64_RBOX(N * 8 + 3); \
71  MCKL_RANDOM_INTERNAL_THREEFRY_GENERIC_4X64_RBOX(N * 8 + 4); \
72  MCKL_RANDOM_INTERNAL_THREEFRY_GENERIC_4X64_KBOX(N * 8 + 4); \
73  MCKL_RANDOM_INTERNAL_THREEFRY_GENERIC_4X64_RBOX(N * 8 + 5); \
74  MCKL_RANDOM_INTERNAL_THREEFRY_GENERIC_4X64_RBOX(N * 8 + 6); \
75  MCKL_RANDOM_INTERNAL_THREEFRY_GENERIC_4X64_RBOX(N * 8 + 7); \
76  MCKL_RANDOM_INTERNAL_THREEFRY_GENERIC_4X64_RBOX(N * 8 + 8); \
77  MCKL_RANDOM_INTERNAL_THREEFRY_GENERIC_4X64_KBOX(N * 8 + 8);
78 
79 #define MCKL_RANDOM_INTERNAL_THREEFRY_GENERIC_4X64_ROUND_20 \
80  MCKL_RANDOM_INTERNAL_THREEFRY_GENERIC_4X64_KBOX(0) \
81  MCKL_RANDOM_INTERNAL_THREEFRY_GENERIC_4X64_CYCLE_8(0) \
82  MCKL_RANDOM_INTERNAL_THREEFRY_GENERIC_4X64_CYCLE_8(1) \
83  MCKL_RANDOM_INTERNAL_THREEFRY_GENERIC_4X64_CYCLE_4(2)
84 
85 #define MCKL_RANDOM_INTERNAL_THREEFRY_GENERIC_4X64_ROUND_72 \
86  MCKL_RANDOM_INTERNAL_THREEFRY_GENERIC_4X64_KBOX(0) \
87  MCKL_RANDOM_INTERNAL_THREEFRY_GENERIC_4X64_CYCLE_8(0) \
88  MCKL_RANDOM_INTERNAL_THREEFRY_GENERIC_4X64_CYCLE_8(1) \
89  MCKL_RANDOM_INTERNAL_THREEFRY_GENERIC_4X64_CYCLE_8(2) \
90  MCKL_RANDOM_INTERNAL_THREEFRY_GENERIC_4X64_CYCLE_8(3) \
91  MCKL_RANDOM_INTERNAL_THREEFRY_GENERIC_4X64_CYCLE_8(4) \
92  MCKL_RANDOM_INTERNAL_THREEFRY_GENERIC_4X64_CYCLE_8(5) \
93  MCKL_RANDOM_INTERNAL_THREEFRY_GENERIC_4X64_CYCLE_8(6) \
94  MCKL_RANDOM_INTERNAL_THREEFRY_GENERIC_4X64_CYCLE_8(7) \
95  MCKL_RANDOM_INTERNAL_THREEFRY_GENERIC_4X64_CYCLE_8(8)
96 
97 #define MCKL_RANDOM_INTERNAL_THREEFRY_GENERIC_4X64_ROUND(L) \
98  T s0 = std::get<0>(buf.s); \
99  T s1 = std::get<1>(buf.s); \
100  T s2 = std::get<2>(buf.s); \
101  T s3 = std::get<3>(buf.s); \
102  T t1; \
103  T t3; \
104  MCKL_RANDOM_INTERNAL_THREEFRY_GENERIC_4X64_ROUND_##L; \
105  std::get<0>(buf.s) = s0; \
106  std::get<1>(buf.s) = s1; \
107  std::get<2>(buf.s) = s2; \
108  std::get<3>(buf.s) = s3;
109 
110 namespace mckl {
111 
112 namespace internal {
113 
114 template <typename T>
116 {
117  static_assert(std::numeric_limits<T>::digits == 64,
118  "**Threefry4x64GeneratorGenericImpl** used with T other than a "
119  "64-bit unsigned integers");
120 
121  static constexpr std::size_t K = 4;
122  static constexpr std::size_t Rounds = 20;
124 
125  public:
126  static void eval(
127  const void *plain, void *cipher, const std::array<T, K + 4> &par)
128  {
129  alignas(MCKL_ALIGNMENT) union {
130  std::array<T, K> s;
131  std::array<char, sizeof(T) * K> r;
132  } buf;
133 
134  std::memcpy(buf.s.data(), plain, sizeof(T) * K);
135  union_le<char>(buf.s);
137  union_le<T>(buf.r);
138  std::memcpy(cipher, buf.s.data(), sizeof(T) * K);
139  }
140 
141  template <typename ResultType>
142  static void eval(
143  Counter<T, K> &ctr, ResultType *r, const std::array<T, K + 4> &par)
144  {
145  alignas(MCKL_ALIGNMENT) union {
146  std::array<T, K> s;
147  Counter<T, K> c;
148  std::array<ResultType, sizeof(T) * K / sizeof(ResultType)> r;
149  } buf;
150 
152  buf.c = ctr;
153 #if MCKL_REQUIRE_ENDIANNESS_NEUTURAL
154  union_le<typename Counter<T, K>::value_type>(buf.s);
155 #endif
157 #if MCKL_REQUIRE_ENDIANNESS_NEUTURAL
158  union_le<T>(buf.r);
159 #endif
160  std::memcpy(r, buf.r.data(), sizeof(T) * K);
161  }
162 
163  template <typename ResultType>
164  static void eval(Counter<T, K> &ctr, std::size_t n, ResultType *r,
165  const std::array<T, K + 4> &par)
166  {
167  constexpr std::size_t R = sizeof(T) * K / sizeof(ResultType);
168 
169  for (std::size_t i = 0; i != n; ++i, r += R) {
170  eval(ctr, r, par);
171  }
172  }
173 }; // class Threefry4x64GeneratorGenericImpl
174 
175 template <typename T>
177 {
178  static_assert(std::numeric_limits<T>::digits == 64,
179  "**Threefish256GeneratorGenericImpl** used with T other than a "
180  "64-bit unsigned integers");
181 
182  static constexpr std::size_t K = 4;
183  static constexpr std::size_t Rounds = 72;
185 
186  public:
187  static void eval(
188  const void *plain, void *cipher, const std::array<T, K + 4> &par)
189  {
190  alignas(MCKL_ALIGNMENT) union {
191  std::array<T, K> s;
192  std::array<char, sizeof(T) * K> r;
193  } buf;
194 
195  std::memcpy(buf.s.data(), plain, sizeof(T) * K);
196  union_le<char>(buf.s);
198  union_le<T>(buf.r);
199  std::memcpy(cipher, buf.s.data(), sizeof(T) * K);
200  }
201 
202  template <typename ResultType>
203  static void eval(
204  Counter<T, K> &ctr, ResultType *r, const std::array<T, K + 4> &par)
205  {
206  alignas(MCKL_ALIGNMENT) union {
207  std::array<T, K> s;
208  Counter<T, K> c;
209  std::array<ResultType, sizeof(T) * K / sizeof(ResultType)> r;
210  } buf;
211 
213  buf.c = ctr;
214 #if MCKL_REQUIRE_ENDIANNESS_NEUTURAL
215  union_le<typename Counter<T, K>::value_type>(buf.s);
216 #endif
218 #if MCKL_REQUIRE_ENDIANNESS_NEUTURAL
219  union_le<T>(buf.r);
220 #endif
221  std::memcpy(r, buf.r.data(), sizeof(T) * K);
222  }
223 
224  template <typename ResultType>
225  static void eval(Counter<T, K> &ctr, std::size_t n, ResultType *r,
226  const std::array<T, K + 4> &par)
227  {
228  constexpr std::size_t R = sizeof(T) * K / sizeof(ResultType);
229 
230  for (std::size_t i = 0; i != n; ++i, r += R) {
231  eval(ctr, r, par);
232  }
233  }
234 }; // class Threefish256GeneratorGenericImpl
235 
236 } // namespace internal
237 
238 } // namespace mckl
239 
240 #endif // MCKL_RANDOM_INTERNAL_THREEFRY_GENERIC_4X64_HPP
static void eval(Counter< T, K > &ctr, 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)
#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(const void *plain, void *cipher, const std::array< T, K+4 > &par)
#define MCKL_RANDOM_INTERNAL_THREEFRY_GENERIC_4X64_ROUND(L)
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
static void eval(const void *plain, void *cipher, const std::array< T, K+4 > &par)
static void eval(Counter< T, K > &ctr, std::size_t n, ResultType *r, const std::array< T, K+4 > &par)