MCKL
Monte Carlo Kernel Library
threefry_generic_8x64.hpp
Go to the documentation of this file.
1 //============================================================================
2 // MCKL/include/mckl/random/internal/threefry_generic_8x64.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_8X64_HPP
33 #define MCKL_RANDOM_INTERNAL_THREEFRY_GENERIC_8X64_HPP
34 
39 
40 #define MCKL_RANDOM_INTERNAL_THREEFRY_GENERIC_8X64_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  s4 += ThreefryKBox<T, K, N>::template key<4>(par); \
46  s5 += ThreefryKBox<T, K, N>::template key<5>(par); \
47  s6 += ThreefryKBox<T, K, N>::template key<6>(par); \
48  s7 += ThreefryKBox<T, K, N>::template key<7>(par);
49 
50 #define MCKL_RANDOM_INTERNAL_THREEFRY_GENERIC_8X64_RBOX(N) \
51  { \
52  constexpr int L0 = Constants::rotate::value[0][(N - 1) % 8]; \
53  constexpr int L1 = Constants::rotate::value[1][(N - 1) % 8]; \
54  constexpr int L2 = Constants::rotate::value[2][(N - 1) % 8]; \
55  constexpr int L3 = Constants::rotate::value[3][(N - 1) % 8]; \
56  constexpr int R0 = 64 - L0; \
57  constexpr int R1 = 64 - L1; \
58  constexpr int R2 = 64 - L2; \
59  constexpr int R3 = 64 - L3; \
60  t0 = s0 + s1; \
61  t2 = s2 + s3; \
62  t4 = s4 + s5; \
63  t6 = s6 + s7; \
64  t1 = (s1 << L0) | (s1 >> R0); \
65  t3 = (s3 << L1) | (s3 >> R1); \
66  t5 = (s5 << L2) | (s5 >> R2); \
67  t7 = (s7 << L3) | (s7 >> R3); \
68  s0 = t2; \
69  s2 = t4; \
70  s4 = t6; \
71  s6 = t0; \
72  s1 = t0 ^ t1; \
73  s3 = t6 ^ t7; \
74  s5 = t4 ^ t5; \
75  s7 = t2 ^ t3; \
76  }
77 
78 #define MCKL_RANDOM_INTERNAL_THREEFRY_GENERIC_8X64_CYCLE_4(N) \
79  MCKL_RANDOM_INTERNAL_THREEFRY_GENERIC_8X64_RBOX(N * 8 + 1); \
80  MCKL_RANDOM_INTERNAL_THREEFRY_GENERIC_8X64_RBOX(N * 8 + 2); \
81  MCKL_RANDOM_INTERNAL_THREEFRY_GENERIC_8X64_RBOX(N * 8 + 3); \
82  MCKL_RANDOM_INTERNAL_THREEFRY_GENERIC_8X64_RBOX(N * 8 + 4); \
83  MCKL_RANDOM_INTERNAL_THREEFRY_GENERIC_8X64_KBOX(N * 8 + 4);
84 
85 #define MCKL_RANDOM_INTERNAL_THREEFRY_GENERIC_8X64_CYCLE_8(N) \
86  MCKL_RANDOM_INTERNAL_THREEFRY_GENERIC_8X64_RBOX(N * 8 + 1); \
87  MCKL_RANDOM_INTERNAL_THREEFRY_GENERIC_8X64_RBOX(N * 8 + 2); \
88  MCKL_RANDOM_INTERNAL_THREEFRY_GENERIC_8X64_RBOX(N * 8 + 3); \
89  MCKL_RANDOM_INTERNAL_THREEFRY_GENERIC_8X64_RBOX(N * 8 + 4); \
90  MCKL_RANDOM_INTERNAL_THREEFRY_GENERIC_8X64_KBOX(N * 8 + 4); \
91  MCKL_RANDOM_INTERNAL_THREEFRY_GENERIC_8X64_RBOX(N * 8 + 5); \
92  MCKL_RANDOM_INTERNAL_THREEFRY_GENERIC_8X64_RBOX(N * 8 + 6); \
93  MCKL_RANDOM_INTERNAL_THREEFRY_GENERIC_8X64_RBOX(N * 8 + 7); \
94  MCKL_RANDOM_INTERNAL_THREEFRY_GENERIC_8X64_RBOX(N * 8 + 8); \
95  MCKL_RANDOM_INTERNAL_THREEFRY_GENERIC_8X64_KBOX(N * 8 + 8);
96 
97 #define MCKL_RANDOM_INTERNAL_THREEFRY_GENERIC_8X64_ROUND_20 \
98  MCKL_RANDOM_INTERNAL_THREEFRY_GENERIC_8X64_KBOX(0) \
99  MCKL_RANDOM_INTERNAL_THREEFRY_GENERIC_8X64_CYCLE_8(0) \
100  MCKL_RANDOM_INTERNAL_THREEFRY_GENERIC_8X64_CYCLE_8(1) \
101  MCKL_RANDOM_INTERNAL_THREEFRY_GENERIC_8X64_CYCLE_4(2)
102 
103 #define MCKL_RANDOM_INTERNAL_THREEFRY_GENERIC_8X64_ROUND_72 \
104  MCKL_RANDOM_INTERNAL_THREEFRY_GENERIC_8X64_KBOX(0) \
105  MCKL_RANDOM_INTERNAL_THREEFRY_GENERIC_8X64_CYCLE_8(0) \
106  MCKL_RANDOM_INTERNAL_THREEFRY_GENERIC_8X64_CYCLE_8(1) \
107  MCKL_RANDOM_INTERNAL_THREEFRY_GENERIC_8X64_CYCLE_8(2) \
108  MCKL_RANDOM_INTERNAL_THREEFRY_GENERIC_8X64_CYCLE_8(3) \
109  MCKL_RANDOM_INTERNAL_THREEFRY_GENERIC_8X64_CYCLE_8(4) \
110  MCKL_RANDOM_INTERNAL_THREEFRY_GENERIC_8X64_CYCLE_8(5) \
111  MCKL_RANDOM_INTERNAL_THREEFRY_GENERIC_8X64_CYCLE_8(6) \
112  MCKL_RANDOM_INTERNAL_THREEFRY_GENERIC_8X64_CYCLE_8(7) \
113  MCKL_RANDOM_INTERNAL_THREEFRY_GENERIC_8X64_CYCLE_8(8)
114 
115 #define MCKL_RANDOM_INTERNAL_THREEFRY_GENERIC_8X64_ROUND(L) \
116  T s0 = std::get<0>(buf.s); \
117  T s1 = std::get<1>(buf.s); \
118  T s2 = std::get<2>(buf.s); \
119  T s3 = std::get<3>(buf.s); \
120  T s4 = std::get<4>(buf.s); \
121  T s5 = std::get<5>(buf.s); \
122  T s6 = std::get<6>(buf.s); \
123  T s7 = std::get<7>(buf.s); \
124  T t0; \
125  T t1; \
126  T t2; \
127  T t3; \
128  T t4; \
129  T t5; \
130  T t6; \
131  T t7; \
132  MCKL_RANDOM_INTERNAL_THREEFRY_GENERIC_8X64_ROUND_##L; \
133  std::get<0>(buf.s) = s0; \
134  std::get<1>(buf.s) = s1; \
135  std::get<2>(buf.s) = s2; \
136  std::get<3>(buf.s) = s3; \
137  std::get<4>(buf.s) = s4; \
138  std::get<5>(buf.s) = s5; \
139  std::get<6>(buf.s) = s6; \
140  std::get<7>(buf.s) = s7;
141 
142 namespace mckl {
143 
144 namespace internal {
145 
146 template <typename T>
148 {
149  static_assert(std::numeric_limits<T>::digits == 64,
150  "**Threefry8x64GeneratorGenericImpl** used with T other than a "
151  "64-bit unsigned integers");
152 
153  static constexpr std::size_t K = 8;
154  static constexpr std::size_t Rounds = 20;
156 
157  public:
158  static void eval(
159  const void *plain, void *cipher, const std::array<T, K + 4> &par)
160  {
161  alignas(MCKL_ALIGNMENT) union {
162  std::array<T, K> s;
163  std::array<char, sizeof(T) * K> r;
164  } buf;
165 
166  std::memcpy(buf.s.data(), plain, sizeof(T) * K);
167  union_le<char>(buf.s);
169  union_le<T>(buf.r);
170  std::memcpy(cipher, buf.s.data(), sizeof(T) * K);
171  }
172 
173  template <typename ResultType>
174  static void eval(
175  Counter<T, K> &ctr, ResultType *r, const std::array<T, K + 4> &par)
176  {
177  alignas(MCKL_ALIGNMENT) union {
178  std::array<T, K> s;
179  Counter<T, K> c;
180  std::array<ResultType, sizeof(T) * K / sizeof(ResultType)> r;
181  } buf;
182 
184  buf.c = ctr;
185 #if MCKL_REQUIRE_ENDIANNESS_NEUTURAL
186  union_le<typename Counter<T, K>::value_type>(buf.s);
187 #endif
189 #if MCKL_REQUIRE_ENDIANNESS_NEUTURAL
190  union_le<T>(buf.r);
191 #endif
192  std::memcpy(r, buf.r.data(), sizeof(T) * K);
193  }
194 
195  template <typename ResultType>
196  static void eval(Counter<T, K> &ctr, std::size_t n, ResultType *r,
197  const std::array<T, K + 4> &par)
198  {
199  constexpr std::size_t R = sizeof(T) * K / sizeof(ResultType);
200 
201  for (std::size_t i = 0; i != n; ++i, r += R) {
202  eval(ctr, r, par);
203  }
204  }
205 }; // class Threefry8x64GeneratorGenericImpl
206 
207 template <typename T>
209 {
210  static_assert(std::numeric_limits<T>::digits == 64,
211  "**Threefish512GeneratorGenericImpl** used with T other than a "
212  "64-bit unsigned integers");
213 
214  static constexpr std::size_t K = 8;
215  static constexpr std::size_t Rounds = 72;
217 
218  public:
219  static void eval(
220  const void *plain, void *cipher, const std::array<T, K + 4> &par)
221  {
222  alignas(MCKL_ALIGNMENT) union {
223  std::array<T, K> s;
224  std::array<char, sizeof(T) * K> r;
225  } buf;
226 
227  std::memcpy(buf.s.data(), plain, sizeof(T) * K);
228  union_le<char>(buf.s);
230  union_le<T>(buf.r);
231  std::memcpy(cipher, buf.s.data(), sizeof(T) * K);
232  }
233 
234  template <typename ResultType>
235  static void eval(
236  Counter<T, K> &ctr, ResultType *r, const std::array<T, K + 4> &par)
237  {
238  alignas(MCKL_ALIGNMENT) union {
239  std::array<T, K> s;
240  Counter<T, K> c;
241  std::array<ResultType, sizeof(T) * K / sizeof(ResultType)> r;
242  } buf;
243 
245  buf.c = ctr;
246 #if MCKL_REQUIRE_ENDIANNESS_NEUTURAL
247  union_le<typename Counter<T, K>::value_type>(buf.s);
248 #endif
250 #if MCKL_REQUIRE_ENDIANNESS_NEUTURAL
251  union_le<T>(buf.r);
252 #endif
253  std::memcpy(r, buf.r.data(), sizeof(T) * K);
254  }
255 
256  template <typename ResultType>
257  static void eval(Counter<T, K> &ctr, std::size_t n, ResultType *r,
258  const std::array<T, K + 4> &par)
259  {
260  constexpr std::size_t R = sizeof(T) * K / sizeof(ResultType);
261 
262  for (std::size_t i = 0; i != n; ++i, r += R) {
263  eval(ctr, r, par);
264  }
265  }
266 }; // class Threefish512GeneratorGenericImpl
267 
268 } // namespace internal
269 
270 } // namespace mckl
271 
272 #endif // MCKL_RANDOM_INTERNAL_THREEFRY_GENERIC_8X64_HPP
static void eval(Counter< T, K > &ctr, ResultType *r, const std::array< T, K+4 > &par)
#define MCKL_INLINE_CALL
Definition: intel.h:142
#define MCKL_RANDOM_INTERNAL_THREEFRY_GENERIC_8X64_ROUND(L)
static void eval(const void *plain, void *cipher, const std::array< T, K+4 > &par)
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)
Default Threefry constants.
static void eval(Counter< T, K > &ctr, std::size_t n, ResultType *r, const std::array< T, K+4 > &par)
void increment(std::array< T, K > &ctr, std::integral_constant< T, NSkip >)
Increment a counter by given steps.
Definition: mcmc.hpp:40
static void eval(Counter< T, K > &ctr, ResultType *r, const std::array< T, K+4 > &par)
#define MCKL_ALIGNMENT
The default alignment for scalar type.
Definition: config.h:187