32 #ifndef MCKL_RANDOM_INTERNAL_THREEFRY_SSE2_8X64_HPP 33 #define MCKL_RANDOM_INTERNAL_THREEFRY_SSE2_8X64_HPP 43 #define MCKL_RANDOM_INTERNAL_THREEFRY_SSE2_8X64_KBOX(N) \ 44 xmmt0 = _mm_set1_epi64x(static_cast<MCKL_INT64>( \ 45 ThreefryKBox<T, K, N>::template key<0>(par))); \ 46 xmmt1 = _mm_set1_epi64x(static_cast<MCKL_INT64>( \ 47 ThreefryKBox<T, K, N>::template key<1>(par))); \ 48 xmmt2 = _mm_set1_epi64x(static_cast<MCKL_INT64>( \ 49 ThreefryKBox<T, K, N>::template key<2>(par))); \ 50 xmmt3 = _mm_set1_epi64x(static_cast<MCKL_INT64>( \ 51 ThreefryKBox<T, K, N>::template key<3>(par))); \ 52 xmmt4 = _mm_set1_epi64x(static_cast<MCKL_INT64>( \ 53 ThreefryKBox<T, K, N>::template key<4>(par))); \ 54 xmmt5 = _mm_set1_epi64x(static_cast<MCKL_INT64>( \ 55 ThreefryKBox<T, K, N>::template key<5>(par))); \ 56 xmmt6 = _mm_set1_epi64x(static_cast<MCKL_INT64>( \ 57 ThreefryKBox<T, K, N>::template key<6>(par))); \ 58 xmmt7 = _mm_set1_epi64x(static_cast<MCKL_INT64>( \ 59 ThreefryKBox<T, K, N>::template key<7>(par))); \ 60 xmms0 = _mm_add_epi64(xmms0, xmmt0); \ 61 xmms1 = _mm_add_epi64(xmms1, xmmt1); \ 62 xmms2 = _mm_add_epi64(xmms2, xmmt2); \ 63 xmms3 = _mm_add_epi64(xmms3, xmmt3); \ 64 xmms4 = _mm_add_epi64(xmms4, xmmt4); \ 65 xmms5 = _mm_add_epi64(xmms5, xmmt5); \ 66 xmms6 = _mm_add_epi64(xmms6, xmmt6); \ 67 xmms7 = _mm_add_epi64(xmms7, xmmt7); 69 #define MCKL_RANDOM_INTERNAL_THREEFRY_SSE2_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 xmmt0 = _mm_add_epi64(xmms0, xmms1); \ 80 xmmt2 = _mm_add_epi64(xmms2, xmms3); \ 81 xmmt4 = _mm_add_epi64(xmms4, xmms5); \ 82 xmmt6 = _mm_add_epi64(xmms6, xmms7); \ 83 xmmt1 = _mm_slli_epi64(xmms1, L0); \ 84 xmmt3 = _mm_slli_epi64(xmms3, L1); \ 85 xmmt5 = _mm_slli_epi64(xmms5, L2); \ 86 xmmt7 = _mm_slli_epi64(xmms7, L3); \ 87 xmms1 = _mm_srli_epi64(xmms1, R0); \ 88 xmms3 = _mm_srli_epi64(xmms3, R1); \ 89 xmms5 = _mm_srli_epi64(xmms5, R2); \ 90 xmms7 = _mm_srli_epi64(xmms7, R3); \ 91 xmmt1 = _mm_or_si128(xmms1, xmmt1); \ 92 xmmt3 = _mm_or_si128(xmms3, xmmt3); \ 93 xmmt5 = _mm_or_si128(xmms5, xmmt5); \ 94 xmmt7 = _mm_or_si128(xmms7, xmmt7); \ 99 xmms1 = _mm_xor_si128(xmmt0, xmmt1); \ 100 xmms3 = _mm_xor_si128(xmmt6, xmmt7); \ 101 xmms5 = _mm_xor_si128(xmmt4, xmmt5); \ 102 xmms7 = _mm_xor_si128(xmmt2, xmmt3); \ 105 #define MCKL_RANDOM_INTERNAL_THREEFRY_SSE2_8X64_CYCLE_4(N) \ 106 MCKL_RANDOM_INTERNAL_THREEFRY_SSE2_8X64_RBOX(N * 8 + 1); \ 107 MCKL_RANDOM_INTERNAL_THREEFRY_SSE2_8X64_RBOX(N * 8 + 2); \ 108 MCKL_RANDOM_INTERNAL_THREEFRY_SSE2_8X64_RBOX(N * 8 + 3); \ 109 MCKL_RANDOM_INTERNAL_THREEFRY_SSE2_8X64_RBOX(N * 8 + 4); \ 110 MCKL_RANDOM_INTERNAL_THREEFRY_SSE2_8X64_KBOX(N * 8 + 4); 112 #define MCKL_RANDOM_INTERNAL_THREEFRY_SSE2_8X64_CYCLE_8(N) \ 113 MCKL_RANDOM_INTERNAL_THREEFRY_SSE2_8X64_RBOX(N * 8 + 1); \ 114 MCKL_RANDOM_INTERNAL_THREEFRY_SSE2_8X64_RBOX(N * 8 + 2); \ 115 MCKL_RANDOM_INTERNAL_THREEFRY_SSE2_8X64_RBOX(N * 8 + 3); \ 116 MCKL_RANDOM_INTERNAL_THREEFRY_SSE2_8X64_RBOX(N * 8 + 4); \ 117 MCKL_RANDOM_INTERNAL_THREEFRY_SSE2_8X64_KBOX(N * 8 + 4); \ 118 MCKL_RANDOM_INTERNAL_THREEFRY_SSE2_8X64_RBOX(N * 8 + 5); \ 119 MCKL_RANDOM_INTERNAL_THREEFRY_SSE2_8X64_RBOX(N * 8 + 6); \ 120 MCKL_RANDOM_INTERNAL_THREEFRY_SSE2_8X64_RBOX(N * 8 + 7); \ 121 MCKL_RANDOM_INTERNAL_THREEFRY_SSE2_8X64_RBOX(N * 8 + 8); \ 122 MCKL_RANDOM_INTERNAL_THREEFRY_SSE2_8X64_KBOX(N * 8 + 8); 128 template <
typename T>
131 static_assert(std::numeric_limits<T>::digits == 64,
132 "**Threefry8x64GeneratorSSE2Impl** 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(__m128i) * S / (
sizeof(T) * K);
185 _mm_set_epi64x(static_cast<MCKL_INT64>(std::get<1>(ctr)),
186 static_cast<MCKL_INT64>(std::get<0>(ctr)));
188 _mm_set_epi64x(static_cast<MCKL_INT64>(std::get<3>(ctr)),
189 static_cast<MCKL_INT64>(std::get<2>(ctr)));
191 _mm_set_epi64x(static_cast<MCKL_INT64>(std::get<5>(ctr)),
192 static_cast<MCKL_INT64>(std::get<4>(ctr)));
194 _mm_set_epi64x(static_cast<MCKL_INT64>(std::get<7>(ctr)),
195 static_cast<MCKL_INT64>(std::get<6>(ctr)));
198 __m128i *rptr =
reinterpret_cast<__m128i *
>(r);
200 __m128i xmmt0 = _mm_add_epi64(xmmc0, _mm_set_epi64x(0, 1));
201 __m128i xmmt4 = _mm_add_epi64(xmmc0, _mm_set_epi64x(0, 2));
204 __m128i xmmt1 = xmmc1;
205 __m128i xmmt2 = xmmc2;
206 __m128i xmmt3 = xmmc3;
207 __m128i xmmt5 = xmmc1;
208 __m128i xmmt6 = xmmc2;
209 __m128i xmmt7 = xmmc3;
230 xmms0 = _mm_unpacklo_epi64(xmmt0, xmmt1);
231 xmms1 = _mm_unpackhi_epi64(xmmt0, xmmt1);
232 xmms2 = _mm_unpacklo_epi64(xmmt2, xmmt3);
233 xmms3 = _mm_unpackhi_epi64(xmmt2, xmmt3);
234 xmms4 = _mm_unpacklo_epi64(xmmt4, xmmt5);
235 xmms5 = _mm_unpackhi_epi64(xmmt4, xmmt5);
236 xmms6 = _mm_unpacklo_epi64(xmmt6, xmmt7);
237 xmms7 = _mm_unpackhi_epi64(xmmt6, xmmt7);
244 xmmt0 = _mm_unpacklo_epi64(xmms0, xmms1);
245 xmmt1 = _mm_unpackhi_epi64(xmms0, xmms1);
246 xmmt2 = _mm_unpacklo_epi64(xmms2, xmms3);
247 xmmt3 = _mm_unpackhi_epi64(xmms2, xmms3);
248 xmmt4 = _mm_unpacklo_epi64(xmms4, xmms5);
249 xmmt5 = _mm_unpackhi_epi64(xmms4, xmms5);
250 xmmt6 = _mm_unpacklo_epi64(xmms6, xmms7);
251 xmmt7 = _mm_unpackhi_epi64(xmms6, xmms7);
265 _mm_storeu_si128(rptr++, xmmt0);
266 _mm_storeu_si128(rptr++, xmmt1);
267 _mm_storeu_si128(rptr++, xmmt2);
268 _mm_storeu_si128(rptr++, xmmt3);
269 _mm_storeu_si128(rptr++, xmmt4);
270 _mm_storeu_si128(rptr++, xmmt5);
271 _mm_storeu_si128(rptr++, xmmt6);
272 _mm_storeu_si128(rptr++, xmmt7);
274 std::array<__m128i, S> s;
275 std::get<0>(s) = xmmt0;
276 std::get<1>(s) = xmmt1;
277 std::get<2>(s) = xmmt2;
278 std::get<3>(s) = xmmt3;
279 std::get<4>(s) = xmmt4;
280 std::get<5>(s) = xmmt5;
281 std::get<6>(s) = xmmt6;
282 std::get<7>(s) = xmmt7;
283 std::memcpy(rptr, s.data(), n *
sizeof(T) * K);
290 template <
typename T>
293 static_assert(std::numeric_limits<T>::digits == 64,
294 "**Threefish512GeneratorSSE2Impl** used with T other than a 64-bit " 295 "unsigned integers");
297 static constexpr std::size_t K = 8;
298 static constexpr std::size_t Rounds = 20;
303 const void *plain,
void *cipher,
const std::array<T, K + 4> &par)
308 template <
typename ResultType>
309 static void eval(std::array<std::uint64_t, 8> &ctr, ResultType *r,
310 const std::array<T, K + 4> &par)
315 template <
typename ResultType>
316 static void eval(std::array<std::uint64_t, 8> &ctr, std::size_t n,
317 ResultType *r,
const std::array<T, K + 4> &par)
319 constexpr std::size_t R =
sizeof(T) * K /
sizeof(ResultType);
321 const std::size_t n0 =
322 static_cast<std::size_t
>(std::min(static_cast<std::uint64_t>(n),
323 std::numeric_limits<std::uint64_t>::max() - ctr.front()));
325 eval_kernel(ctr, n0, r, par);
335 eval_kernel(ctr, n, r, par);
338 template <
typename ResultType>
339 static void eval_kernel(std::array<std::uint64_t, 8> &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(__m128i) * S / (
sizeof(T) * K);
346 _mm_set_epi64x(static_cast<MCKL_INT64>(std::get<1>(ctr)),
347 static_cast<MCKL_INT64>(std::get<0>(ctr)));
349 _mm_set_epi64x(static_cast<MCKL_INT64>(std::get<3>(ctr)),
350 static_cast<MCKL_INT64>(std::get<2>(ctr)));
352 _mm_set_epi64x(static_cast<MCKL_INT64>(std::get<5>(ctr)),
353 static_cast<MCKL_INT64>(std::get<4>(ctr)));
355 _mm_set_epi64x(static_cast<MCKL_INT64>(std::get<7>(ctr)),
356 static_cast<MCKL_INT64>(std::get<6>(ctr)));
359 __m128i *rptr =
reinterpret_cast<__m128i *
>(r);
361 __m128i xmmt0 = _mm_add_epi64(xmmc0, _mm_set_epi64x(0, 1));
362 __m128i xmmt4 = _mm_add_epi64(xmmc0, _mm_set_epi64x(0, 2));
365 __m128i xmmt1 = xmmc1;
366 __m128i xmmt2 = xmmc2;
367 __m128i xmmt3 = xmmc3;
368 __m128i xmmt5 = xmmc1;
369 __m128i xmmt6 = xmmc2;
370 __m128i xmmt7 = xmmc3;
391 xmms0 = _mm_unpacklo_epi64(xmmt0, xmmt1);
392 xmms1 = _mm_unpackhi_epi64(xmmt0, xmmt1);
393 xmms2 = _mm_unpacklo_epi64(xmmt2, xmmt3);
394 xmms3 = _mm_unpackhi_epi64(xmmt2, xmmt3);
395 xmms4 = _mm_unpacklo_epi64(xmmt4, xmmt5);
396 xmms5 = _mm_unpackhi_epi64(xmmt4, xmmt5);
397 xmms6 = _mm_unpacklo_epi64(xmmt6, xmmt7);
398 xmms7 = _mm_unpackhi_epi64(xmmt6, xmmt7);
411 xmmt0 = _mm_unpacklo_epi64(xmms0, xmms1);
412 xmmt1 = _mm_unpackhi_epi64(xmms0, xmms1);
413 xmmt2 = _mm_unpacklo_epi64(xmms2, xmms3);
414 xmmt3 = _mm_unpackhi_epi64(xmms2, xmms3);
415 xmmt4 = _mm_unpacklo_epi64(xmms4, xmms5);
416 xmmt5 = _mm_unpackhi_epi64(xmms4, xmms5);
417 xmmt6 = _mm_unpacklo_epi64(xmms6, xmms7);
418 xmmt7 = _mm_unpackhi_epi64(xmms6, xmms7);
432 _mm_storeu_si128(rptr++, xmmt0);
433 _mm_storeu_si128(rptr++, xmmt1);
434 _mm_storeu_si128(rptr++, xmmt2);
435 _mm_storeu_si128(rptr++, xmmt3);
436 _mm_storeu_si128(rptr++, xmmt4);
437 _mm_storeu_si128(rptr++, xmmt5);
438 _mm_storeu_si128(rptr++, xmmt6);
439 _mm_storeu_si128(rptr++, xmmt7);
441 std::array<__m128i, S> s;
442 std::get<0>(s) = xmmt0;
443 std::get<1>(s) = xmmt1;
444 std::get<2>(s) = xmmt2;
445 std::get<3>(s) = xmmt3;
446 std::get<4>(s) = xmmt4;
447 std::get<5>(s) = xmmt5;
448 std::get<6>(s) = xmmt6;
449 std::get<7>(s) = xmmt7;
450 std::memcpy(rptr, s.data(), n *
sizeof(T) * K);
463 #endif // MCKL_RANDOM_INTERNAL_THREEFRY_SSE2_8X64_HPP
#define MCKL_PUSH_GCC_WARNING(warning)
static void eval(const void *plain, void *cipher, 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)
static void eval(const void *plain, void *cipher, const std::array< T, K+4 > &par)
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_RANDOM_INTERNAL_THREEFRY_SSE2_8X64_CYCLE_8(N)
#define MCKL_RANDOM_INTERNAL_THREEFRY_SSE2_8X64_CYCLE_4(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)
static void eval(const void *plain, void *cipher, const std::array< T, K+4 > &par)
static void eval_kernel(std::array< std::uint64_t, 8 > &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_SSE2_8X64_KBOX(N)
#define MCKL_POP_GCC_WARNING