32 #ifndef MCKL_RANDOM_INTERNAL_THREEFRY_AVX2_32_HPP 33 #define MCKL_RANDOM_INTERNAL_THREEFRY_AVX2_32_HPP 50 template <
typename T, std::
size_t K, std::
size_t Rounds,
typename Constants>
55 const void *plain,
void *cipher,
const std::array<T, K + 4> &par)
61 template <
typename ResultType>
63 Counter<T, K> &ctr, ResultType *r,
const std::array<T, K + 4> &par)
69 template <
typename ResultType>
71 const std::array<T, K + 4> &par)
73 constexpr std::size_t
S = K <= 8 ? 8 : K;
74 constexpr std::size_t N =
sizeof(__m256i) * S / (
sizeof(T) * K);
75 constexpr std::size_t R =
sizeof(T) * K /
sizeof(ResultType);
78 std::array<__m256i, S> s;
83 std::memcpy(r, s.data(),
sizeof(T) * K * N);
90 ctr, n, t.data(), par);
91 std::memcpy(r, t.data(),
sizeof(T) * K * n);
95 template <std::
size_t, std::
size_t S>
96 static void round(std::array<__m256i, S> &,
const std::array<T, K + 4> &,
101 template <std::
size_t N, std::
size_t S>
102 static void round(std::array<__m256i, S> &s,
103 const std::array<T, K + 4> &par, std::true_type)
108 template <std::
size_t N, std::
size_t S>
110 std::array<__m256i, S> &s,
const std::array<T, K + 4> &par)
113 std::integral_constant<bool, (N % 4 == 0 && N <= Rounds)>());
116 template <std::
size_t, std::
size_t S>
117 static void kbox(std::array<__m256i, S> &,
const std::array<T, K + 4> &,
122 template <std::
size_t N>
123 static void kbox(std::array<__m256i, 8> &s,
124 const std::array<T, K + 4> &par, std::true_type)
126 std::array<__m256i, K> k;
129 std::get<0>(s) = _mm256_add_epi32(std::get<0>(s), std::get<0 % K>(k));
130 std::get<1>(s) = _mm256_add_epi32(std::get<1>(s), std::get<1 % K>(k));
131 std::get<2>(s) = _mm256_add_epi32(std::get<2>(s), std::get<2 % K>(k));
132 std::get<3>(s) = _mm256_add_epi32(std::get<3>(s), std::get<3 % K>(k));
133 std::get<4>(s) = _mm256_add_epi32(std::get<4>(s), std::get<4 % K>(k));
134 std::get<5>(s) = _mm256_add_epi32(std::get<5>(s), std::get<5 % K>(k));
135 std::get<6>(s) = _mm256_add_epi32(std::get<6>(s), std::get<6 % K>(k));
136 std::get<7>(s) = _mm256_add_epi32(std::get<7>(s), std::get<7 % K>(k));
139 template <std::
size_t N>
140 static void kbox(std::array<__m256i, 16> &s,
141 const std::array<T, K + 4> &par, std::true_type)
143 std::array<__m256i, K> k;
147 _mm256_add_epi32(std::get<0x0>(s), std::get<0x0 % K>(k));
149 _mm256_add_epi32(std::get<0x1>(s), std::get<0x1 % K>(k));
151 _mm256_add_epi32(std::get<0x2>(s), std::get<0x2 % K>(k));
153 _mm256_add_epi32(std::get<0x3>(s), std::get<0x3 % K>(k));
155 _mm256_add_epi32(std::get<0x4>(s), std::get<0x4 % K>(k));
157 _mm256_add_epi32(std::get<0x5>(s), std::get<0x5 % K>(k));
159 _mm256_add_epi32(std::get<0x6>(s), std::get<0x6 % K>(k));
161 _mm256_add_epi32(std::get<0x7>(s), std::get<0x7 % K>(k));
163 _mm256_add_epi32(std::get<0x8>(s), std::get<0x8 % K>(k));
165 _mm256_add_epi32(std::get<0x9>(s), std::get<0x9 % K>(k));
167 _mm256_add_epi32(std::get<0xA>(s), std::get<0xA % K>(k));
169 _mm256_add_epi32(std::get<0xB>(s), std::get<0xB % K>(k));
171 _mm256_add_epi32(std::get<0xC>(s), std::get<0xC % K>(k));
173 _mm256_add_epi32(std::get<0xD>(s), std::get<0xD % K>(k));
175 _mm256_add_epi32(std::get<0xE>(s), std::get<0xE % K>(k));
177 _mm256_add_epi32(std::get<0xF>(s), std::get<0xF % K>(k));
180 template <std::
size_t N, std::
size_t S>
181 MCKL_INLINE static void rbox(std::array<__m256i, S> &s)
183 rbox<N>(s, std::integral_constant<bool, (N > 0 && N <= Rounds)>());
186 template <std::
size_t, std::
size_t S>
187 static void rbox(std::array<__m256i, S> &, std::false_type)
191 template <std::
size_t N>
192 static void rbox(std::array<__m256i, 8> &s, std::true_type)
194 constexpr
int L0 = Constants::rotate::value[0 % (K / 2)][(N - 1) % 8];
195 constexpr
int L1 = Constants::rotate::value[1 % (K / 2)][(N - 1) % 8];
196 constexpr
int L2 = Constants::rotate::value[2 % (K / 2)][(N - 1) % 8];
197 constexpr
int L3 = Constants::rotate::value[3 % (K / 2)][(N - 1) % 8];
198 constexpr
int R0 = 32 - L0;
199 constexpr
int R1 = 32 - L1;
200 constexpr
int R2 = 32 - L2;
201 constexpr
int R3 = 32 - L3;
203 std::get<0>(s) = _mm256_add_epi32(std::get<0>(s), std::get<1>(s));
204 std::get<2>(s) = _mm256_add_epi32(std::get<2>(s), std::get<3>(s));
205 std::get<4>(s) = _mm256_add_epi32(std::get<4>(s), std::get<5>(s));
206 std::get<6>(s) = _mm256_add_epi32(std::get<6>(s), std::get<7>(s));
208 __m256i l0 = _mm256_slli_epi32(std::get<1>(s), L0);
209 __m256i l1 = _mm256_slli_epi32(std::get<3>(s), L1);
210 __m256i l2 = _mm256_slli_epi32(std::get<5>(s), L2);
211 __m256i l3 = _mm256_slli_epi32(std::get<7>(s), L3);
213 __m256i r0 = _mm256_srli_epi32(std::get<1>(s), R0);
214 __m256i r1 = _mm256_srli_epi32(std::get<3>(s), R1);
215 __m256i r2 = _mm256_srli_epi32(std::get<5>(s), R2);
216 __m256i r3 = _mm256_srli_epi32(std::get<7>(s), R3);
218 std::get<1>(s) = _mm256_or_si256(l0, r0);
219 std::get<3>(s) = _mm256_or_si256(l1, r1);
220 std::get<5>(s) = _mm256_or_si256(l2, r2);
221 std::get<7>(s) = _mm256_or_si256(l3, r3);
223 std::get<1>(s) = _mm256_xor_si256(std::get<0>(s), std::get<1>(s));
224 std::get<3>(s) = _mm256_xor_si256(std::get<2>(s), std::get<3>(s));
225 std::get<5>(s) = _mm256_xor_si256(std::get<4>(s), std::get<5>(s));
226 std::get<7>(s) = _mm256_xor_si256(std::get<6>(s), std::get<7>(s));
231 template <std::
size_t N>
232 static void rbox(std::array<__m256i, 16> &s, std::true_type)
234 constexpr
int L0 = Constants::rotate::value[0 % (K / 2)][(N - 1) % 8];
235 constexpr
int L1 = Constants::rotate::value[1 % (K / 2)][(N - 1) % 8];
236 constexpr
int L2 = Constants::rotate::value[2 % (K / 2)][(N - 1) % 8];
237 constexpr
int L3 = Constants::rotate::value[3 % (K / 2)][(N - 1) % 8];
238 constexpr
int L4 = Constants::rotate::value[4 % (K / 2)][(N - 1) % 8];
239 constexpr
int L5 = Constants::rotate::value[5 % (K / 2)][(N - 1) % 8];
240 constexpr
int L6 = Constants::rotate::value[6 % (K / 2)][(N - 1) % 8];
241 constexpr
int L7 = Constants::rotate::value[7 % (K / 2)][(N - 1) % 8];
242 constexpr
int R0 = 32 - L0;
243 constexpr
int R1 = 32 - L1;
244 constexpr
int R2 = 32 - L2;
245 constexpr
int R3 = 32 - L3;
246 constexpr
int R4 = 32 - L4;
247 constexpr
int R5 = 32 - L5;
248 constexpr
int R6 = 32 - L6;
249 constexpr
int R7 = 32 - L7;
252 _mm256_add_epi32(std::get<0x0>(s), std::get<0x1>(s));
254 _mm256_add_epi32(std::get<0x2>(s), std::get<0x3>(s));
256 _mm256_add_epi32(std::get<0x4>(s), std::get<0x5>(s));
258 _mm256_add_epi32(std::get<0x6>(s), std::get<0x7>(s));
260 _mm256_add_epi32(std::get<0x8>(s), std::get<0x9>(s));
262 _mm256_add_epi32(std::get<0xA>(s), std::get<0xB>(s));
264 _mm256_add_epi32(std::get<0xC>(s), std::get<0xD>(s));
266 _mm256_add_epi32(std::get<0xE>(s), std::get<0xF>(s));
268 __m256i l0 = _mm256_slli_epi32(std::get<0x1>(s), L0);
269 __m256i l1 = _mm256_slli_epi32(std::get<0x3>(s), L1);
270 __m256i l2 = _mm256_slli_epi32(std::get<0x5>(s), L2);
271 __m256i l3 = _mm256_slli_epi32(std::get<0x7>(s), L3);
272 __m256i l4 = _mm256_slli_epi32(std::get<0x9>(s), L4);
273 __m256i l5 = _mm256_slli_epi32(std::get<0xB>(s), L5);
274 __m256i l6 = _mm256_slli_epi32(std::get<0xD>(s), L6);
275 __m256i l7 = _mm256_slli_epi32(std::get<0xF>(s), L7);
277 std::get<0x1>(s) = _mm256_srli_epi32(std::get<0x1>(s), R0);
278 std::get<0x3>(s) = _mm256_srli_epi32(std::get<0x3>(s), R1);
279 std::get<0x5>(s) = _mm256_srli_epi32(std::get<0x5>(s), R2);
280 std::get<0x7>(s) = _mm256_srli_epi32(std::get<0x7>(s), R3);
281 std::get<0x9>(s) = _mm256_srli_epi32(std::get<0x9>(s), R4);
282 std::get<0xB>(s) = _mm256_srli_epi32(std::get<0xB>(s), R5);
283 std::get<0xD>(s) = _mm256_srli_epi32(std::get<0xD>(s), R6);
284 std::get<0xF>(s) = _mm256_srli_epi32(std::get<0xF>(s), R7);
286 std::get<0x1>(s) = _mm256_or_si256(l0, std::get<0x1>(s));
287 std::get<0x3>(s) = _mm256_or_si256(l1, std::get<0x3>(s));
288 std::get<0x5>(s) = _mm256_or_si256(l2, std::get<0x5>(s));
289 std::get<0x7>(s) = _mm256_or_si256(l3, std::get<0x7>(s));
290 std::get<0x9>(s) = _mm256_or_si256(l4, std::get<0x9>(s));
291 std::get<0xB>(s) = _mm256_or_si256(l5, std::get<0xB>(s));
292 std::get<0xD>(s) = _mm256_or_si256(l6, std::get<0xD>(s));
293 std::get<0xF>(s) = _mm256_or_si256(l7, std::get<0xF>(s));
296 _mm256_xor_si256(std::get<0x0>(s), std::get<0x1>(s));
298 _mm256_xor_si256(std::get<0x2>(s), std::get<0x3>(s));
300 _mm256_xor_si256(std::get<0x4>(s), std::get<0x5>(s));
302 _mm256_xor_si256(std::get<0x6>(s), std::get<0x7>(s));
304 _mm256_xor_si256(std::get<0x8>(s), std::get<0x9>(s));
306 _mm256_xor_si256(std::get<0xA>(s), std::get<0xB>(s));
308 _mm256_xor_si256(std::get<0xC>(s), std::get<0xD>(s));
310 _mm256_xor_si256(std::get<0xE>(s), std::get<0xF>(s));
315 template <std::
size_t N>
316 static void set_key(std::array<__m256i, 2> &k,
const std::array<T, 6> &par)
318 std::get<0>(k) = _mm256_set1_epi32(
320 std::get<1>(k) = _mm256_set1_epi32(
324 template <std::
size_t N>
325 static void set_key(std::array<__m256i, 4> &k,
const std::array<T, 8> &par)
327 std::get<0>(k) = _mm256_set1_epi32(
329 std::get<1>(k) = _mm256_set1_epi32(
331 std::get<2>(k) = _mm256_set1_epi32(
333 std::get<3>(k) = _mm256_set1_epi32(
337 template <std::
size_t N>
339 std::array<__m256i, 8> &k,
const std::array<T, 12> &par)
341 std::get<0>(k) = _mm256_set1_epi32(
343 std::get<1>(k) = _mm256_set1_epi32(
345 std::get<2>(k) = _mm256_set1_epi32(
347 std::get<3>(k) = _mm256_set1_epi32(
349 std::get<4>(k) = _mm256_set1_epi32(
351 std::get<5>(k) = _mm256_set1_epi32(
353 std::get<6>(k) = _mm256_set1_epi32(
355 std::get<7>(k) = _mm256_set1_epi32(
359 template <std::
size_t N>
361 std::array<__m256i, 16> &k,
const std::array<T, 20> &par)
363 std::get<0x0>(k) = _mm256_set1_epi32(
365 std::get<0x1>(k) = _mm256_set1_epi32(
367 std::get<0x2>(k) = _mm256_set1_epi32(
369 std::get<0x3>(k) = _mm256_set1_epi32(
371 std::get<0x4>(k) = _mm256_set1_epi32(
373 std::get<0x5>(k) = _mm256_set1_epi32(
375 std::get<0x6>(k) = _mm256_set1_epi32(
377 std::get<0x7>(k) = _mm256_set1_epi32(
379 std::get<0x8>(k) = _mm256_set1_epi32(
381 std::get<0x9>(k) = _mm256_set1_epi32(
383 std::get<0xA>(k) = _mm256_set1_epi32(
385 std::get<0xB>(k) = _mm256_set1_epi32(
387 std::get<0xC>(k) = _mm256_set1_epi32(
389 std::get<0xD>(k) = _mm256_set1_epi32(
391 std::get<0xE>(k) = _mm256_set1_epi32(
393 std::get<0xF>(k) = _mm256_set1_epi32(
397 template <std::
size_t S>
398 static void permute(std::array<__m256i, S> &s)
400 permute<0>(s, std::integral_constant<bool, 0 <
S / K>());
403 template <std::
size_t, std::
size_t S>
404 static void permute(std::array<__m256i, S> &, std::false_type)
408 template <std::
size_t I, std::
size_t S>
409 static void permute(std::array<__m256i, S> &s, std::true_type)
412 permute<I + 1>(s, std::integral_constant<bool, I + 1 <
S / K>());
416 template <
typename T>
422 template <
typename T>
434 #endif // MCKL_RANDOM_INTERNAL_THREEFRY_AVX2_32_HPP #define MCKL_PUSH_GCC_WARNING(warning)
void round(std::size_t n, const float *a, float *y)
typename internal::CounterImpl< T, K >::type Counter
A counter type with the same width as std::array<T, K> but with possibly fewer elements.
static void eval(const void *plain, void *cipher, const std::array< T, K+4 > &par)
#define MCKL_RANDOM_INTERNAL_THREEFRY_UNROLL_ROUND(N, s, par)
Default Threefry constants.
static void eval(Counter< T, K > &ctr, std::size_t n, ResultType *r, const std::array< T, K+4 > &par)
static void eval(Counter< T, K > &ctr, ResultType *r, const std::array< T, K+4 > &par)
#define MCKL_ALIGNMENT
The default alignment for scalar type.
#define MCKL_POP_GCC_WARNING
void increment_si256(std::array< T, K > &ctr, std::array< __m256i, S > &s, std::false_type)