MCKL
Monte Carlo Kernel Library
threefry_avx2_64.hpp
Go to the documentation of this file.
1 //============================================================================
2 // MCKL/include/mckl/random/internal/threefry_avx2_64.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_AVX2_64_HPP
33 #define MCKL_RANDOM_INTERNAL_THREEFRY_AVX2_64_HPP
34 
45 
46 MCKL_PUSH_GCC_WARNING("-Wignored-attributes")
47 
48 namespace mckl {
49 
50 namespace internal {
51 
52 template <typename T, std::size_t K, std::size_t Rounds, typename Constants>
54 {
55  public:
56  static void eval(
57  const void *plain, void *cipher, const std::array<T, K + 4> &par)
58  {
60  plain, cipher, par);
61  }
62 
63  template <typename ResultType>
64  static void eval(
65  Counter<T, K> &ctr, ResultType *r, const std::array<T, K + 4> &par)
66  {
68  ctr, r, par);
69  }
70 
71  template <typename ResultType>
72  static void eval(Counter<T, K> &ctr, std::size_t n, ResultType *r,
73  const std::array<T, K + 4> &par)
74  {
75  constexpr std::size_t S = K <= 8 ? 8 : K;
76  constexpr std::size_t N = sizeof(__m256i) * S / (sizeof(T) * K);
77  constexpr std::size_t R = sizeof(T) * K / sizeof(ResultType);
78 
79  while (n >= N) {
80  std::array<__m256i, S> s;
82  MCKL_INLINE_CALL transpose4x64_load_si256(s);
84  MCKL_INLINE_CALL transpose4x64_store_si256(s);
85  std::memcpy(r, s.data(), sizeof(T) * K * N);
86  n -= N;
87  r += N * R;
88  }
89 
90  alignas(MCKL_ALIGNMENT) std::array<ResultType, N * R> t;
92  ctr, n, t.data(), par);
93  std::memcpy(r, t.data(), sizeof(T) * K * n);
94  }
95 
96  private:
97  template <std::size_t, std::size_t S>
98  static void round(std::array<__m256i, S> &, const std::array<T, K + 4> &,
99  std::false_type)
100  {
101  }
102 
103  template <std::size_t N, std::size_t S>
104  static void round(std::array<__m256i, S> &s,
105  const std::array<T, K + 4> &par, std::true_type)
106  {
108  }
109 
110  template <std::size_t N, std::size_t S>
111  MCKL_INLINE static void kbox(
112  std::array<__m256i, S> &s, const std::array<T, K + 4> &par)
113  {
114  kbox<N>(s, par,
115  std::integral_constant<bool, (N % 4 == 0 && N <= Rounds)>());
116  }
117 
118  template <std::size_t, std::size_t S>
119  static void kbox(std::array<__m256i, S> &, const std::array<T, K + 4> &,
120  std::false_type)
121  {
122  }
123 
124  template <std::size_t N>
125  static void kbox(std::array<__m256i, 8> &s,
126  const std::array<T, K + 4> &par, std::true_type)
127  {
128  std::array<__m256i, K> k;
129  set_key<N>(k, par);
130 
131  std::get<0>(s) = _mm256_add_epi64(std::get<0>(s), std::get<0 % K>(k));
132  std::get<1>(s) = _mm256_add_epi64(std::get<1>(s), std::get<1 % K>(k));
133  std::get<2>(s) = _mm256_add_epi64(std::get<2>(s), std::get<2 % K>(k));
134  std::get<3>(s) = _mm256_add_epi64(std::get<3>(s), std::get<3 % K>(k));
135  std::get<4>(s) = _mm256_add_epi64(std::get<4>(s), std::get<4 % K>(k));
136  std::get<5>(s) = _mm256_add_epi64(std::get<5>(s), std::get<5 % K>(k));
137  std::get<6>(s) = _mm256_add_epi64(std::get<6>(s), std::get<6 % K>(k));
138  std::get<7>(s) = _mm256_add_epi64(std::get<7>(s), std::get<7 % K>(k));
139  }
140 
141  template <std::size_t N>
142  static void kbox(std::array<__m256i, 16> &s,
143  const std::array<T, K + 4> &par, std::true_type)
144  {
145  std::array<__m256i, K> k;
146  set_key<N>(k, par);
147 
148  std::get<0x0>(s) =
149  _mm256_add_epi64(std::get<0x0>(s), std::get<0x0 % K>(k));
150  std::get<0x1>(s) =
151  _mm256_add_epi64(std::get<0x1>(s), std::get<0x1 % K>(k));
152  std::get<0x2>(s) =
153  _mm256_add_epi64(std::get<0x2>(s), std::get<0x2 % K>(k));
154  std::get<0x3>(s) =
155  _mm256_add_epi64(std::get<0x3>(s), std::get<0x3 % K>(k));
156  std::get<0x4>(s) =
157  _mm256_add_epi64(std::get<0x4>(s), std::get<0x4 % K>(k));
158  std::get<0x5>(s) =
159  _mm256_add_epi64(std::get<0x5>(s), std::get<0x5 % K>(k));
160  std::get<0x6>(s) =
161  _mm256_add_epi64(std::get<0x6>(s), std::get<0x6 % K>(k));
162  std::get<0x7>(s) =
163  _mm256_add_epi64(std::get<0x7>(s), std::get<0x7 % K>(k));
164  std::get<0x8>(s) =
165  _mm256_add_epi64(std::get<0x8>(s), std::get<0x8 % K>(k));
166  std::get<0x9>(s) =
167  _mm256_add_epi64(std::get<0x9>(s), std::get<0x9 % K>(k));
168  std::get<0xA>(s) =
169  _mm256_add_epi64(std::get<0xA>(s), std::get<0xA % K>(k));
170  std::get<0xB>(s) =
171  _mm256_add_epi64(std::get<0xB>(s), std::get<0xB % K>(k));
172  std::get<0xC>(s) =
173  _mm256_add_epi64(std::get<0xC>(s), std::get<0xC % K>(k));
174  std::get<0xD>(s) =
175  _mm256_add_epi64(std::get<0xD>(s), std::get<0xD % K>(k));
176  std::get<0xE>(s) =
177  _mm256_add_epi64(std::get<0xE>(s), std::get<0xE % K>(k));
178  std::get<0xF>(s) =
179  _mm256_add_epi64(std::get<0xF>(s), std::get<0xF % K>(k));
180  }
181 
182  template <std::size_t N, std::size_t S>
183  MCKL_INLINE static void rbox(std::array<__m256i, S> &s)
184  {
185  rbox<N>(s, std::integral_constant<bool, (N > 0 && N <= Rounds)>());
186  }
187 
188  template <std::size_t, std::size_t S>
189  static void rbox(std::array<__m256i, S> &, std::false_type)
190  {
191  }
192 
193  template <std::size_t N>
194  static void rbox(std::array<__m256i, 8> &s, std::true_type)
195  {
196  constexpr int L0 = Constants::rotate::value[0 % (K / 2)][(N - 1) % 8];
197  constexpr int L1 = Constants::rotate::value[1 % (K / 2)][(N - 1) % 8];
198  constexpr int L2 = Constants::rotate::value[2 % (K / 2)][(N - 1) % 8];
199  constexpr int L3 = Constants::rotate::value[3 % (K / 2)][(N - 1) % 8];
200  constexpr int R0 = 64 - L0;
201  constexpr int R1 = 64 - L1;
202  constexpr int R2 = 64 - L2;
203  constexpr int R3 = 64 - L3;
204 
205  std::get<0>(s) = _mm256_add_epi64(std::get<0>(s), std::get<1>(s));
206  std::get<2>(s) = _mm256_add_epi64(std::get<2>(s), std::get<3>(s));
207  std::get<4>(s) = _mm256_add_epi64(std::get<4>(s), std::get<5>(s));
208  std::get<6>(s) = _mm256_add_epi64(std::get<6>(s), std::get<7>(s));
209 
210  __m256i l0 = _mm256_slli_epi64(std::get<1>(s), L0);
211  __m256i l1 = _mm256_slli_epi64(std::get<3>(s), L1);
212  __m256i l2 = _mm256_slli_epi64(std::get<5>(s), L2);
213  __m256i l3 = _mm256_slli_epi64(std::get<7>(s), L3);
214 
215  __m256i r0 = _mm256_srli_epi64(std::get<1>(s), R0);
216  __m256i r1 = _mm256_srli_epi64(std::get<3>(s), R1);
217  __m256i r2 = _mm256_srli_epi64(std::get<5>(s), R2);
218  __m256i r3 = _mm256_srli_epi64(std::get<7>(s), R3);
219 
220  std::get<1>(s) = _mm256_or_si256(l0, r0);
221  std::get<3>(s) = _mm256_or_si256(l1, r1);
222  std::get<5>(s) = _mm256_or_si256(l2, r2);
223  std::get<7>(s) = _mm256_or_si256(l3, r3);
224 
225  std::get<1>(s) = _mm256_xor_si256(std::get<0>(s), std::get<1>(s));
226  std::get<3>(s) = _mm256_xor_si256(std::get<2>(s), std::get<3>(s));
227  std::get<5>(s) = _mm256_xor_si256(std::get<4>(s), std::get<5>(s));
228  std::get<7>(s) = _mm256_xor_si256(std::get<6>(s), std::get<7>(s));
229 
230  permute(s);
231  }
232 
233  template <std::size_t N>
234  static void rbox(std::array<__m256i, 16> &s, std::true_type)
235  {
236  constexpr int L0 = Constants::rotate::value[0 % (K / 2)][(N - 1) % 8];
237  constexpr int L1 = Constants::rotate::value[1 % (K / 2)][(N - 1) % 8];
238  constexpr int L2 = Constants::rotate::value[2 % (K / 2)][(N - 1) % 8];
239  constexpr int L3 = Constants::rotate::value[3 % (K / 2)][(N - 1) % 8];
240  constexpr int L4 = Constants::rotate::value[4 % (K / 2)][(N - 1) % 8];
241  constexpr int L5 = Constants::rotate::value[5 % (K / 2)][(N - 1) % 8];
242  constexpr int L6 = Constants::rotate::value[6 % (K / 2)][(N - 1) % 8];
243  constexpr int L7 = Constants::rotate::value[7 % (K / 2)][(N - 1) % 8];
244  constexpr int R0 = 64 - L0;
245  constexpr int R1 = 64 - L1;
246  constexpr int R2 = 64 - L2;
247  constexpr int R3 = 64 - L3;
248  constexpr int R4 = 64 - L4;
249  constexpr int R5 = 64 - L5;
250  constexpr int R6 = 64 - L6;
251  constexpr int R7 = 64 - L7;
252 
253  std::get<0x0>(s) =
254  _mm256_add_epi64(std::get<0x0>(s), std::get<0x1>(s));
255  std::get<0x2>(s) =
256  _mm256_add_epi64(std::get<0x2>(s), std::get<0x3>(s));
257  std::get<0x4>(s) =
258  _mm256_add_epi64(std::get<0x4>(s), std::get<0x5>(s));
259  std::get<0x6>(s) =
260  _mm256_add_epi64(std::get<0x6>(s), std::get<0x7>(s));
261  std::get<0x8>(s) =
262  _mm256_add_epi64(std::get<0x8>(s), std::get<0x9>(s));
263  std::get<0xA>(s) =
264  _mm256_add_epi64(std::get<0xA>(s), std::get<0xB>(s));
265  std::get<0xC>(s) =
266  _mm256_add_epi64(std::get<0xC>(s), std::get<0xD>(s));
267  std::get<0xE>(s) =
268  _mm256_add_epi64(std::get<0xE>(s), std::get<0xF>(s));
269 
270  __m256i l0 = _mm256_slli_epi64(std::get<0x1>(s), L0);
271  __m256i l1 = _mm256_slli_epi64(std::get<0x3>(s), L1);
272  __m256i l2 = _mm256_slli_epi64(std::get<0x5>(s), L2);
273  __m256i l3 = _mm256_slli_epi64(std::get<0x7>(s), L3);
274  __m256i l4 = _mm256_slli_epi64(std::get<0x9>(s), L4);
275  __m256i l5 = _mm256_slli_epi64(std::get<0xB>(s), L5);
276  __m256i l6 = _mm256_slli_epi64(std::get<0xD>(s), L6);
277  __m256i l7 = _mm256_slli_epi64(std::get<0xF>(s), L7);
278 
279  std::get<0x1>(s) = _mm256_srli_epi64(std::get<0x1>(s), R0);
280  std::get<0x3>(s) = _mm256_srli_epi64(std::get<0x3>(s), R1);
281  std::get<0x5>(s) = _mm256_srli_epi64(std::get<0x5>(s), R2);
282  std::get<0x7>(s) = _mm256_srli_epi64(std::get<0x7>(s), R3);
283  std::get<0x9>(s) = _mm256_srli_epi64(std::get<0x9>(s), R4);
284  std::get<0xB>(s) = _mm256_srli_epi64(std::get<0xB>(s), R5);
285  std::get<0xD>(s) = _mm256_srli_epi64(std::get<0xD>(s), R6);
286  std::get<0xF>(s) = _mm256_srli_epi64(std::get<0xF>(s), R7);
287 
288  std::get<0x1>(s) = _mm256_or_si256(l0, std::get<0x1>(s));
289  std::get<0x3>(s) = _mm256_or_si256(l1, std::get<0x3>(s));
290  std::get<0x5>(s) = _mm256_or_si256(l2, std::get<0x5>(s));
291  std::get<0x7>(s) = _mm256_or_si256(l3, std::get<0x7>(s));
292  std::get<0x9>(s) = _mm256_or_si256(l4, std::get<0x9>(s));
293  std::get<0xB>(s) = _mm256_or_si256(l5, std::get<0xB>(s));
294  std::get<0xD>(s) = _mm256_or_si256(l6, std::get<0xD>(s));
295  std::get<0xF>(s) = _mm256_or_si256(l7, std::get<0xF>(s));
296 
297  std::get<0x1>(s) =
298  _mm256_xor_si256(std::get<0x0>(s), std::get<0x1>(s));
299  std::get<0x3>(s) =
300  _mm256_xor_si256(std::get<0x2>(s), std::get<0x3>(s));
301  std::get<0x5>(s) =
302  _mm256_xor_si256(std::get<0x4>(s), std::get<0x5>(s));
303  std::get<0x7>(s) =
304  _mm256_xor_si256(std::get<0x6>(s), std::get<0x7>(s));
305  std::get<0x9>(s) =
306  _mm256_xor_si256(std::get<0x8>(s), std::get<0x9>(s));
307  std::get<0xB>(s) =
308  _mm256_xor_si256(std::get<0xA>(s), std::get<0xB>(s));
309  std::get<0xD>(s) =
310  _mm256_xor_si256(std::get<0xC>(s), std::get<0xD>(s));
311  std::get<0xF>(s) =
312  _mm256_xor_si256(std::get<0xE>(s), std::get<0xF>(s));
313 
314  permute(s);
315  }
316 
317  template <std::size_t N>
318  static void set_key(std::array<__m256i, 2> &k, const std::array<T, 6> &par)
319  {
320  std::get<0>(k) = _mm256_set1_epi64x(static_cast<MCKL_INT64>(
321  ThreefryKBox<T, 2, N>::template key<0>(par)));
322  std::get<1>(k) = _mm256_set1_epi64x(static_cast<MCKL_INT64>(
323  ThreefryKBox<T, 2, N>::template key<1>(par)));
324  }
325 
326  template <std::size_t N>
327  static void set_key(std::array<__m256i, 4> &k, const std::array<T, 8> &par)
328  {
329  std::get<0>(k) = _mm256_set1_epi64x(static_cast<MCKL_INT64>(
330  ThreefryKBox<T, 4, N>::template key<0>(par)));
331  std::get<1>(k) = _mm256_set1_epi64x(static_cast<MCKL_INT64>(
332  ThreefryKBox<T, 4, N>::template key<1>(par)));
333  std::get<2>(k) = _mm256_set1_epi64x(static_cast<MCKL_INT64>(
334  ThreefryKBox<T, 4, N>::template key<2>(par)));
335  std::get<3>(k) = _mm256_set1_epi64x(static_cast<MCKL_INT64>(
336  ThreefryKBox<T, 4, N>::template key<3>(par)));
337  }
338 
339  template <std::size_t N>
340  static void set_key(
341  std::array<__m256i, 8> &k, const std::array<T, 12> &par)
342  {
343  std::get<0>(k) = _mm256_set1_epi64x(static_cast<MCKL_INT64>(
344  ThreefryKBox<T, 8, N>::template key<0>(par)));
345  std::get<1>(k) = _mm256_set1_epi64x(static_cast<MCKL_INT64>(
346  ThreefryKBox<T, 8, N>::template key<1>(par)));
347  std::get<2>(k) = _mm256_set1_epi64x(static_cast<MCKL_INT64>(
348  ThreefryKBox<T, 8, N>::template key<2>(par)));
349  std::get<3>(k) = _mm256_set1_epi64x(static_cast<MCKL_INT64>(
350  ThreefryKBox<T, 8, N>::template key<3>(par)));
351  std::get<4>(k) = _mm256_set1_epi64x(static_cast<MCKL_INT64>(
352  ThreefryKBox<T, 8, N>::template key<4>(par)));
353  std::get<5>(k) = _mm256_set1_epi64x(static_cast<MCKL_INT64>(
354  ThreefryKBox<T, 8, N>::template key<5>(par)));
355  std::get<6>(k) = _mm256_set1_epi64x(static_cast<MCKL_INT64>(
356  ThreefryKBox<T, 8, N>::template key<6>(par)));
357  std::get<7>(k) = _mm256_set1_epi64x(static_cast<MCKL_INT64>(
358  ThreefryKBox<T, 8, N>::template key<7>(par)));
359  }
360 
361  template <std::size_t N>
362  static void set_key(
363  std::array<__m256i, 16> &k, const std::array<T, 20> &par)
364  {
365  std::get<0x0>(k) = _mm256_set1_epi64x(static_cast<MCKL_INT64>(
366  ThreefryKBox<T, 16, N>::template key<0x0>(par)));
367  std::get<0x1>(k) = _mm256_set1_epi64x(static_cast<MCKL_INT64>(
368  ThreefryKBox<T, 16, N>::template key<0x1>(par)));
369  std::get<0x2>(k) = _mm256_set1_epi64x(static_cast<MCKL_INT64>(
370  ThreefryKBox<T, 16, N>::template key<0x2>(par)));
371  std::get<0x3>(k) = _mm256_set1_epi64x(static_cast<MCKL_INT64>(
372  ThreefryKBox<T, 16, N>::template key<0x3>(par)));
373  std::get<0x4>(k) = _mm256_set1_epi64x(static_cast<MCKL_INT64>(
374  ThreefryKBox<T, 16, N>::template key<0x4>(par)));
375  std::get<0x5>(k) = _mm256_set1_epi64x(static_cast<MCKL_INT64>(
376  ThreefryKBox<T, 16, N>::template key<0x5>(par)));
377  std::get<0x6>(k) = _mm256_set1_epi64x(static_cast<MCKL_INT64>(
378  ThreefryKBox<T, 16, N>::template key<0x6>(par)));
379  std::get<0x7>(k) = _mm256_set1_epi64x(static_cast<MCKL_INT64>(
380  ThreefryKBox<T, 16, N>::template key<0x7>(par)));
381  std::get<0x8>(k) = _mm256_set1_epi64x(static_cast<MCKL_INT64>(
382  ThreefryKBox<T, 16, N>::template key<0x8>(par)));
383  std::get<0x9>(k) = _mm256_set1_epi64x(static_cast<MCKL_INT64>(
384  ThreefryKBox<T, 16, N>::template key<0x9>(par)));
385  std::get<0xA>(k) = _mm256_set1_epi64x(static_cast<MCKL_INT64>(
386  ThreefryKBox<T, 16, N>::template key<0xA>(par)));
387  std::get<0xB>(k) = _mm256_set1_epi64x(static_cast<MCKL_INT64>(
388  ThreefryKBox<T, 16, N>::template key<0xB>(par)));
389  std::get<0xC>(k) = _mm256_set1_epi64x(static_cast<MCKL_INT64>(
390  ThreefryKBox<T, 16, N>::template key<0xC>(par)));
391  std::get<0xD>(k) = _mm256_set1_epi64x(static_cast<MCKL_INT64>(
392  ThreefryKBox<T, 16, N>::template key<0xD>(par)));
393  std::get<0xE>(k) = _mm256_set1_epi64x(static_cast<MCKL_INT64>(
394  ThreefryKBox<T, 16, N>::template key<0xE>(par)));
395  std::get<0xF>(k) = _mm256_set1_epi64x(static_cast<MCKL_INT64>(
396  ThreefryKBox<T, 16, N>::template key<0xF>(par)));
397  }
398 
399  template <std::size_t S>
400  static void permute(std::array<__m256i, S> &s)
401  {
402  permute<0>(s, std::integral_constant<bool, 0 < S / K>());
403  }
404 
405  template <std::size_t, std::size_t S>
406  static void permute(std::array<__m256i, S> &, std::false_type)
407  {
408  }
409 
410  template <std::size_t I, std::size_t S>
411  static void permute(std::array<__m256i, S> &s, std::true_type)
412  {
414  permute<I + 1>(s, std::integral_constant<bool, I + 1 < S / K>());
415  }
416 }; // class ThreefryGeneratorAVX2Impl64
417 
418 template <typename T>
421 {
422 }; // class ThreefryGeneratorAVX2Impl64
423 
424 template <typename T>
427 {
428 }; // class ThreefryGeneratorAVX2Impl64
429 
430 template <typename T>
433 {
434 }; // class ThreefryGeneratorAVX2Impl64
435 
436 template <typename T>
439 {
440 }; // class ThreefryGeneratorAVX2Impl64
441 
442 template <typename T>
445 {
446 }; // class ThreefryGeneratorAVX2Impl64
447 
448 template <typename T>
451 {
452 }; // class ThreefryGeneratorAVX2Impl64
453 
454 template <typename T>
457 {
458 }; // class ThreefryGeneratorAVX2Impl64
459 
460 } // namespace internal
461 
462 } // namespace mckl
463 
465 
466 #endif // MCKL_RANDOM_INTERNAL_THREEFRY_AVX2_64_HPP
#define MCKL_PUSH_GCC_WARNING(warning)
Definition: compiler.h:78
void round(std::size_t n, const float *a, float *y)
Definition: vmf.hpp:310
#define MCKL_INLINE_CALL
Definition: intel.h:142
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
#define MCKL_RANDOM_INTERNAL_THREEFRY_UNROLL_ROUND(N, s, par)
Default Threefry constants.
Definition: mcmc.hpp:40
#define MCKL_ALIGNMENT
The default alignment for scalar type.
Definition: config.h:187
static void eval(Counter< T, K > &ctr, std::size_t n, ResultType *r, const std::array< T, K+4 > &par)
#define MCKL_INLINE
Definition: clang.h:147
static void eval(Counter< T, K > &ctr, ResultType *r, const std::array< T, K+4 > &par)
#define MCKL_POP_GCC_WARNING
Definition: compiler.h:79
void increment_si256(std::array< T, K > &ctr, std::array< __m256i, S > &s, std::false_type)