32 #ifndef MCKL_RANDOM_INTERNAL_THREEFRY_SSE2_32_HPP 33 #define MCKL_RANDOM_INTERNAL_THREEFRY_SSE2_32_HPP 49 template <
typename T, std::
size_t K, std::
size_t Rounds,
typename Constants>
54 const void *plain,
void *cipher,
const std::array<T, K + 4> &par)
60 template <
typename ResultType>
62 Counter<T, K> &ctr, ResultType *r,
const std::array<T, K + 4> &par)
68 template <
typename ResultType>
70 const std::array<T, K + 4> &par)
72 constexpr std::size_t
S = K <= 8 ? 8 : K;
73 constexpr std::size_t N =
sizeof(__m128i) * S / (
sizeof(T) * K);
74 constexpr std::size_t R =
sizeof(T) * K /
sizeof(ResultType);
77 std::array<__m128i, S> s;
82 std::memcpy(r, s.data(),
sizeof(T) * K * N);
89 ctr, n, t.data(), par);
90 std::memcpy(r, t.data(),
sizeof(T) * K * n);
94 template <std::
size_t N, std::
size_t S>
95 static void round(std::array<__m128i, S> &,
const std::array<T, K + 4> &,
100 template <std::
size_t N, std::
size_t S>
101 static void round(std::array<__m128i, S> &s,
102 const std::array<T, K + 4> &par, std::true_type)
107 template <std::
size_t N, std::
size_t S>
109 std::array<__m128i, S> &s,
const std::array<T, K + 4> &par)
112 std::integral_constant<bool, (N % 4 == 0 && N <= Rounds)>());
115 template <std::
size_t, std::
size_t S>
116 static void kbox(std::array<__m128i, S> &,
const std::array<T, K + 4> &,
121 template <std::
size_t N>
122 static void kbox(std::array<__m128i, 8> &s,
123 const std::array<T, K + 4> &par, std::true_type)
125 std::array<__m128i, K> k;
128 std::get<0>(s) = _mm_add_epi32(std::get<0>(s), std::get<0 % K>(k));
129 std::get<1>(s) = _mm_add_epi32(std::get<1>(s), std::get<1 % K>(k));
130 std::get<2>(s) = _mm_add_epi32(std::get<2>(s), std::get<2 % K>(k));
131 std::get<3>(s) = _mm_add_epi32(std::get<3>(s), std::get<3 % K>(k));
132 std::get<4>(s) = _mm_add_epi32(std::get<4>(s), std::get<4 % K>(k));
133 std::get<5>(s) = _mm_add_epi32(std::get<5>(s), std::get<5 % K>(k));
134 std::get<6>(s) = _mm_add_epi32(std::get<6>(s), std::get<6 % K>(k));
135 std::get<7>(s) = _mm_add_epi32(std::get<7>(s), std::get<7 % K>(k));
138 template <std::
size_t N>
139 static void kbox(std::array<__m128i, 16> &s,
140 const std::array<T, K + 4> &par, std::true_type)
142 std::array<__m128i, K> k;
146 _mm_add_epi32(std::get<0x0>(s), std::get<0x0 % K>(k));
148 _mm_add_epi32(std::get<0x1>(s), std::get<0x1 % K>(k));
150 _mm_add_epi32(std::get<0x2>(s), std::get<0x2 % K>(k));
152 _mm_add_epi32(std::get<0x3>(s), std::get<0x3 % K>(k));
154 _mm_add_epi32(std::get<0x4>(s), std::get<0x4 % K>(k));
156 _mm_add_epi32(std::get<0x5>(s), std::get<0x5 % K>(k));
158 _mm_add_epi32(std::get<0x6>(s), std::get<0x6 % K>(k));
160 _mm_add_epi32(std::get<0x7>(s), std::get<0x7 % K>(k));
162 _mm_add_epi32(std::get<0x8>(s), std::get<0x8 % K>(k));
164 _mm_add_epi32(std::get<0x9>(s), std::get<0x9 % K>(k));
166 _mm_add_epi32(std::get<0xA>(s), std::get<0xA % K>(k));
168 _mm_add_epi32(std::get<0xB>(s), std::get<0xB % K>(k));
170 _mm_add_epi32(std::get<0xC>(s), std::get<0xC % K>(k));
172 _mm_add_epi32(std::get<0xD>(s), std::get<0xD % K>(k));
174 _mm_add_epi32(std::get<0xE>(s), std::get<0xE % K>(k));
176 _mm_add_epi32(std::get<0xF>(s), std::get<0xF % K>(k));
179 template <std::
size_t N, std::
size_t S>
180 MCKL_INLINE static void rbox(std::array<__m128i, S> &s)
182 rbox<N>(s, std::integral_constant<bool, (N > 0 && N <= Rounds)>());
185 template <std::
size_t, std::
size_t S>
186 static void rbox(std::array<__m128i, S> &, std::false_type)
190 template <std::
size_t N>
191 static void rbox(std::array<__m128i, 8> &s, std::true_type)
193 constexpr
int L0 = Constants::rotate::value[0 % (K / 2)][(N - 1) % 8];
194 constexpr
int L1 = Constants::rotate::value[1 % (K / 2)][(N - 1) % 8];
195 constexpr
int L2 = Constants::rotate::value[2 % (K / 2)][(N - 1) % 8];
196 constexpr
int L3 = Constants::rotate::value[3 % (K / 2)][(N - 1) % 8];
197 constexpr
int R0 = 32 - L0;
198 constexpr
int R1 = 32 - L1;
199 constexpr
int R2 = 32 - L2;
200 constexpr
int R3 = 32 - L3;
202 std::get<0>(s) = _mm_add_epi32(std::get<0>(s), std::get<1>(s));
203 std::get<2>(s) = _mm_add_epi32(std::get<2>(s), std::get<3>(s));
204 std::get<4>(s) = _mm_add_epi32(std::get<4>(s), std::get<5>(s));
205 std::get<6>(s) = _mm_add_epi32(std::get<6>(s), std::get<7>(s));
207 __m128i l0 = _mm_slli_epi32(std::get<1>(s), L0);
208 __m128i l1 = _mm_slli_epi32(std::get<3>(s), L1);
209 __m128i l2 = _mm_slli_epi32(std::get<5>(s), L2);
210 __m128i l3 = _mm_slli_epi32(std::get<7>(s), L3);
212 __m128i r0 = _mm_srli_epi32(std::get<1>(s), R0);
213 __m128i r1 = _mm_srli_epi32(std::get<3>(s), R1);
214 __m128i r2 = _mm_srli_epi32(std::get<5>(s), R2);
215 __m128i r3 = _mm_srli_epi32(std::get<7>(s), R3);
217 std::get<1>(s) = _mm_or_si128(l0, r0);
218 std::get<3>(s) = _mm_or_si128(l1, r1);
219 std::get<5>(s) = _mm_or_si128(l2, r2);
220 std::get<7>(s) = _mm_or_si128(l3, r3);
222 std::get<1>(s) = _mm_xor_si128(std::get<0>(s), std::get<1>(s));
223 std::get<3>(s) = _mm_xor_si128(std::get<2>(s), std::get<3>(s));
224 std::get<5>(s) = _mm_xor_si128(std::get<4>(s), std::get<5>(s));
225 std::get<7>(s) = _mm_xor_si128(std::get<6>(s), std::get<7>(s));
230 template <std::
size_t N>
231 static void rbox(std::array<__m128i, 16> &s, std::true_type)
233 constexpr
int L0 = Constants::rotate::value[0 % (K / 2)][(N - 1) % 8];
234 constexpr
int L1 = Constants::rotate::value[1 % (K / 2)][(N - 1) % 8];
235 constexpr
int L2 = Constants::rotate::value[2 % (K / 2)][(N - 1) % 8];
236 constexpr
int L3 = Constants::rotate::value[3 % (K / 2)][(N - 1) % 8];
237 constexpr
int L4 = Constants::rotate::value[4 % (K / 2)][(N - 1) % 8];
238 constexpr
int L5 = Constants::rotate::value[5 % (K / 2)][(N - 1) % 8];
239 constexpr
int L6 = Constants::rotate::value[6 % (K / 2)][(N - 1) % 8];
240 constexpr
int L7 = Constants::rotate::value[7 % (K / 2)][(N - 1) % 8];
241 constexpr
int R0 = 32 - L0;
242 constexpr
int R1 = 32 - L1;
243 constexpr
int R2 = 32 - L2;
244 constexpr
int R3 = 32 - L3;
245 constexpr
int R4 = 32 - L4;
246 constexpr
int R5 = 32 - L5;
247 constexpr
int R6 = 32 - L6;
248 constexpr
int R7 = 32 - L7;
250 std::get<0x0>(s) = _mm_add_epi32(std::get<0x0>(s), std::get<0x1>(s));
251 std::get<0x2>(s) = _mm_add_epi32(std::get<0x2>(s), std::get<0x3>(s));
252 std::get<0x4>(s) = _mm_add_epi32(std::get<0x4>(s), std::get<0x5>(s));
253 std::get<0x6>(s) = _mm_add_epi32(std::get<0x6>(s), std::get<0x7>(s));
254 std::get<0x8>(s) = _mm_add_epi32(std::get<0x8>(s), std::get<0x9>(s));
255 std::get<0xA>(s) = _mm_add_epi32(std::get<0xA>(s), std::get<0xB>(s));
256 std::get<0xC>(s) = _mm_add_epi32(std::get<0xC>(s), std::get<0xD>(s));
257 std::get<0xE>(s) = _mm_add_epi32(std::get<0xE>(s), std::get<0xF>(s));
259 __m128i l0 = _mm_slli_epi32(std::get<0x1>(s), L0);
260 __m128i l1 = _mm_slli_epi32(std::get<0x3>(s), L1);
261 __m128i l2 = _mm_slli_epi32(std::get<0x5>(s), L2);
262 __m128i l3 = _mm_slli_epi32(std::get<0x7>(s), L3);
263 __m128i l4 = _mm_slli_epi32(std::get<0x9>(s), L4);
264 __m128i l5 = _mm_slli_epi32(std::get<0xB>(s), L5);
265 __m128i l6 = _mm_slli_epi32(std::get<0xD>(s), L6);
266 __m128i l7 = _mm_slli_epi32(std::get<0xF>(s), L7);
268 std::get<0x1>(s) = _mm_srli_epi32(std::get<0x1>(s), R0);
269 std::get<0x3>(s) = _mm_srli_epi32(std::get<0x3>(s), R1);
270 std::get<0x5>(s) = _mm_srli_epi32(std::get<0x5>(s), R2);
271 std::get<0x7>(s) = _mm_srli_epi32(std::get<0x7>(s), R3);
272 std::get<0x9>(s) = _mm_srli_epi32(std::get<0x9>(s), R4);
273 std::get<0xB>(s) = _mm_srli_epi32(std::get<0xB>(s), R5);
274 std::get<0xD>(s) = _mm_srli_epi32(std::get<0xD>(s), R6);
275 std::get<0xF>(s) = _mm_srli_epi32(std::get<0xF>(s), R7);
277 std::get<0x1>(s) = _mm_or_si128(l0, std::get<0x1>(s));
278 std::get<0x3>(s) = _mm_or_si128(l1, std::get<0x3>(s));
279 std::get<0x5>(s) = _mm_or_si128(l2, std::get<0x5>(s));
280 std::get<0x7>(s) = _mm_or_si128(l3, std::get<0x7>(s));
281 std::get<0x9>(s) = _mm_or_si128(l4, std::get<0x9>(s));
282 std::get<0xB>(s) = _mm_or_si128(l5, std::get<0xB>(s));
283 std::get<0xD>(s) = _mm_or_si128(l6, std::get<0xD>(s));
284 std::get<0xF>(s) = _mm_or_si128(l7, std::get<0xF>(s));
286 std::get<0x1>(s) = _mm_xor_si128(std::get<0x0>(s), std::get<0x1>(s));
287 std::get<0x3>(s) = _mm_xor_si128(std::get<0x2>(s), std::get<0x3>(s));
288 std::get<0x5>(s) = _mm_xor_si128(std::get<0x4>(s), std::get<0x5>(s));
289 std::get<0x7>(s) = _mm_xor_si128(std::get<0x6>(s), std::get<0x7>(s));
290 std::get<0x9>(s) = _mm_xor_si128(std::get<0x8>(s), std::get<0x9>(s));
291 std::get<0xB>(s) = _mm_xor_si128(std::get<0xA>(s), std::get<0xB>(s));
292 std::get<0xD>(s) = _mm_xor_si128(std::get<0xC>(s), std::get<0xD>(s));
293 std::get<0xF>(s) = _mm_xor_si128(std::get<0xE>(s), std::get<0xF>(s));
298 template <std::
size_t N>
299 static void set_key(std::array<__m128i, 2> &k,
const std::array<T, 6> &par)
301 std::get<0>(k) = _mm_set1_epi32(
303 std::get<1>(k) = _mm_set1_epi32(
307 template <std::
size_t N>
308 static void set_key(std::array<__m128i, 4> &k,
const std::array<T, 8> &par)
310 std::get<0>(k) = _mm_set1_epi32(
312 std::get<1>(k) = _mm_set1_epi32(
314 std::get<2>(k) = _mm_set1_epi32(
316 std::get<3>(k) = _mm_set1_epi32(
320 template <std::
size_t N>
322 std::array<__m128i, 8> &k,
const std::array<T, 12> &par)
324 std::get<0>(k) = _mm_set1_epi32(
326 std::get<1>(k) = _mm_set1_epi32(
328 std::get<2>(k) = _mm_set1_epi32(
330 std::get<3>(k) = _mm_set1_epi32(
332 std::get<4>(k) = _mm_set1_epi32(
334 std::get<5>(k) = _mm_set1_epi32(
336 std::get<6>(k) = _mm_set1_epi32(
338 std::get<7>(k) = _mm_set1_epi32(
342 template <std::
size_t N>
344 std::array<__m128i, 16> &k,
const std::array<T, 20> &par)
346 std::get<0x0>(k) = _mm_set1_epi32(
348 std::get<0x1>(k) = _mm_set1_epi32(
350 std::get<0x2>(k) = _mm_set1_epi32(
352 std::get<0x3>(k) = _mm_set1_epi32(
354 std::get<0x4>(k) = _mm_set1_epi32(
356 std::get<0x5>(k) = _mm_set1_epi32(
358 std::get<0x6>(k) = _mm_set1_epi32(
360 std::get<0x7>(k) = _mm_set1_epi32(
362 std::get<0x8>(k) = _mm_set1_epi32(
364 std::get<0x9>(k) = _mm_set1_epi32(
366 std::get<0xA>(k) = _mm_set1_epi32(
368 std::get<0xB>(k) = _mm_set1_epi32(
370 std::get<0xC>(k) = _mm_set1_epi32(
372 std::get<0xD>(k) = _mm_set1_epi32(
374 std::get<0xE>(k) = _mm_set1_epi32(
376 std::get<0xF>(k) = _mm_set1_epi32(
380 template <std::
size_t S>
381 static void permute(std::array<__m128i, S> &s)
383 permute<0>(s, std::integral_constant<bool, 0 <
S / K>());
386 template <std::
size_t, std::
size_t S>
387 static void permute(std::array<__m128i, S> &, std::false_type)
391 template <std::
size_t I, std::
size_t S>
392 static void permute(std::array<__m128i, S> &s, std::true_type)
395 permute<I + 1>(s, std::integral_constant<bool, I + 1 <
S / K>());
399 template <
typename T>
405 template <
typename T>
417 #endif // MCKL_RANDOM_INTERNAL_THREEFRY_SSE2_32_HPP #define MCKL_PUSH_GCC_WARNING(warning)
void increment_si128(std::array< T, K > &ctr, std::array< __m128i, S > &s, std::false_type)
void round(std::size_t n, const float *a, float *y)
static void eval(Counter< T, K > &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)
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(Counter< T, K > &ctr, ResultType *r, const std::array< T, K+4 > &par)
#define MCKL_RANDOM_INTERNAL_THREEFRY_UNROLL_ROUND(N, s, par)
Default Threefry constants.
#define MCKL_ALIGNMENT
The default alignment for scalar type.
#define MCKL_POP_GCC_WARNING