32 #ifndef MCKL_RANDOM_INTERNAL_THREEFRY_SSE2_64_HPP 33 #define MCKL_RANDOM_INTERNAL_THREEFRY_SSE2_64_HPP 51 template <
typename T, std::
size_t K, std::
size_t Rounds,
typename Constants>
56 const void *plain,
void *cipher,
const std::array<T, K + 4> &par)
62 template <
typename ResultType>
64 Counter<T, K> &ctr, ResultType *r,
const std::array<T, K + 4> &par)
70 template <
typename ResultType>
72 const std::array<T, K + 4> &par)
74 constexpr std::size_t
S = K <= 8 ? 8 : K;
75 constexpr std::size_t N =
sizeof(__m128i) * S / (
sizeof(T) * K);
76 constexpr std::size_t R =
sizeof(T) * K /
sizeof(ResultType);
79 std::array<__m128i, S> s;
84 std::memcpy(r, s.data(),
sizeof(T) * K * N);
91 ctr, n, t.data(), par);
92 std::memcpy(r, t.data(),
sizeof(T) * K * n);
96 template <std::
size_t, std::
size_t S>
97 static void round(std::array<__m128i, S> &,
const std::array<T, K + 4> &,
102 template <std::
size_t N, std::
size_t S>
103 static void round(std::array<__m128i, S> &s,
104 const std::array<T, K + 4> &par, std::true_type)
109 template <std::
size_t N, std::
size_t S>
111 std::array<__m128i, S> &s,
const std::array<T, K + 4> &par)
114 std::integral_constant<bool, (N % 4 == 0 && N <= Rounds)>());
117 template <std::
size_t, std::
size_t S>
118 static void kbox(std::array<__m128i, S> &,
const std::array<T, K + 4> &,
123 template <std::
size_t N>
124 static void kbox(std::array<__m128i, 8> &s,
125 const std::array<T, K + 4> &par, std::true_type)
127 std::array<__m128i, K> k;
130 std::get<0>(s) = _mm_add_epi64(std::get<0>(s), std::get<0 % K>(k));
131 std::get<1>(s) = _mm_add_epi64(std::get<1>(s), std::get<1 % K>(k));
132 std::get<2>(s) = _mm_add_epi64(std::get<2>(s), std::get<2 % K>(k));
133 std::get<3>(s) = _mm_add_epi64(std::get<3>(s), std::get<3 % K>(k));
134 std::get<4>(s) = _mm_add_epi64(std::get<4>(s), std::get<4 % K>(k));
135 std::get<5>(s) = _mm_add_epi64(std::get<5>(s), std::get<5 % K>(k));
136 std::get<6>(s) = _mm_add_epi64(std::get<6>(s), std::get<6 % K>(k));
137 std::get<7>(s) = _mm_add_epi64(std::get<7>(s), std::get<7 % K>(k));
140 template <std::
size_t N>
141 static void kbox(std::array<__m128i, 16> &s,
142 const std::array<T, K + 4> &par, std::true_type)
144 std::array<__m128i, K> k;
148 _mm_add_epi64(std::get<0x0>(s), std::get<0x0 % K>(k));
150 _mm_add_epi64(std::get<0x1>(s), std::get<0x1 % K>(k));
152 _mm_add_epi64(std::get<0x2>(s), std::get<0x2 % K>(k));
154 _mm_add_epi64(std::get<0x3>(s), std::get<0x3 % K>(k));
156 _mm_add_epi64(std::get<0x4>(s), std::get<0x4 % K>(k));
158 _mm_add_epi64(std::get<0x5>(s), std::get<0x5 % K>(k));
160 _mm_add_epi64(std::get<0x6>(s), std::get<0x6 % K>(k));
162 _mm_add_epi64(std::get<0x7>(s), std::get<0x7 % K>(k));
164 _mm_add_epi64(std::get<0x8>(s), std::get<0x8 % K>(k));
166 _mm_add_epi64(std::get<0x9>(s), std::get<0x9 % K>(k));
168 _mm_add_epi64(std::get<0xA>(s), std::get<0xA % K>(k));
170 _mm_add_epi64(std::get<0xB>(s), std::get<0xB % K>(k));
172 _mm_add_epi64(std::get<0xC>(s), std::get<0xC % K>(k));
174 _mm_add_epi64(std::get<0xD>(s), std::get<0xD % K>(k));
176 _mm_add_epi64(std::get<0xE>(s), std::get<0xE % K>(k));
178 _mm_add_epi64(std::get<0xF>(s), std::get<0xF % K>(k));
181 template <std::
size_t N, std::
size_t S>
182 MCKL_INLINE static void rbox(std::array<__m128i, S> &s)
184 rbox<N>(s, std::integral_constant<bool, (N > 0 && N <= Rounds)>());
187 template <std::
size_t, std::
size_t S>
188 static void rbox(std::array<__m128i, S> &, std::false_type)
192 template <std::
size_t N>
193 static void rbox(std::array<__m128i, 8> &s, std::true_type)
195 constexpr
int L0 = Constants::rotate::value[0 % (K / 2)][(N - 1) % 8];
196 constexpr
int L1 = Constants::rotate::value[1 % (K / 2)][(N - 1) % 8];
197 constexpr
int L2 = Constants::rotate::value[2 % (K / 2)][(N - 1) % 8];
198 constexpr
int L3 = Constants::rotate::value[3 % (K / 2)][(N - 1) % 8];
199 constexpr
int R0 = 64 - L0;
200 constexpr
int R1 = 64 - L1;
201 constexpr
int R2 = 64 - L2;
202 constexpr
int R3 = 64 - L3;
204 std::get<0>(s) = _mm_add_epi64(std::get<0>(s), std::get<1>(s));
205 std::get<2>(s) = _mm_add_epi64(std::get<2>(s), std::get<3>(s));
206 std::get<4>(s) = _mm_add_epi64(std::get<4>(s), std::get<5>(s));
207 std::get<6>(s) = _mm_add_epi64(std::get<6>(s), std::get<7>(s));
209 __m128i l0 = _mm_slli_epi64(std::get<1>(s), L0);
210 __m128i l1 = _mm_slli_epi64(std::get<3>(s), L1);
211 __m128i l2 = _mm_slli_epi64(std::get<5>(s), L2);
212 __m128i l3 = _mm_slli_epi64(std::get<7>(s), L3);
214 __m128i r0 = _mm_srli_epi64(std::get<1>(s), R0);
215 __m128i r1 = _mm_srli_epi64(std::get<3>(s), R1);
216 __m128i r2 = _mm_srli_epi64(std::get<5>(s), R2);
217 __m128i r3 = _mm_srli_epi64(std::get<7>(s), R3);
219 std::get<1>(s) = _mm_or_si128(l0, r0);
220 std::get<3>(s) = _mm_or_si128(l1, r1);
221 std::get<5>(s) = _mm_or_si128(l2, r2);
222 std::get<7>(s) = _mm_or_si128(l3, r3);
224 std::get<1>(s) = _mm_xor_si128(std::get<0>(s), std::get<1>(s));
225 std::get<3>(s) = _mm_xor_si128(std::get<2>(s), std::get<3>(s));
226 std::get<5>(s) = _mm_xor_si128(std::get<4>(s), std::get<5>(s));
227 std::get<7>(s) = _mm_xor_si128(std::get<6>(s), std::get<7>(s));
232 template <std::
size_t N>
233 static void rbox(std::array<__m128i, 16> &s, std::true_type)
235 constexpr
int L0 = Constants::rotate::value[0 % (K / 2)][(N - 1) % 8];
236 constexpr
int L1 = Constants::rotate::value[1 % (K / 2)][(N - 1) % 8];
237 constexpr
int L2 = Constants::rotate::value[2 % (K / 2)][(N - 1) % 8];
238 constexpr
int L3 = Constants::rotate::value[3 % (K / 2)][(N - 1) % 8];
239 constexpr
int L4 = Constants::rotate::value[4 % (K / 2)][(N - 1) % 8];
240 constexpr
int L5 = Constants::rotate::value[5 % (K / 2)][(N - 1) % 8];
241 constexpr
int L6 = Constants::rotate::value[6 % (K / 2)][(N - 1) % 8];
242 constexpr
int L7 = Constants::rotate::value[7 % (K / 2)][(N - 1) % 8];
243 constexpr
int R0 = 64 - L0;
244 constexpr
int R1 = 64 - L1;
245 constexpr
int R2 = 64 - L2;
246 constexpr
int R3 = 64 - L3;
247 constexpr
int R4 = 64 - L4;
248 constexpr
int R5 = 64 - L5;
249 constexpr
int R6 = 64 - L6;
250 constexpr
int R7 = 64 - L7;
252 std::get<0x0>(s) = _mm_add_epi64(std::get<0x0>(s), std::get<0x1>(s));
253 std::get<0x2>(s) = _mm_add_epi64(std::get<0x2>(s), std::get<0x3>(s));
254 std::get<0x4>(s) = _mm_add_epi64(std::get<0x4>(s), std::get<0x5>(s));
255 std::get<0x6>(s) = _mm_add_epi64(std::get<0x6>(s), std::get<0x7>(s));
256 std::get<0x8>(s) = _mm_add_epi64(std::get<0x8>(s), std::get<0x9>(s));
257 std::get<0xA>(s) = _mm_add_epi64(std::get<0xA>(s), std::get<0xB>(s));
258 std::get<0xC>(s) = _mm_add_epi64(std::get<0xC>(s), std::get<0xD>(s));
259 std::get<0xE>(s) = _mm_add_epi64(std::get<0xE>(s), std::get<0xF>(s));
261 __m128i l0 = _mm_slli_epi64(std::get<0x1>(s), L0);
262 __m128i l1 = _mm_slli_epi64(std::get<0x3>(s), L1);
263 __m128i l2 = _mm_slli_epi64(std::get<0x5>(s), L2);
264 __m128i l3 = _mm_slli_epi64(std::get<0x7>(s), L3);
265 __m128i l4 = _mm_slli_epi64(std::get<0x9>(s), L4);
266 __m128i l5 = _mm_slli_epi64(std::get<0xB>(s), L5);
267 __m128i l6 = _mm_slli_epi64(std::get<0xD>(s), L6);
268 __m128i l7 = _mm_slli_epi64(std::get<0xF>(s), L7);
270 std::get<0x1>(s) = _mm_srli_epi64(std::get<0x1>(s), R0);
271 std::get<0x3>(s) = _mm_srli_epi64(std::get<0x3>(s), R1);
272 std::get<0x5>(s) = _mm_srli_epi64(std::get<0x5>(s), R2);
273 std::get<0x7>(s) = _mm_srli_epi64(std::get<0x7>(s), R3);
274 std::get<0x9>(s) = _mm_srli_epi64(std::get<0x9>(s), R4);
275 std::get<0xB>(s) = _mm_srli_epi64(std::get<0xB>(s), R5);
276 std::get<0xD>(s) = _mm_srli_epi64(std::get<0xD>(s), R6);
277 std::get<0xF>(s) = _mm_srli_epi64(std::get<0xF>(s), R7);
279 std::get<0x1>(s) = _mm_or_si128(l0, std::get<0x1>(s));
280 std::get<0x3>(s) = _mm_or_si128(l1, std::get<0x3>(s));
281 std::get<0x5>(s) = _mm_or_si128(l2, std::get<0x5>(s));
282 std::get<0x7>(s) = _mm_or_si128(l3, std::get<0x7>(s));
283 std::get<0x9>(s) = _mm_or_si128(l4, std::get<0x9>(s));
284 std::get<0xB>(s) = _mm_or_si128(l5, std::get<0xB>(s));
285 std::get<0xD>(s) = _mm_or_si128(l6, std::get<0xD>(s));
286 std::get<0xF>(s) = _mm_or_si128(l7, std::get<0xF>(s));
288 std::get<0x1>(s) = _mm_xor_si128(std::get<0x0>(s), std::get<0x1>(s));
289 std::get<0x3>(s) = _mm_xor_si128(std::get<0x2>(s), std::get<0x3>(s));
290 std::get<0x5>(s) = _mm_xor_si128(std::get<0x4>(s), std::get<0x5>(s));
291 std::get<0x7>(s) = _mm_xor_si128(std::get<0x6>(s), std::get<0x7>(s));
292 std::get<0x9>(s) = _mm_xor_si128(std::get<0x8>(s), std::get<0x9>(s));
293 std::get<0xB>(s) = _mm_xor_si128(std::get<0xA>(s), std::get<0xB>(s));
294 std::get<0xD>(s) = _mm_xor_si128(std::get<0xC>(s), std::get<0xD>(s));
295 std::get<0xF>(s) = _mm_xor_si128(std::get<0xE>(s), std::get<0xF>(s));
300 template <std::
size_t N>
301 static void set_key(std::array<__m128i, 2> &k,
const std::array<T, 6> &par)
303 std::get<0>(k) = _mm_set1_epi64x(static_cast<MCKL_INT64>(
305 std::get<1>(k) = _mm_set1_epi64x(static_cast<MCKL_INT64>(
309 template <std::
size_t N>
310 static void set_key(std::array<__m128i, 4> &k,
const std::array<T, 8> &par)
312 std::get<0>(k) = _mm_set1_epi64x(static_cast<MCKL_INT64>(
314 std::get<1>(k) = _mm_set1_epi64x(static_cast<MCKL_INT64>(
316 std::get<2>(k) = _mm_set1_epi64x(static_cast<MCKL_INT64>(
318 std::get<3>(k) = _mm_set1_epi64x(static_cast<MCKL_INT64>(
322 template <std::
size_t N>
324 std::array<__m128i, 8> &k,
const std::array<T, 12> &par)
326 std::get<0>(k) = _mm_set1_epi64x(static_cast<MCKL_INT64>(
328 std::get<1>(k) = _mm_set1_epi64x(static_cast<MCKL_INT64>(
330 std::get<2>(k) = _mm_set1_epi64x(static_cast<MCKL_INT64>(
332 std::get<3>(k) = _mm_set1_epi64x(static_cast<MCKL_INT64>(
334 std::get<4>(k) = _mm_set1_epi64x(static_cast<MCKL_INT64>(
336 std::get<5>(k) = _mm_set1_epi64x(static_cast<MCKL_INT64>(
338 std::get<6>(k) = _mm_set1_epi64x(static_cast<MCKL_INT64>(
340 std::get<7>(k) = _mm_set1_epi64x(static_cast<MCKL_INT64>(
344 template <std::
size_t N>
346 std::array<__m128i, 16> &k,
const std::array<T, 20> &par)
348 std::get<0x0>(k) = _mm_set1_epi64x(static_cast<MCKL_INT64>(
350 std::get<0x1>(k) = _mm_set1_epi64x(static_cast<MCKL_INT64>(
352 std::get<0x2>(k) = _mm_set1_epi64x(static_cast<MCKL_INT64>(
354 std::get<0x3>(k) = _mm_set1_epi64x(static_cast<MCKL_INT64>(
356 std::get<0x4>(k) = _mm_set1_epi64x(static_cast<MCKL_INT64>(
358 std::get<0x5>(k) = _mm_set1_epi64x(static_cast<MCKL_INT64>(
360 std::get<0x6>(k) = _mm_set1_epi64x(static_cast<MCKL_INT64>(
362 std::get<0x7>(k) = _mm_set1_epi64x(static_cast<MCKL_INT64>(
364 std::get<0x8>(k) = _mm_set1_epi64x(static_cast<MCKL_INT64>(
366 std::get<0x9>(k) = _mm_set1_epi64x(static_cast<MCKL_INT64>(
368 std::get<0xA>(k) = _mm_set1_epi64x(static_cast<MCKL_INT64>(
370 std::get<0xB>(k) = _mm_set1_epi64x(static_cast<MCKL_INT64>(
372 std::get<0xC>(k) = _mm_set1_epi64x(static_cast<MCKL_INT64>(
374 std::get<0xD>(k) = _mm_set1_epi64x(static_cast<MCKL_INT64>(
376 std::get<0xE>(k) = _mm_set1_epi64x(static_cast<MCKL_INT64>(
378 std::get<0xF>(k) = _mm_set1_epi64x(static_cast<MCKL_INT64>(
382 template <std::
size_t S>
383 static void permute(std::array<__m128i, S> &s)
385 permute<0>(s, std::integral_constant<bool, 0 <
S / K>());
388 template <std::
size_t, std::
size_t S>
389 static void permute(std::array<__m128i, S> &, std::false_type)
393 template <std::
size_t I, std::
size_t S>
394 static void permute(std::array<__m128i, S> &s, std::true_type)
397 permute<I + 1>(s, std::integral_constant<bool, I + 1 <
S / K>());
401 template <
typename T>
407 template <
typename T>
413 template <
typename T>
419 template <
typename T>
425 template <
typename T>
431 template <
typename T>
437 template <
typename T>
449 #endif // MCKL_RANDOM_INTERNAL_THREEFRY_SSE2_64_HPP
#define MCKL_PUSH_GCC_WARNING(warning)
void increment_si128(std::array< T, K > &ctr, std::array< __m128i, S > &s, std::false_type)
static void eval(Counter< T, K > &ctr, ResultType *r, const std::array< T, K+4 > &par)
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.
#define MCKL_RANDOM_INTERNAL_THREEFRY_UNROLL_ROUND(N, s, par)
static void eval(Counter< T, K > &ctr, std::size_t n, ResultType *r, const std::array< T, K+4 > &par)
Default Threefry constants.
static void eval(const void *plain, void *cipher, const std::array< T, K+4 > &par)
#define MCKL_ALIGNMENT
The default alignment for scalar type.
#define MCKL_POP_GCC_WARNING