32 #ifndef MCKL_RANDOM_INTERNAL_THREEFRY_AVX2_4X32_HPP 33 #define MCKL_RANDOM_INTERNAL_THREEFRY_AVX2_4X32_HPP 42 #define MCKL_RANDOM_INTERNAL_THREEFRY_AVX2_4X32_KBOX(N) \ 43 ymmt0 = _mm256_set1_epi32( \ 44 static_cast<int>(ThreefryKBox<T, K, N>::template key<0>(par))); \ 45 ymmt1 = _mm256_set1_epi32( \ 46 static_cast<int>(ThreefryKBox<T, K, N>::template key<1>(par))); \ 47 ymmt2 = _mm256_set1_epi32( \ 48 static_cast<int>(ThreefryKBox<T, K, N>::template key<2>(par))); \ 49 ymmt3 = _mm256_set1_epi32( \ 50 static_cast<int>(ThreefryKBox<T, K, N>::template key<3>(par))); \ 51 ymms0 = _mm256_add_epi32(ymms0, ymmt0); \ 52 ymms1 = _mm256_add_epi32(ymms1, ymmt1); \ 53 ymms2 = _mm256_add_epi32(ymms2, ymmt2); \ 54 ymms3 = _mm256_add_epi32(ymms3, ymmt3); \ 55 ymms4 = _mm256_add_epi32(ymms4, ymmt0); \ 56 ymms5 = _mm256_add_epi32(ymms5, ymmt1); \ 57 ymms6 = _mm256_add_epi32(ymms6, ymmt2); \ 58 ymms7 = _mm256_add_epi32(ymms7, ymmt3); 60 #define MCKL_RANDOM_INTERNAL_THREEFRY_AVX2_4X32_RBOX(N) \ 62 constexpr int L0 = Constants::rotate::value[0][(N - 1) % 8]; \ 63 constexpr int L1 = Constants::rotate::value[1][(N - 1) % 8]; \ 64 constexpr int R0 = 32 - L0; \ 65 constexpr int R1 = 32 - L1; \ 66 ymms0 = _mm256_add_epi32(ymms0, ymms1); \ 67 ymms2 = _mm256_add_epi32(ymms2, ymms3); \ 68 ymms4 = _mm256_add_epi32(ymms4, ymms5); \ 69 ymms6 = _mm256_add_epi32(ymms6, ymms7); \ 70 ymmt1 = _mm256_slli_epi32(ymms1, L0); \ 71 ymmt3 = _mm256_slli_epi32(ymms3, L1); \ 72 ymmt5 = _mm256_slli_epi32(ymms5, L0); \ 73 ymmt7 = _mm256_slli_epi32(ymms7, L1); \ 74 ymms1 = _mm256_srli_epi32(ymms1, R0); \ 75 ymms3 = _mm256_srli_epi32(ymms3, R1); \ 76 ymms5 = _mm256_srli_epi32(ymms5, R0); \ 77 ymms7 = _mm256_srli_epi32(ymms7, R1); \ 78 ymmt1 = _mm256_or_si256(ymms1, ymmt1); \ 79 ymmt3 = _mm256_or_si256(ymms3, ymmt3); \ 80 ymmt5 = _mm256_or_si256(ymms5, ymmt5); \ 81 ymmt7 = _mm256_or_si256(ymms7, ymmt7); \ 82 ymms1 = _mm256_xor_si256(ymms2, ymmt3); \ 83 ymms3 = _mm256_xor_si256(ymms0, ymmt1); \ 84 ymms5 = _mm256_xor_si256(ymms6, ymmt7); \ 85 ymms7 = _mm256_xor_si256(ymms4, ymmt5); \ 88 #define MCKL_RANDOM_INTERNAL_THREEFRY_AVX2_4X32_CYCLE_4(N) \ 89 MCKL_RANDOM_INTERNAL_THREEFRY_AVX2_4X32_RBOX(N * 8 + 1); \ 90 MCKL_RANDOM_INTERNAL_THREEFRY_AVX2_4X32_RBOX(N * 8 + 2); \ 91 MCKL_RANDOM_INTERNAL_THREEFRY_AVX2_4X32_RBOX(N * 8 + 3); \ 92 MCKL_RANDOM_INTERNAL_THREEFRY_AVX2_4X32_RBOX(N * 8 + 4); \ 93 MCKL_RANDOM_INTERNAL_THREEFRY_AVX2_4X32_KBOX(N * 8 + 4); 95 #define MCKL_RANDOM_INTERNAL_THREEFRY_AVX2_4X32_CYCLE_8(N) \ 96 MCKL_RANDOM_INTERNAL_THREEFRY_AVX2_4X32_RBOX(N * 8 + 1); \ 97 MCKL_RANDOM_INTERNAL_THREEFRY_AVX2_4X32_RBOX(N * 8 + 2); \ 98 MCKL_RANDOM_INTERNAL_THREEFRY_AVX2_4X32_RBOX(N * 8 + 3); \ 99 MCKL_RANDOM_INTERNAL_THREEFRY_AVX2_4X32_RBOX(N * 8 + 4); \ 100 MCKL_RANDOM_INTERNAL_THREEFRY_AVX2_4X32_KBOX(N * 8 + 4); \ 101 MCKL_RANDOM_INTERNAL_THREEFRY_AVX2_4X32_RBOX(N * 8 + 5); \ 102 MCKL_RANDOM_INTERNAL_THREEFRY_AVX2_4X32_RBOX(N * 8 + 6); \ 103 MCKL_RANDOM_INTERNAL_THREEFRY_AVX2_4X32_RBOX(N * 8 + 7); \ 104 MCKL_RANDOM_INTERNAL_THREEFRY_AVX2_4X32_RBOX(N * 8 + 8); \ 105 MCKL_RANDOM_INTERNAL_THREEFRY_AVX2_4X32_KBOX(N * 8 + 8); 111 template <
typename T>
114 static_assert(std::numeric_limits<T>::digits == 32,
115 "**Threefry4x32GeneratorAVX2Impl** used with T other than a " 116 "32-bit unsigned integers");
118 static constexpr std::size_t K = 4;
119 static constexpr std::size_t Rounds = 20;
124 const void *plain,
void *cipher,
const std::array<T, K + 4> &par)
129 template <
typename ResultType>
130 static void eval(std::array<std::uint64_t, 2> &ctr, ResultType *r,
131 const std::array<T, K + 4> &par)
136 template <
typename ResultType>
137 static void eval(std::array<std::uint64_t, 2> &ctr, std::size_t n,
138 ResultType *r,
const std::array<T, K + 4> &par)
140 constexpr std::size_t R =
sizeof(T) * K /
sizeof(ResultType);
142 const std::size_t n0 =
143 static_cast<std::size_t
>(std::min(static_cast<std::uint64_t>(n),
144 std::numeric_limits<std::uint64_t>::max() - ctr.front()));
146 eval_kernel(ctr, n0, r, par);
156 eval_kernel(ctr, n, r, par);
160 template <
typename ResultType>
161 static void eval_kernel(std::array<std::uint64_t, 2> &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<1>(ctr)),
169 static_cast<MCKL_INT64>(std::get<0>(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, 0x02, 0, 0x01));
179 _mm256_add_epi64(ymmc, _mm256_set_epi64x(0, 0x04, 0, 0x03));
181 _mm256_add_epi64(ymmc, _mm256_set_epi64x(0, 0x06, 0, 0x05));
183 _mm256_add_epi64(ymmc, _mm256_set_epi64x(0, 0x08, 0, 0x07));
185 _mm256_add_epi64(ymmc, _mm256_set_epi64x(0, 0x0A, 0, 0x09));
187 _mm256_add_epi64(ymmc, _mm256_set_epi64x(0, 0x0C, 0, 0x0B));
189 _mm256_add_epi64(ymmc, _mm256_set_epi64x(0, 0x0E, 0, 0x0D));
191 _mm256_add_epi64(ymmc, _mm256_set_epi64x(0, 0x10, 0, 0x0F));
192 ymmc = _mm256_add_epi64(ymmc, _mm256_set_epi64x(0, 0x10, 0, 0x10));
194 __m256i ymmt0 = _mm256_unpacklo_epi32(ymms0, ymms1);
195 __m256i ymmt1 = _mm256_unpacklo_epi32(ymms2, ymms3);
196 __m256i ymmt2 = _mm256_unpacklo_epi32(ymms4, ymms5);
197 __m256i ymmt3 = _mm256_unpacklo_epi32(ymms6, ymms7);
198 __m256i ymmt4 = _mm256_unpackhi_epi32(ymms0, ymms1);
199 __m256i ymmt5 = _mm256_unpackhi_epi32(ymms2, ymms3);
200 __m256i ymmt6 = _mm256_unpackhi_epi32(ymms4, ymms5);
201 __m256i ymmt7 = _mm256_unpackhi_epi32(ymms6, ymms7);
202 __m256i ymmt8 = _mm256_unpacklo_epi64(ymmt0, ymmt1);
203 __m256i ymmt9 = _mm256_unpacklo_epi64(ymmt2, ymmt3);
204 __m256i ymmtA = _mm256_unpacklo_epi64(ymmt4, ymmt5);
205 __m256i ymmtB = _mm256_unpacklo_epi64(ymmt6, ymmt7);
206 __m256i ymmtC = _mm256_unpackhi_epi64(ymmt0, ymmt1);
207 __m256i ymmtD = _mm256_unpackhi_epi64(ymmt2, ymmt3);
208 __m256i ymmtE = _mm256_unpackhi_epi64(ymmt4, ymmt5);
209 __m256i ymmtF = _mm256_unpackhi_epi64(ymmt6, ymmt7);
210 ymms0 = _mm256_permute2x128_si256(ymmt8, ymmt9, 0x20);
211 ymms1 = _mm256_permute2x128_si256(ymmtC, ymmtD, 0x20);
212 ymms2 = _mm256_permute2x128_si256(ymmtA, ymmtB, 0x20);
213 ymms3 = _mm256_permute2x128_si256(ymmtE, ymmtF, 0x20);
214 ymms4 = _mm256_permute2x128_si256(ymmt8, ymmt9, 0x31);
215 ymms5 = _mm256_permute2x128_si256(ymmtC, ymmtD, 0x31);
216 ymms6 = _mm256_permute2x128_si256(ymmtA, ymmtB, 0x31);
217 ymms7 = _mm256_permute2x128_si256(ymmtE, ymmtF, 0x31);
224 ymmt0 = _mm256_unpacklo_epi32(ymms0, ymms1);
225 ymmt1 = _mm256_unpacklo_epi32(ymms2, ymms3);
226 ymmt2 = _mm256_unpacklo_epi32(ymms4, ymms5);
227 ymmt3 = _mm256_unpacklo_epi32(ymms6, ymms7);
228 ymmt4 = _mm256_unpackhi_epi32(ymms0, ymms1);
229 ymmt5 = _mm256_unpackhi_epi32(ymms2, ymms3);
230 ymmt6 = _mm256_unpackhi_epi32(ymms4, ymms5);
231 ymmt7 = _mm256_unpackhi_epi32(ymms6, ymms7);
232 ymmt8 = _mm256_unpacklo_epi64(ymmt0, ymmt1);
233 ymmt9 = _mm256_unpacklo_epi64(ymmt2, ymmt3);
234 ymmtA = _mm256_unpacklo_epi64(ymmt4, ymmt5);
235 ymmtB = _mm256_unpacklo_epi64(ymmt6, ymmt7);
236 ymmtC = _mm256_unpackhi_epi64(ymmt0, ymmt1);
237 ymmtD = _mm256_unpackhi_epi64(ymmt2, ymmt3);
238 ymmtE = _mm256_unpackhi_epi64(ymmt4, ymmt5);
239 ymmtF = _mm256_unpackhi_epi64(ymmt6, ymmt7);
240 ymms0 = _mm256_permute2x128_si256(ymmt8, ymmt9, 0x20);
241 ymms1 = _mm256_permute2x128_si256(ymmtC, ymmtD, 0x20);
242 ymms2 = _mm256_permute2x128_si256(ymmtA, ymmtB, 0x20);
243 ymms3 = _mm256_permute2x128_si256(ymmtE, ymmtF, 0x20);
244 ymms4 = _mm256_permute2x128_si256(ymmt8, ymmt9, 0x31);
245 ymms5 = _mm256_permute2x128_si256(ymmtC, ymmtD, 0x31);
246 ymms6 = _mm256_permute2x128_si256(ymmtA, ymmtB, 0x31);
247 ymms7 = _mm256_permute2x128_si256(ymmtE, ymmtF, 0x31);
251 _mm256_storeu_si256(rptr++, ymms0);
252 _mm256_storeu_si256(rptr++, ymms1);
253 _mm256_storeu_si256(rptr++, ymms2);
254 _mm256_storeu_si256(rptr++, ymms3);
255 _mm256_storeu_si256(rptr++, ymms4);
256 _mm256_storeu_si256(rptr++, ymms5);
257 _mm256_storeu_si256(rptr++, ymms6);
258 _mm256_storeu_si256(rptr++, ymms7);
260 std::array<__m256i, S> s;
261 std::get<0>(s) = ymms0;
262 std::get<1>(s) = ymms1;
263 std::get<2>(s) = ymms2;
264 std::get<3>(s) = ymms3;
265 std::get<4>(s) = ymms4;
266 std::get<5>(s) = ymms5;
267 std::get<6>(s) = ymms6;
268 std::get<7>(s) = ymms7;
269 std::memcpy(rptr, s.data(), n *
sizeof(T) * K);
282 #endif // MCKL_RANDOM_INTERNAL_THREEFRY_AVX2_4X32_HPP #define MCKL_RANDOM_INTERNAL_THREEFRY_AVX2_4X32_CYCLE_8(N)
#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, 2 > &ctr, ResultType *r, const std::array< T, K+4 > &par)
Default Threefry constants.
#define MCKL_RANDOM_INTERNAL_THREEFRY_AVX2_4X32_KBOX(N)
static void eval(const void *plain, void *cipher, const std::array< T, K+4 > &par)
#define MCKL_RANDOM_INTERNAL_THREEFRY_AVX2_4X32_CYCLE_4(N)
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_POP_GCC_WARNING