32 #ifndef MCKL_RANDOM_INTERNAL_THREEFRY_AVX2_4X64_HPP 33 #define MCKL_RANDOM_INTERNAL_THREEFRY_AVX2_4X64_HPP 43 #define MCKL_RANDOM_INTERNAL_THREEFRY_AVX2_4X64_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 ymms0 = _mm256_add_epi64(ymms0, ymmt0); \ 53 ymms1 = _mm256_add_epi64(ymms1, ymmt1); \ 54 ymms2 = _mm256_add_epi64(ymms2, ymmt2); \ 55 ymms3 = _mm256_add_epi64(ymms3, ymmt3); \ 56 ymms4 = _mm256_add_epi64(ymms4, ymmt0); \ 57 ymms5 = _mm256_add_epi64(ymms5, ymmt1); \ 58 ymms6 = _mm256_add_epi64(ymms6, ymmt2); \ 59 ymms7 = _mm256_add_epi64(ymms7, ymmt3); 61 #define MCKL_RANDOM_INTERNAL_THREEFRY_AVX2_4X64_RBOX(N) \ 63 constexpr int L0 = Constants::rotate::value[0][(N - 1) % 8]; \ 64 constexpr int L1 = Constants::rotate::value[1][(N - 1) % 8]; \ 65 constexpr int R0 = 64 - L0; \ 66 constexpr int R1 = 64 - L1; \ 67 ymms0 = _mm256_add_epi64(ymms0, ymms1); \ 68 ymms2 = _mm256_add_epi64(ymms2, ymms3); \ 69 ymms4 = _mm256_add_epi64(ymms4, ymms5); \ 70 ymms6 = _mm256_add_epi64(ymms6, ymms7); \ 71 ymmt1 = _mm256_slli_epi64(ymms1, L0); \ 72 ymmt3 = _mm256_slli_epi64(ymms3, L1); \ 73 ymmt5 = _mm256_slli_epi64(ymms5, L0); \ 74 ymmt7 = _mm256_slli_epi64(ymms7, L1); \ 75 ymms1 = _mm256_srli_epi64(ymms1, R0); \ 76 ymms3 = _mm256_srli_epi64(ymms3, R1); \ 77 ymms5 = _mm256_srli_epi64(ymms5, R0); \ 78 ymms7 = _mm256_srli_epi64(ymms7, R1); \ 79 ymmt1 = _mm256_or_si256(ymms1, ymmt1); \ 80 ymmt3 = _mm256_or_si256(ymms3, ymmt3); \ 81 ymmt5 = _mm256_or_si256(ymms5, ymmt5); \ 82 ymmt7 = _mm256_or_si256(ymms7, ymmt7); \ 83 ymms1 = _mm256_xor_si256(ymms2, ymmt3); \ 84 ymms3 = _mm256_xor_si256(ymms0, ymmt1); \ 85 ymms5 = _mm256_xor_si256(ymms6, ymmt7); \ 86 ymms7 = _mm256_xor_si256(ymms4, ymmt5); \ 89 #define MCKL_RANDOM_INTERNAL_THREEFRY_AVX2_4X64_CYCLE_4(N) \ 90 MCKL_RANDOM_INTERNAL_THREEFRY_AVX2_4X64_RBOX(N * 8 + 1); \ 91 MCKL_RANDOM_INTERNAL_THREEFRY_AVX2_4X64_RBOX(N * 8 + 2); \ 92 MCKL_RANDOM_INTERNAL_THREEFRY_AVX2_4X64_RBOX(N * 8 + 3); \ 93 MCKL_RANDOM_INTERNAL_THREEFRY_AVX2_4X64_RBOX(N * 8 + 4); \ 94 MCKL_RANDOM_INTERNAL_THREEFRY_AVX2_4X64_KBOX(N * 8 + 4); 96 #define MCKL_RANDOM_INTERNAL_THREEFRY_AVX2_4X64_CYCLE_8(N) \ 97 MCKL_RANDOM_INTERNAL_THREEFRY_AVX2_4X64_RBOX(N * 8 + 1); \ 98 MCKL_RANDOM_INTERNAL_THREEFRY_AVX2_4X64_RBOX(N * 8 + 2); \ 99 MCKL_RANDOM_INTERNAL_THREEFRY_AVX2_4X64_RBOX(N * 8 + 3); \ 100 MCKL_RANDOM_INTERNAL_THREEFRY_AVX2_4X64_RBOX(N * 8 + 4); \ 101 MCKL_RANDOM_INTERNAL_THREEFRY_AVX2_4X64_KBOX(N * 8 + 4); \ 102 MCKL_RANDOM_INTERNAL_THREEFRY_AVX2_4X64_RBOX(N * 8 + 5); \ 103 MCKL_RANDOM_INTERNAL_THREEFRY_AVX2_4X64_RBOX(N * 8 + 6); \ 104 MCKL_RANDOM_INTERNAL_THREEFRY_AVX2_4X64_RBOX(N * 8 + 7); \ 105 MCKL_RANDOM_INTERNAL_THREEFRY_AVX2_4X64_RBOX(N * 8 + 8); \ 106 MCKL_RANDOM_INTERNAL_THREEFRY_AVX2_4X64_KBOX(N * 8 + 8); 112 template <
typename T>
115 static_assert(std::numeric_limits<T>::digits == 64,
116 "**Threefry4x64GeneratorAVX2Impl** used with T other than a 64-bit " 117 "unsigned integers");
119 static constexpr std::size_t K = 4;
120 static constexpr std::size_t Rounds = 20;
125 const void *plain,
void *cipher,
const std::array<T, K + 4> &par)
130 template <
typename ResultType>
131 static void eval(std::array<std::uint64_t, 4> &ctr, ResultType *r,
132 const std::array<T, K + 4> &par)
137 template <
typename ResultType>
138 static void eval(std::array<std::uint64_t, 4> &ctr, std::size_t n,
139 ResultType *r,
const std::array<T, K + 4> &par)
141 constexpr std::size_t R =
sizeof(T) * K /
sizeof(ResultType);
143 const std::size_t n0 =
144 static_cast<std::size_t
>(std::min(static_cast<std::uint64_t>(n),
145 std::numeric_limits<std::uint64_t>::max() - ctr.front()));
160 template <
typename ResultType>
161 static void eval_kernel(std::array<std::uint64_t, 4> &ctr, std::size_t n,
162 ResultType *r,
const std::array<T, K + 4> &par)
164 constexpr std::size_t
S = 8;
165 constexpr std::size_t N =
sizeof(__m256i) * S / (
sizeof(T) * K);
168 _mm256_set_epi64x(static_cast<MCKL_INT64>(std::get<3>(ctr)),
169 static_cast<MCKL_INT64>(std::get<2>(ctr)),
170 static_cast<MCKL_INT64>(std::get<1>(ctr)),
171 static_cast<MCKL_INT64>(std::get<0>(ctr)));
174 __m256i *rptr =
reinterpret_cast<__m256i *
>(r);
177 _mm256_add_epi64(ymmc, _mm256_set_epi64x(0, 0, 0, 1));
179 _mm256_add_epi64(ymmc, _mm256_set_epi64x(0, 0, 0, 2));
181 _mm256_add_epi64(ymmc, _mm256_set_epi64x(0, 0, 0, 3));
183 _mm256_add_epi64(ymmc, _mm256_set_epi64x(0, 0, 0, 4));
185 _mm256_add_epi64(ymmc, _mm256_set_epi64x(0, 0, 0, 5));
187 _mm256_add_epi64(ymmc, _mm256_set_epi64x(0, 0, 0, 6));
189 _mm256_add_epi64(ymmc, _mm256_set_epi64x(0, 0, 0, 7));
191 _mm256_add_epi64(ymmc, _mm256_set_epi64x(0, 0, 0, 8));
213 ymmt0 = _mm256_unpacklo_epi64(ymms0, ymms1);
214 ymmt1 = _mm256_unpacklo_epi64(ymms2, ymms3);
215 ymmt2 = _mm256_unpackhi_epi64(ymms0, ymms1);
216 ymmt3 = _mm256_unpackhi_epi64(ymms2, ymms3);
217 ymmt4 = _mm256_unpacklo_epi64(ymms4, ymms5);
218 ymmt5 = _mm256_unpacklo_epi64(ymms6, ymms7);
219 ymmt6 = _mm256_unpackhi_epi64(ymms4, ymms5);
220 ymmt7 = _mm256_unpackhi_epi64(ymms6, ymms7);
221 ymms0 = _mm256_permute2x128_si256(ymmt0, ymmt1, 0x20);
222 ymms1 = _mm256_permute2x128_si256(ymmt2, ymmt3, 0x20);
223 ymms2 = _mm256_permute2x128_si256(ymmt0, ymmt1, 0x31);
224 ymms3 = _mm256_permute2x128_si256(ymmt2, ymmt3, 0x31);
225 ymms4 = _mm256_permute2x128_si256(ymmt4, ymmt5, 0x20);
226 ymms5 = _mm256_permute2x128_si256(ymmt6, ymmt7, 0x20);
227 ymms6 = _mm256_permute2x128_si256(ymmt4, ymmt5, 0x31);
228 ymms7 = _mm256_permute2x128_si256(ymmt6, ymmt7, 0x31);
235 ymmt0 = _mm256_unpacklo_epi64(ymms0, ymms1);
236 ymmt1 = _mm256_unpacklo_epi64(ymms2, ymms3);
237 ymmt2 = _mm256_unpackhi_epi64(ymms0, ymms1);
238 ymmt3 = _mm256_unpackhi_epi64(ymms2, ymms3);
239 ymmt4 = _mm256_unpacklo_epi64(ymms4, ymms5);
240 ymmt5 = _mm256_unpacklo_epi64(ymms6, ymms7);
241 ymmt6 = _mm256_unpackhi_epi64(ymms4, ymms5);
242 ymmt7 = _mm256_unpackhi_epi64(ymms6, ymms7);
243 ymms0 = _mm256_permute2x128_si256(ymmt0, ymmt1, 0x20);
244 ymms1 = _mm256_permute2x128_si256(ymmt2, ymmt3, 0x20);
245 ymms2 = _mm256_permute2x128_si256(ymmt0, ymmt1, 0x31);
246 ymms3 = _mm256_permute2x128_si256(ymmt2, ymmt3, 0x31);
247 ymms4 = _mm256_permute2x128_si256(ymmt4, ymmt5, 0x20);
248 ymms5 = _mm256_permute2x128_si256(ymmt6, ymmt7, 0x20);
249 ymms6 = _mm256_permute2x128_si256(ymmt4, ymmt5, 0x31);
250 ymms7 = _mm256_permute2x128_si256(ymmt6, ymmt7, 0x31);
264 _mm256_storeu_si256(rptr++, ymms0);
265 _mm256_storeu_si256(rptr++, ymms1);
266 _mm256_storeu_si256(rptr++, ymms2);
267 _mm256_storeu_si256(rptr++, ymms3);
268 _mm256_storeu_si256(rptr++, ymms4);
269 _mm256_storeu_si256(rptr++, ymms5);
270 _mm256_storeu_si256(rptr++, ymms6);
271 _mm256_storeu_si256(rptr++, ymms7);
273 std::array<__m256i, S> s;
274 std::get<0>(s) = ymms0;
275 std::get<1>(s) = ymms1;
276 std::get<2>(s) = ymms2;
277 std::get<3>(s) = ymms3;
278 std::get<4>(s) = ymms4;
279 std::get<5>(s) = ymms5;
280 std::get<6>(s) = ymms6;
281 std::get<7>(s) = ymms7;
282 std::memcpy(rptr, s.data(), n *
sizeof(T) * K);
289 template <
typename T>
292 static_assert(std::numeric_limits<T>::digits == 64,
293 "**Threefish256GeneratorAVX2Impl** used with T other than a 64-bit " 294 "unsigned integers");
296 static constexpr std::size_t K = 4;
297 static constexpr std::size_t Rounds = 72;
302 const void *plain,
void *cipher,
const std::array<T, K + 4> &par)
307 template <
typename ResultType>
308 static void eval(std::array<std::uint64_t, 4> &ctr, ResultType *r,
309 const std::array<T, K + 4> &par)
314 template <
typename ResultType>
315 static void eval(std::array<std::uint64_t, 4> &ctr, std::size_t n,
316 ResultType *r,
const std::array<T, K + 4> &par)
318 constexpr std::size_t R =
sizeof(T) * K /
sizeof(ResultType);
320 const std::size_t n0 =
321 static_cast<std::size_t
>(std::min(static_cast<std::uint64_t>(n),
322 std::numeric_limits<std::uint64_t>::max() - ctr.front()));
338 template <
typename ResultType>
339 static void eval_kernel(std::array<std::uint64_t, 4> &ctr, std::size_t n,
340 ResultType *r,
const std::array<T, K + 4> &par)
342 constexpr std::size_t
S = 8;
343 constexpr std::size_t N =
sizeof(__m256i) * S / (
sizeof(T) * K);
346 _mm256_set_epi64x(static_cast<MCKL_INT64>(std::get<3>(ctr)),
347 static_cast<MCKL_INT64>(std::get<2>(ctr)),
348 static_cast<MCKL_INT64>(std::get<1>(ctr)),
349 static_cast<MCKL_INT64>(std::get<0>(ctr)));
352 __m256i *rptr =
reinterpret_cast<__m256i *
>(r);
355 _mm256_add_epi64(ymmc, _mm256_set_epi64x(0, 0, 0, 1));
357 _mm256_add_epi64(ymmc, _mm256_set_epi64x(0, 0, 0, 2));
359 _mm256_add_epi64(ymmc, _mm256_set_epi64x(0, 0, 0, 3));
361 _mm256_add_epi64(ymmc, _mm256_set_epi64x(0, 0, 0, 4));
363 _mm256_add_epi64(ymmc, _mm256_set_epi64x(0, 0, 0, 5));
365 _mm256_add_epi64(ymmc, _mm256_set_epi64x(0, 0, 0, 6));
367 _mm256_add_epi64(ymmc, _mm256_set_epi64x(0, 0, 0, 7));
369 _mm256_add_epi64(ymmc, _mm256_set_epi64x(0, 0, 0, 8));
391 ymmt0 = _mm256_unpacklo_epi64(ymms0, ymms1);
392 ymmt1 = _mm256_unpacklo_epi64(ymms2, ymms3);
393 ymmt2 = _mm256_unpackhi_epi64(ymms0, ymms1);
394 ymmt3 = _mm256_unpackhi_epi64(ymms2, ymms3);
395 ymmt4 = _mm256_unpacklo_epi64(ymms4, ymms5);
396 ymmt5 = _mm256_unpacklo_epi64(ymms6, ymms7);
397 ymmt6 = _mm256_unpackhi_epi64(ymms4, ymms5);
398 ymmt7 = _mm256_unpackhi_epi64(ymms6, ymms7);
399 ymms0 = _mm256_permute2x128_si256(ymmt0, ymmt1, 0x20);
400 ymms1 = _mm256_permute2x128_si256(ymmt2, ymmt3, 0x20);
401 ymms2 = _mm256_permute2x128_si256(ymmt0, ymmt1, 0x31);
402 ymms3 = _mm256_permute2x128_si256(ymmt2, ymmt3, 0x31);
403 ymms4 = _mm256_permute2x128_si256(ymmt4, ymmt5, 0x20);
404 ymms5 = _mm256_permute2x128_si256(ymmt6, ymmt7, 0x20);
405 ymms6 = _mm256_permute2x128_si256(ymmt4, ymmt5, 0x31);
406 ymms7 = _mm256_permute2x128_si256(ymmt6, ymmt7, 0x31);
419 ymmt0 = _mm256_unpacklo_epi64(ymms0, ymms1);
420 ymmt1 = _mm256_unpacklo_epi64(ymms2, ymms3);
421 ymmt2 = _mm256_unpackhi_epi64(ymms0, ymms1);
422 ymmt3 = _mm256_unpackhi_epi64(ymms2, ymms3);
423 ymmt4 = _mm256_unpacklo_epi64(ymms4, ymms5);
424 ymmt5 = _mm256_unpacklo_epi64(ymms6, ymms7);
425 ymmt6 = _mm256_unpackhi_epi64(ymms4, ymms5);
426 ymmt7 = _mm256_unpackhi_epi64(ymms6, ymms7);
427 ymms0 = _mm256_permute2x128_si256(ymmt0, ymmt1, 0x20);
428 ymms1 = _mm256_permute2x128_si256(ymmt2, ymmt3, 0x20);
429 ymms2 = _mm256_permute2x128_si256(ymmt0, ymmt1, 0x31);
430 ymms3 = _mm256_permute2x128_si256(ymmt2, ymmt3, 0x31);
431 ymms4 = _mm256_permute2x128_si256(ymmt4, ymmt5, 0x20);
432 ymms5 = _mm256_permute2x128_si256(ymmt6, ymmt7, 0x20);
433 ymms6 = _mm256_permute2x128_si256(ymmt4, ymmt5, 0x31);
434 ymms7 = _mm256_permute2x128_si256(ymmt6, ymmt7, 0x31);
448 _mm256_storeu_si256(rptr++, ymms0);
449 _mm256_storeu_si256(rptr++, ymms1);
450 _mm256_storeu_si256(rptr++, ymms2);
451 _mm256_storeu_si256(rptr++, ymms3);
452 _mm256_storeu_si256(rptr++, ymms4);
453 _mm256_storeu_si256(rptr++, ymms5);
454 _mm256_storeu_si256(rptr++, ymms6);
455 _mm256_storeu_si256(rptr++, ymms7);
457 std::array<__m256i, S> s;
458 std::get<0>(s) = ymms0;
459 std::get<1>(s) = ymms1;
460 std::get<2>(s) = ymms2;
461 std::get<3>(s) = ymms3;
462 std::get<4>(s) = ymms4;
463 std::get<5>(s) = ymms5;
464 std::get<6>(s) = ymms6;
465 std::get<7>(s) = ymms7;
466 std::memcpy(rptr, s.data(), n *
sizeof(T) * K);
479 #endif // MCKL_RANDOM_INTERNAL_THREEFRY_AVX2_4X64_HPP #define MCKL_PUSH_GCC_WARNING(warning)
static void eval(std::array< std::uint64_t, 4 > &ctr, ResultType *r, const std::array< T, K+4 > &par)
#define MCKL_RANDOM_INTERNAL_THREEFRY_AVX2_4X64_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)
#define MCKL_RANDOM_INTERNAL_THREEFRY_AVX2_4X64_CYCLE_8(N)
Default Threefry constants.
static void eval(const void *plain, void *cipher, const std::array< T, K+4 > &par)
static void eval(std::array< std::uint64_t, 4 > &ctr, std::size_t n, ResultType *r, const std::array< T, K+4 > &par)
static void eval(std::array< std::uint64_t, 4 > &ctr, ResultType *r, 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_kernel(std::array< std::uint64_t, 4 > &ctr, std::size_t n, ResultType *r, const std::array< T, K+4 > &par)
#define MCKL_POP_GCC_WARNING
#define MCKL_RANDOM_INTERNAL_THREEFRY_AVX2_4X64_KBOX(N)
static void eval(std::array< std::uint64_t, 4 > &ctr, std::size_t n, ResultType *r, const std::array< T, K+4 > &par)