32 #ifndef MCKL_RANDOM_INTERNAL_THREEFRY_AVX2_2X64_HPP 33 #define MCKL_RANDOM_INTERNAL_THREEFRY_AVX2_2X64_HPP 43 #define MCKL_RANDOM_INTERNAL_THREEFRY_AVX2_2X64_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 ymms0 = _mm256_add_epi64(ymms0, ymmt0); \ 49 ymms1 = _mm256_add_epi64(ymms1, ymmt1); \ 50 ymms2 = _mm256_add_epi64(ymms2, ymmt0); \ 51 ymms3 = _mm256_add_epi64(ymms3, ymmt1); \ 52 ymms4 = _mm256_add_epi64(ymms4, ymmt0); \ 53 ymms5 = _mm256_add_epi64(ymms5, ymmt1); \ 54 ymms6 = _mm256_add_epi64(ymms6, ymmt0); \ 55 ymms7 = _mm256_add_epi64(ymms7, ymmt1); 57 #define MCKL_RANDOM_INTERNAL_THREEFRY_AVX2_2X64_RBOX(N) \ 59 constexpr int L0 = Constants::rotate::value[0][(N - 1) % 8]; \ 60 constexpr int R0 = 64 - L0; \ 61 ymms0 = _mm256_add_epi64(ymms0, ymms1); \ 62 ymms2 = _mm256_add_epi64(ymms2, ymms3); \ 63 ymms4 = _mm256_add_epi64(ymms4, ymms5); \ 64 ymms6 = _mm256_add_epi64(ymms6, ymms7); \ 65 ymmt1 = _mm256_slli_epi64(ymms1, L0); \ 66 ymmt3 = _mm256_slli_epi64(ymms3, L0); \ 67 ymmt5 = _mm256_slli_epi64(ymms5, L0); \ 68 ymmt7 = _mm256_slli_epi64(ymms7, L0); \ 69 ymms1 = _mm256_srli_epi64(ymms1, R0); \ 70 ymms3 = _mm256_srli_epi64(ymms3, R0); \ 71 ymms5 = _mm256_srli_epi64(ymms5, R0); \ 72 ymms7 = _mm256_srli_epi64(ymms7, R0); \ 73 ymmt1 = _mm256_or_si256(ymms1, ymmt1); \ 74 ymmt3 = _mm256_or_si256(ymms3, ymmt3); \ 75 ymmt5 = _mm256_or_si256(ymms5, ymmt5); \ 76 ymmt7 = _mm256_or_si256(ymms7, ymmt7); \ 77 ymms1 = _mm256_xor_si256(ymms0, ymmt1); \ 78 ymms3 = _mm256_xor_si256(ymms2, ymmt3); \ 79 ymms5 = _mm256_xor_si256(ymms4, ymmt5); \ 80 ymms7 = _mm256_xor_si256(ymms6, ymmt7); \ 83 #define MCKL_RANDOM_INTERNAL_THREEFRY_AVX2_2X64_CYCLE_4(N) \ 84 MCKL_RANDOM_INTERNAL_THREEFRY_AVX2_2X64_RBOX(N * 8 + 1); \ 85 MCKL_RANDOM_INTERNAL_THREEFRY_AVX2_2X64_RBOX(N * 8 + 2); \ 86 MCKL_RANDOM_INTERNAL_THREEFRY_AVX2_2X64_RBOX(N * 8 + 3); \ 87 MCKL_RANDOM_INTERNAL_THREEFRY_AVX2_2X64_RBOX(N * 8 + 4); \ 88 MCKL_RANDOM_INTERNAL_THREEFRY_AVX2_2X64_KBOX(N * 8 + 4); 90 #define MCKL_RANDOM_INTERNAL_THREEFRY_AVX2_2X64_CYCLE_8(N) \ 91 MCKL_RANDOM_INTERNAL_THREEFRY_AVX2_2X64_RBOX(N * 8 + 1); \ 92 MCKL_RANDOM_INTERNAL_THREEFRY_AVX2_2X64_RBOX(N * 8 + 2); \ 93 MCKL_RANDOM_INTERNAL_THREEFRY_AVX2_2X64_RBOX(N * 8 + 3); \ 94 MCKL_RANDOM_INTERNAL_THREEFRY_AVX2_2X64_RBOX(N * 8 + 4); \ 95 MCKL_RANDOM_INTERNAL_THREEFRY_AVX2_2X64_KBOX(N * 8 + 4); \ 96 MCKL_RANDOM_INTERNAL_THREEFRY_AVX2_2X64_RBOX(N * 8 + 5); \ 97 MCKL_RANDOM_INTERNAL_THREEFRY_AVX2_2X64_RBOX(N * 8 + 6); \ 98 MCKL_RANDOM_INTERNAL_THREEFRY_AVX2_2X64_RBOX(N * 8 + 7); \ 99 MCKL_RANDOM_INTERNAL_THREEFRY_AVX2_2X64_RBOX(N * 8 + 8); \ 100 MCKL_RANDOM_INTERNAL_THREEFRY_AVX2_2X64_KBOX(N * 8 + 8); 106 template <
typename T>
109 static_assert(std::numeric_limits<T>::digits == 64,
110 "**Threefry2x64GeneratorAVX2Impl** used with T other than a 64-bit " 111 "unsigned integers");
113 static constexpr std::size_t K = 2;
114 static constexpr std::size_t Rounds = 20;
119 const void *plain,
void *cipher,
const std::array<T, K + 4> &par)
124 template <
typename ResultType>
125 static void eval(std::array<std::uint64_t, 2> &ctr, ResultType *r,
126 const std::array<T, K + 4> &par)
131 template <
typename ResultType>
132 static void eval(std::array<std::uint64_t, 2> &ctr, std::size_t n,
133 ResultType *r,
const std::array<T, K + 4> &par)
135 constexpr std::size_t R =
sizeof(T) * K /
sizeof(ResultType);
137 const std::size_t n0 =
138 static_cast<std::size_t
>(std::min(static_cast<std::uint64_t>(n),
139 std::numeric_limits<std::uint64_t>::max() - ctr.front()));
141 eval_kernel(ctr, n0, r, par);
151 eval_kernel(ctr, n, r, par);
155 template <
typename ResultType>
156 static void eval_kernel(std::array<std::uint64_t, 2> &ctr, std::size_t n,
157 ResultType *r,
const std::array<T, K + 4> &par)
159 constexpr std::size_t
S = 8;
160 constexpr std::size_t N =
sizeof(__m256i) * S / (
sizeof(T) * K);
163 _mm256_set_epi64x(static_cast<MCKL_INT64>(std::get<1>(ctr)),
164 static_cast<MCKL_INT64>(std::get<0>(ctr)),
165 static_cast<MCKL_INT64>(std::get<1>(ctr)),
166 static_cast<MCKL_INT64>(std::get<0>(ctr)));
169 __m256i *rptr =
reinterpret_cast<__m256i *
>(r);
172 _mm256_add_epi64(ymmc, _mm256_set_epi64x(0, 0x02, 0, 0x01));
174 _mm256_add_epi64(ymmc, _mm256_set_epi64x(0, 0x04, 0, 0x03));
176 _mm256_add_epi64(ymmc, _mm256_set_epi64x(0, 0x06, 0, 0x05));
178 _mm256_add_epi64(ymmc, _mm256_set_epi64x(0, 0x08, 0, 0x07));
180 _mm256_add_epi64(ymmc, _mm256_set_epi64x(0, 0x0A, 0, 0x09));
182 _mm256_add_epi64(ymmc, _mm256_set_epi64x(0, 0x0C, 0, 0x0B));
184 _mm256_add_epi64(ymmc, _mm256_set_epi64x(0, 0x0E, 0, 0x0D));
186 _mm256_add_epi64(ymmc, _mm256_set_epi64x(0, 0x10, 0, 0x0F));
187 ymmc = _mm256_add_epi64(ymmc, _mm256_set_epi64x(0, 0x10, 0, 0x10));
208 ymmt0 = _mm256_unpacklo_epi64(ymms0, ymms1);
209 ymmt1 = _mm256_unpacklo_epi64(ymms2, ymms3);
210 ymmt2 = _mm256_unpackhi_epi64(ymms0, ymms1);
211 ymmt3 = _mm256_unpackhi_epi64(ymms2, ymms3);
212 ymmt4 = _mm256_unpacklo_epi64(ymms4, ymms5);
213 ymmt5 = _mm256_unpacklo_epi64(ymms6, ymms7);
214 ymmt6 = _mm256_unpackhi_epi64(ymms4, ymms5);
215 ymmt7 = _mm256_unpackhi_epi64(ymms6, ymms7);
216 ymms0 = _mm256_permute2x128_si256(ymmt0, ymmt1, 0x20);
217 ymms1 = _mm256_permute2x128_si256(ymmt2, ymmt3, 0x20);
218 ymms2 = _mm256_permute2x128_si256(ymmt0, ymmt1, 0x31);
219 ymms3 = _mm256_permute2x128_si256(ymmt2, ymmt3, 0x31);
220 ymms4 = _mm256_permute2x128_si256(ymmt4, ymmt5, 0x20);
221 ymms5 = _mm256_permute2x128_si256(ymmt6, ymmt7, 0x20);
222 ymms6 = _mm256_permute2x128_si256(ymmt4, ymmt5, 0x31);
223 ymms7 = _mm256_permute2x128_si256(ymmt6, ymmt7, 0x31);
230 ymmt0 = _mm256_unpacklo_epi64(ymms0, ymms1);
231 ymmt1 = _mm256_unpacklo_epi64(ymms2, ymms3);
232 ymmt2 = _mm256_unpackhi_epi64(ymms0, ymms1);
233 ymmt3 = _mm256_unpackhi_epi64(ymms2, ymms3);
234 ymmt4 = _mm256_unpacklo_epi64(ymms4, ymms5);
235 ymmt5 = _mm256_unpacklo_epi64(ymms6, ymms7);
236 ymmt6 = _mm256_unpackhi_epi64(ymms4, ymms5);
237 ymmt7 = _mm256_unpackhi_epi64(ymms6, ymms7);
238 ymms0 = _mm256_permute2x128_si256(ymmt0, ymmt1, 0x20);
239 ymms1 = _mm256_permute2x128_si256(ymmt2, ymmt3, 0x20);
240 ymms2 = _mm256_permute2x128_si256(ymmt0, ymmt1, 0x31);
241 ymms3 = _mm256_permute2x128_si256(ymmt2, ymmt3, 0x31);
242 ymms4 = _mm256_permute2x128_si256(ymmt4, ymmt5, 0x20);
243 ymms5 = _mm256_permute2x128_si256(ymmt6, ymmt7, 0x20);
244 ymms6 = _mm256_permute2x128_si256(ymmt4, ymmt5, 0x31);
245 ymms7 = _mm256_permute2x128_si256(ymmt6, ymmt7, 0x31);
259 _mm256_storeu_si256(rptr++, ymms0);
260 _mm256_storeu_si256(rptr++, ymms1);
261 _mm256_storeu_si256(rptr++, ymms2);
262 _mm256_storeu_si256(rptr++, ymms3);
263 _mm256_storeu_si256(rptr++, ymms4);
264 _mm256_storeu_si256(rptr++, ymms5);
265 _mm256_storeu_si256(rptr++, ymms6);
266 _mm256_storeu_si256(rptr++, ymms7);
268 std::array<__m256i, S> s;
269 std::get<0>(s) = ymms0;
270 std::get<1>(s) = ymms1;
271 std::get<2>(s) = ymms2;
272 std::get<3>(s) = ymms3;
273 std::get<4>(s) = ymms4;
274 std::get<5>(s) = ymms5;
275 std::get<6>(s) = ymms6;
276 std::get<7>(s) = ymms7;
277 std::memcpy(rptr, s.data(), n *
sizeof(T) * K);
290 #endif // MCKL_RANDOM_INTERNAL_THREEFRY_AVX2_2X64_HPP #define MCKL_PUSH_GCC_WARNING(warning)
static void eval(std::array< std::uint64_t, 2 > &ctr, std::size_t n, ResultType *r, const std::array< T, K+4 > &par)
#define MCKL_RANDOM_INTERNAL_THREEFRY_AVX2_2X64_KBOX(N)
#define MCKL_RANDOM_INTERNAL_THREEFRY_AVX2_2X64_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, 2 > &ctr, ResultType *r, const std::array< T, K+4 > &par)
#define MCKL_RANDOM_INTERNAL_THREEFRY_AVX2_2X64_CYCLE_4(N)
static void eval(const void *plain, void *cipher, const std::array< T, K+4 > &par)
#define MCKL_POP_GCC_WARNING