32 #ifndef MCKL_RANDOM_INTERNAL_THREEFRY_AVX2_8X64_HPP 33 #define MCKL_RANDOM_INTERNAL_THREEFRY_AVX2_8X64_HPP 43 #define MCKL_RANDOM_INTERNAL_THREEFRY_AVX2_8X64_KBOX(N) \ 44 ymmt0 = _mm256_set1_epi64x(static_cast<MCKL_INT64>( \ 45 ThreefryKBox<T, K, N>::template key<0>(par))); \ 46 ymmt1 = _mm256_set1_epi64x(static_cast<MCKL_INT64>( \ 47 ThreefryKBox<T, K, N>::template key<1>(par))); \ 48 ymmt2 = _mm256_set1_epi64x(static_cast<MCKL_INT64>( \ 49 ThreefryKBox<T, K, N>::template key<2>(par))); \ 50 ymmt3 = _mm256_set1_epi64x(static_cast<MCKL_INT64>( \ 51 ThreefryKBox<T, K, N>::template key<3>(par))); \ 52 ymmt4 = _mm256_set1_epi64x(static_cast<MCKL_INT64>( \ 53 ThreefryKBox<T, K, N>::template key<4>(par))); \ 54 ymmt5 = _mm256_set1_epi64x(static_cast<MCKL_INT64>( \ 55 ThreefryKBox<T, K, N>::template key<5>(par))); \ 56 ymmt6 = _mm256_set1_epi64x(static_cast<MCKL_INT64>( \ 57 ThreefryKBox<T, K, N>::template key<6>(par))); \ 58 ymmt7 = _mm256_set1_epi64x(static_cast<MCKL_INT64>( \ 59 ThreefryKBox<T, K, N>::template key<7>(par))); \ 60 ymms0 = _mm256_add_epi64(ymms0, ymmt0); \ 61 ymms1 = _mm256_add_epi64(ymms1, ymmt1); \ 62 ymms2 = _mm256_add_epi64(ymms2, ymmt2); \ 63 ymms3 = _mm256_add_epi64(ymms3, ymmt3); \ 64 ymms4 = _mm256_add_epi64(ymms4, ymmt4); \ 65 ymms5 = _mm256_add_epi64(ymms5, ymmt5); \ 66 ymms6 = _mm256_add_epi64(ymms6, ymmt6); \ 67 ymms7 = _mm256_add_epi64(ymms7, ymmt7); 69 #define MCKL_RANDOM_INTERNAL_THREEFRY_AVX2_8X64_RBOX(N) \ 71 constexpr int L0 = Constants::rotate::value[0][(N - 1) % 8]; \ 72 constexpr int L1 = Constants::rotate::value[1][(N - 1) % 8]; \ 73 constexpr int L2 = Constants::rotate::value[2][(N - 1) % 8]; \ 74 constexpr int L3 = Constants::rotate::value[3][(N - 1) % 8]; \ 75 constexpr int R0 = 64 - L0; \ 76 constexpr int R1 = 64 - L1; \ 77 constexpr int R2 = 64 - L2; \ 78 constexpr int R3 = 64 - L3; \ 79 ymmt0 = _mm256_add_epi64(ymms0, ymms1); \ 80 ymmt2 = _mm256_add_epi64(ymms2, ymms3); \ 81 ymmt4 = _mm256_add_epi64(ymms4, ymms5); \ 82 ymmt6 = _mm256_add_epi64(ymms6, ymms7); \ 83 ymmt1 = _mm256_slli_epi64(ymms1, L0); \ 84 ymmt3 = _mm256_slli_epi64(ymms3, L1); \ 85 ymmt5 = _mm256_slli_epi64(ymms5, L2); \ 86 ymmt7 = _mm256_slli_epi64(ymms7, L3); \ 87 ymms1 = _mm256_srli_epi64(ymms1, R0); \ 88 ymms3 = _mm256_srli_epi64(ymms3, R1); \ 89 ymms5 = _mm256_srli_epi64(ymms5, R2); \ 90 ymms7 = _mm256_srli_epi64(ymms7, R3); \ 91 ymmt1 = _mm256_or_si256(ymms1, ymmt1); \ 92 ymmt3 = _mm256_or_si256(ymms3, ymmt3); \ 93 ymmt5 = _mm256_or_si256(ymms5, ymmt5); \ 94 ymmt7 = _mm256_or_si256(ymms7, ymmt7); \ 99 ymms1 = _mm256_xor_si256(ymmt0, ymmt1); \ 100 ymms3 = _mm256_xor_si256(ymmt6, ymmt7); \ 101 ymms5 = _mm256_xor_si256(ymmt4, ymmt5); \ 102 ymms7 = _mm256_xor_si256(ymmt2, ymmt3); \ 105 #define MCKL_RANDOM_INTERNAL_THREEFRY_AVX2_8X64_CYCLE_4(N) \ 106 MCKL_RANDOM_INTERNAL_THREEFRY_AVX2_8X64_RBOX(N * 8 + 1); \ 107 MCKL_RANDOM_INTERNAL_THREEFRY_AVX2_8X64_RBOX(N * 8 + 2); \ 108 MCKL_RANDOM_INTERNAL_THREEFRY_AVX2_8X64_RBOX(N * 8 + 3); \ 109 MCKL_RANDOM_INTERNAL_THREEFRY_AVX2_8X64_RBOX(N * 8 + 4); \ 110 MCKL_RANDOM_INTERNAL_THREEFRY_AVX2_8X64_KBOX(N * 8 + 4); 112 #define MCKL_RANDOM_INTERNAL_THREEFRY_AVX2_8X64_CYCLE_8(N) \ 113 MCKL_RANDOM_INTERNAL_THREEFRY_AVX2_8X64_RBOX(N * 8 + 1); \ 114 MCKL_RANDOM_INTERNAL_THREEFRY_AVX2_8X64_RBOX(N * 8 + 2); \ 115 MCKL_RANDOM_INTERNAL_THREEFRY_AVX2_8X64_RBOX(N * 8 + 3); \ 116 MCKL_RANDOM_INTERNAL_THREEFRY_AVX2_8X64_RBOX(N * 8 + 4); \ 117 MCKL_RANDOM_INTERNAL_THREEFRY_AVX2_8X64_KBOX(N * 8 + 4); \ 118 MCKL_RANDOM_INTERNAL_THREEFRY_AVX2_8X64_RBOX(N * 8 + 5); \ 119 MCKL_RANDOM_INTERNAL_THREEFRY_AVX2_8X64_RBOX(N * 8 + 6); \ 120 MCKL_RANDOM_INTERNAL_THREEFRY_AVX2_8X64_RBOX(N * 8 + 7); \ 121 MCKL_RANDOM_INTERNAL_THREEFRY_AVX2_8X64_RBOX(N * 8 + 8); \ 122 MCKL_RANDOM_INTERNAL_THREEFRY_AVX2_8X64_KBOX(N * 8 + 8); 128 template <
typename T>
131 static_assert(std::numeric_limits<T>::digits == 64,
132 "**Threefry8x64GeneratorAVX2Impl** used with T other than a 64-bit " 133 "unsigned integers");
135 static constexpr std::size_t K = 8;
136 static constexpr std::size_t Rounds = 20;
141 const void *plain,
void *cipher,
const std::array<T, K + 4> &par)
146 template <
typename ResultType>
147 static void eval(std::array<std::uint64_t, 8> &ctr, ResultType *r,
148 const std::array<T, K + 4> &par)
153 template <
typename ResultType>
154 static void eval(std::array<std::uint64_t, 8> &ctr, std::size_t n,
155 ResultType *r,
const std::array<T, K + 4> &par)
157 constexpr std::size_t R =
sizeof(T) * K /
sizeof(ResultType);
159 const std::size_t n0 =
160 static_cast<std::size_t
>(std::min(static_cast<std::uint64_t>(n),
161 std::numeric_limits<std::uint64_t>::max() - ctr.front()));
163 eval_kernel(ctr, n0, r, par);
173 eval_kernel(ctr, n, r, par);
177 template <
typename ResultType>
178 static void eval_kernel(std::array<std::uint64_t, 8> &ctr, std::size_t n,
179 ResultType *r,
const std::array<T, K + 4> &par)
181 constexpr std::size_t
S = 8;
182 constexpr std::size_t N =
sizeof(__m256i) * S / (
sizeof(T) * K);
185 _mm256_set_epi64x(static_cast<MCKL_INT64>(std::get<3>(ctr)),
186 static_cast<MCKL_INT64>(std::get<2>(ctr)),
187 static_cast<MCKL_INT64>(std::get<1>(ctr)),
188 static_cast<MCKL_INT64>(std::get<0>(ctr)));
190 _mm256_set_epi64x(static_cast<MCKL_INT64>(std::get<7>(ctr)),
191 static_cast<MCKL_INT64>(std::get<6>(ctr)),
192 static_cast<MCKL_INT64>(std::get<5>(ctr)),
193 static_cast<MCKL_INT64>(std::get<4>(ctr)));
196 __m256i *rptr =
reinterpret_cast<__m256i *
>(r);
199 _mm256_add_epi64(ymmc0, _mm256_set_epi64x(0, 0, 0, 1));
201 _mm256_add_epi64(ymmc0, _mm256_set_epi64x(0, 0, 0, 2));
203 _mm256_add_epi64(ymmc0, _mm256_set_epi64x(0, 0, 0, 3));
205 _mm256_add_epi64(ymmc0, _mm256_set_epi64x(0, 0, 0, 4));
208 __m256i ymms1 = ymmc1;
209 __m256i ymms3 = ymmc1;
210 __m256i ymms5 = ymmc1;
211 __m256i ymms7 = ymmc1;
232 ymmt0 = _mm256_unpacklo_epi64(ymms0, ymms1);
233 ymmt1 = _mm256_unpacklo_epi64(ymms2, ymms3);
234 ymmt2 = _mm256_unpackhi_epi64(ymms0, ymms1);
235 ymmt3 = _mm256_unpackhi_epi64(ymms2, ymms3);
236 ymmt4 = _mm256_unpacklo_epi64(ymms4, ymms5);
237 ymmt5 = _mm256_unpacklo_epi64(ymms6, ymms7);
238 ymmt6 = _mm256_unpackhi_epi64(ymms4, ymms5);
239 ymmt7 = _mm256_unpackhi_epi64(ymms6, ymms7);
240 ymms0 = _mm256_permute2x128_si256(ymmt0, ymmt1, 0x20);
241 ymms1 = _mm256_permute2x128_si256(ymmt2, ymmt3, 0x20);
242 ymms2 = _mm256_permute2x128_si256(ymmt0, ymmt1, 0x31);
243 ymms3 = _mm256_permute2x128_si256(ymmt2, ymmt3, 0x31);
244 ymms4 = _mm256_permute2x128_si256(ymmt4, ymmt5, 0x20);
245 ymms5 = _mm256_permute2x128_si256(ymmt6, ymmt7, 0x20);
246 ymms6 = _mm256_permute2x128_si256(ymmt4, ymmt5, 0x31);
247 ymms7 = _mm256_permute2x128_si256(ymmt6, ymmt7, 0x31);
254 ymmt0 = _mm256_unpacklo_epi64(ymms0, ymms1);
255 ymmt1 = _mm256_unpacklo_epi64(ymms2, ymms3);
256 ymmt2 = _mm256_unpackhi_epi64(ymms0, ymms1);
257 ymmt3 = _mm256_unpackhi_epi64(ymms2, ymms3);
258 ymmt4 = _mm256_unpacklo_epi64(ymms4, ymms5);
259 ymmt5 = _mm256_unpacklo_epi64(ymms6, ymms7);
260 ymmt6 = _mm256_unpackhi_epi64(ymms4, ymms5);
261 ymmt7 = _mm256_unpackhi_epi64(ymms6, ymms7);
262 ymms0 = _mm256_permute2x128_si256(ymmt0, ymmt1, 0x20);
263 ymms1 = _mm256_permute2x128_si256(ymmt2, ymmt3, 0x20);
264 ymms2 = _mm256_permute2x128_si256(ymmt0, ymmt1, 0x31);
265 ymms3 = _mm256_permute2x128_si256(ymmt2, ymmt3, 0x31);
266 ymms4 = _mm256_permute2x128_si256(ymmt4, ymmt5, 0x20);
267 ymms5 = _mm256_permute2x128_si256(ymmt6, ymmt7, 0x20);
268 ymms6 = _mm256_permute2x128_si256(ymmt4, ymmt5, 0x31);
269 ymms7 = _mm256_permute2x128_si256(ymmt6, ymmt7, 0x31);
283 _mm256_storeu_si256(rptr++, ymms0);
284 _mm256_storeu_si256(rptr++, ymms1);
285 _mm256_storeu_si256(rptr++, ymms2);
286 _mm256_storeu_si256(rptr++, ymms3);
287 _mm256_storeu_si256(rptr++, ymms4);
288 _mm256_storeu_si256(rptr++, ymms5);
289 _mm256_storeu_si256(rptr++, ymms6);
290 _mm256_storeu_si256(rptr++, ymms7);
292 std::array<__m256i, S> s;
293 std::get<0>(s) = ymms0;
294 std::get<1>(s) = ymms1;
295 std::get<2>(s) = ymms2;
296 std::get<3>(s) = ymms3;
297 std::get<4>(s) = ymms4;
298 std::get<5>(s) = ymms5;
299 std::get<6>(s) = ymms6;
300 std::get<7>(s) = ymms7;
301 std::memcpy(rptr, s.data(), n *
sizeof(T) * K);
308 template <
typename T>
311 static_assert(std::numeric_limits<T>::digits == 64,
312 "**Threefish512GeneratorAVX2Impl** used with T other than a 64-bit " 313 "unsigned integers");
315 static constexpr std::size_t K = 8;
316 static constexpr std::size_t Rounds = 20;
321 const void *plain,
void *cipher,
const std::array<T, K + 4> &par)
326 template <
typename ResultType>
327 static void eval(std::array<std::uint64_t, 8> &ctr, ResultType *r,
328 const std::array<T, K + 4> &par)
333 template <
typename ResultType>
334 static void eval(std::array<std::uint64_t, 8> &ctr, std::size_t n,
335 ResultType *r,
const std::array<T, K + 4> &par)
337 constexpr std::size_t R =
sizeof(T) * K /
sizeof(ResultType);
339 const std::size_t n0 =
340 static_cast<std::size_t
>(std::min(static_cast<std::uint64_t>(n),
341 std::numeric_limits<std::uint64_t>::max() - ctr.front()));
343 eval_kernel(ctr, n0, r, par);
353 eval_kernel(ctr, n, r, par);
357 template <
typename ResultType>
358 static void eval_kernel(std::array<std::uint64_t, 8> &ctr, std::size_t n,
359 ResultType *r,
const std::array<T, K + 4> &par)
361 constexpr std::size_t
S = 8;
362 constexpr std::size_t N =
sizeof(__m256i) * S / (
sizeof(T) * K);
365 _mm256_set_epi64x(static_cast<MCKL_INT64>(std::get<3>(ctr)),
366 static_cast<MCKL_INT64>(std::get<2>(ctr)),
367 static_cast<MCKL_INT64>(std::get<1>(ctr)),
368 static_cast<MCKL_INT64>(std::get<0>(ctr)));
370 _mm256_set_epi64x(static_cast<MCKL_INT64>(std::get<7>(ctr)),
371 static_cast<MCKL_INT64>(std::get<6>(ctr)),
372 static_cast<MCKL_INT64>(std::get<5>(ctr)),
373 static_cast<MCKL_INT64>(std::get<4>(ctr)));
376 __m256i *rptr =
reinterpret_cast<__m256i *
>(r);
379 _mm256_add_epi64(ymmc0, _mm256_set_epi64x(0, 0, 0, 1));
381 _mm256_add_epi64(ymmc0, _mm256_set_epi64x(0, 0, 0, 2));
383 _mm256_add_epi64(ymmc0, _mm256_set_epi64x(0, 0, 0, 3));
385 _mm256_add_epi64(ymmc0, _mm256_set_epi64x(0, 0, 0, 4));
388 __m256i ymms1 = ymmc1;
389 __m256i ymms3 = ymmc1;
390 __m256i ymms5 = ymmc1;
391 __m256i ymms7 = ymmc1;
412 ymmt0 = _mm256_unpacklo_epi64(ymms0, ymms1);
413 ymmt1 = _mm256_unpacklo_epi64(ymms2, ymms3);
414 ymmt2 = _mm256_unpackhi_epi64(ymms0, ymms1);
415 ymmt3 = _mm256_unpackhi_epi64(ymms2, ymms3);
416 ymmt4 = _mm256_unpacklo_epi64(ymms4, ymms5);
417 ymmt5 = _mm256_unpacklo_epi64(ymms6, ymms7);
418 ymmt6 = _mm256_unpackhi_epi64(ymms4, ymms5);
419 ymmt7 = _mm256_unpackhi_epi64(ymms6, ymms7);
420 ymms0 = _mm256_permute2x128_si256(ymmt0, ymmt1, 0x20);
421 ymms1 = _mm256_permute2x128_si256(ymmt2, ymmt3, 0x20);
422 ymms2 = _mm256_permute2x128_si256(ymmt0, ymmt1, 0x31);
423 ymms3 = _mm256_permute2x128_si256(ymmt2, ymmt3, 0x31);
424 ymms4 = _mm256_permute2x128_si256(ymmt4, ymmt5, 0x20);
425 ymms5 = _mm256_permute2x128_si256(ymmt6, ymmt7, 0x20);
426 ymms6 = _mm256_permute2x128_si256(ymmt4, ymmt5, 0x31);
427 ymms7 = _mm256_permute2x128_si256(ymmt6, ymmt7, 0x31);
440 ymmt0 = _mm256_unpacklo_epi64(ymms0, ymms1);
441 ymmt1 = _mm256_unpacklo_epi64(ymms2, ymms3);
442 ymmt2 = _mm256_unpackhi_epi64(ymms0, ymms1);
443 ymmt3 = _mm256_unpackhi_epi64(ymms2, ymms3);
444 ymmt4 = _mm256_unpacklo_epi64(ymms4, ymms5);
445 ymmt5 = _mm256_unpacklo_epi64(ymms6, ymms7);
446 ymmt6 = _mm256_unpackhi_epi64(ymms4, ymms5);
447 ymmt7 = _mm256_unpackhi_epi64(ymms6, ymms7);
448 ymms0 = _mm256_permute2x128_si256(ymmt0, ymmt1, 0x20);
449 ymms1 = _mm256_permute2x128_si256(ymmt2, ymmt3, 0x20);
450 ymms2 = _mm256_permute2x128_si256(ymmt0, ymmt1, 0x31);
451 ymms3 = _mm256_permute2x128_si256(ymmt2, ymmt3, 0x31);
452 ymms4 = _mm256_permute2x128_si256(ymmt4, ymmt5, 0x20);
453 ymms5 = _mm256_permute2x128_si256(ymmt6, ymmt7, 0x20);
454 ymms6 = _mm256_permute2x128_si256(ymmt4, ymmt5, 0x31);
455 ymms7 = _mm256_permute2x128_si256(ymmt6, ymmt7, 0x31);
469 _mm256_storeu_si256(rptr++, ymms0);
470 _mm256_storeu_si256(rptr++, ymms1);
471 _mm256_storeu_si256(rptr++, ymms2);
472 _mm256_storeu_si256(rptr++, ymms3);
473 _mm256_storeu_si256(rptr++, ymms4);
474 _mm256_storeu_si256(rptr++, ymms5);
475 _mm256_storeu_si256(rptr++, ymms6);
476 _mm256_storeu_si256(rptr++, ymms7);
478 std::array<__m256i, S> s;
479 std::get<0>(s) = ymms0;
480 std::get<1>(s) = ymms1;
481 std::get<2>(s) = ymms2;
482 std::get<3>(s) = ymms3;
483 std::get<4>(s) = ymms4;
484 std::get<5>(s) = ymms5;
485 std::get<6>(s) = ymms6;
486 std::get<7>(s) = ymms7;
487 std::memcpy(rptr, s.data(), n *
sizeof(T) * K);
500 #endif // MCKL_RANDOM_INTERNAL_THREEFRY_AVX2_8X64_HPP static void eval(std::array< std::uint64_t, 8 > &ctr, ResultType *r, const std::array< T, K+4 > &par)
#define MCKL_PUSH_GCC_WARNING(warning)
#define MCKL_RANDOM_INTERNAL_THREEFRY_AVX2_8X64_CYCLE_4(N)
static void eval(const void *plain, void *cipher, const std::array< T, K+4 > &par)
static void eval(const void *plain, void *cipher, const std::array< T, K+4 > &par)
static void eval(const void *plain, void *cipher, 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_AVX2_8X64_CYCLE_8(N)
Default Threefry constants.
static void eval(std::array< std::uint64_t, 8 > &ctr, std::size_t n, ResultType *r, const std::array< T, K+4 > &par)
static void eval(std::array< std::uint64_t, 8 > &ctr, ResultType *r, const std::array< T, K+4 > &par)
#define MCKL_RANDOM_INTERNAL_THREEFRY_AVX2_8X64_KBOX(N)
static void eval(std::array< std::uint64_t, 8 > &ctr, std::size_t n, ResultType *r, const std::array< T, K+4 > &par)
#define MCKL_POP_GCC_WARNING