32 #ifndef MCKL_RANDOM_INTERNAL_THREEFRY_SSE2_4X32_HPP 33 #define MCKL_RANDOM_INTERNAL_THREEFRY_SSE2_4X32_HPP 42 #define MCKL_RANDOM_INTERNAL_THREEFRY_SSE2_4X32_KBOX(N) \ 43 xmmt0 = _mm_set1_epi32( \ 44 static_cast<int>(ThreefryKBox<T, K, N>::template key<0>(par))); \ 45 xmmt1 = _mm_set1_epi32( \ 46 static_cast<int>(ThreefryKBox<T, K, N>::template key<1>(par))); \ 47 xmmt2 = _mm_set1_epi32( \ 48 static_cast<int>(ThreefryKBox<T, K, N>::template key<2>(par))); \ 49 xmmt3 = _mm_set1_epi32( \ 50 static_cast<int>(ThreefryKBox<T, K, N>::template key<3>(par))); \ 51 xmms0 = _mm_add_epi32(xmms0, xmmt0); \ 52 xmms1 = _mm_add_epi32(xmms1, xmmt1); \ 53 xmms2 = _mm_add_epi32(xmms2, xmmt2); \ 54 xmms3 = _mm_add_epi32(xmms3, xmmt3); \ 55 xmms4 = _mm_add_epi32(xmms4, xmmt0); \ 56 xmms5 = _mm_add_epi32(xmms5, xmmt1); \ 57 xmms6 = _mm_add_epi32(xmms6, xmmt2); \ 58 xmms7 = _mm_add_epi32(xmms7, xmmt3); 60 #define MCKL_RANDOM_INTERNAL_THREEFRY_SSE2_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 xmms0 = _mm_add_epi32(xmms0, xmms1); \ 67 xmms2 = _mm_add_epi32(xmms2, xmms3); \ 68 xmms4 = _mm_add_epi32(xmms4, xmms5); \ 69 xmms6 = _mm_add_epi32(xmms6, xmms7); \ 70 xmmt1 = _mm_slli_epi32(xmms1, L0); \ 71 xmmt3 = _mm_slli_epi32(xmms3, L1); \ 72 xmmt5 = _mm_slli_epi32(xmms5, L0); \ 73 xmmt7 = _mm_slli_epi32(xmms7, L1); \ 74 xmms1 = _mm_srli_epi32(xmms1, R0); \ 75 xmms3 = _mm_srli_epi32(xmms3, R1); \ 76 xmms5 = _mm_srli_epi32(xmms5, R0); \ 77 xmms7 = _mm_srli_epi32(xmms7, R1); \ 78 xmmt1 = _mm_or_si128(xmms1, xmmt1); \ 79 xmmt3 = _mm_or_si128(xmms3, xmmt3); \ 80 xmmt5 = _mm_or_si128(xmms5, xmmt5); \ 81 xmmt7 = _mm_or_si128(xmms7, xmmt7); \ 82 xmms1 = _mm_xor_si128(xmms2, xmmt3); \ 83 xmms3 = _mm_xor_si128(xmms0, xmmt1); \ 84 xmms5 = _mm_xor_si128(xmms6, xmmt7); \ 85 xmms7 = _mm_xor_si128(xmms4, xmmt5); \ 88 #define MCKL_RANDOM_INTERNAL_THREEFRY_SSE2_4X32_CYCLE_4(N) \ 89 MCKL_RANDOM_INTERNAL_THREEFRY_SSE2_4X32_RBOX(N * 8 + 1); \ 90 MCKL_RANDOM_INTERNAL_THREEFRY_SSE2_4X32_RBOX(N * 8 + 2); \ 91 MCKL_RANDOM_INTERNAL_THREEFRY_SSE2_4X32_RBOX(N * 8 + 3); \ 92 MCKL_RANDOM_INTERNAL_THREEFRY_SSE2_4X32_RBOX(N * 8 + 4); \ 93 MCKL_RANDOM_INTERNAL_THREEFRY_SSE2_4X32_KBOX(N * 8 + 4); 95 #define MCKL_RANDOM_INTERNAL_THREEFRY_SSE2_4X32_CYCLE_8(N) \ 96 MCKL_RANDOM_INTERNAL_THREEFRY_SSE2_4X32_RBOX(N * 8 + 1); \ 97 MCKL_RANDOM_INTERNAL_THREEFRY_SSE2_4X32_RBOX(N * 8 + 2); \ 98 MCKL_RANDOM_INTERNAL_THREEFRY_SSE2_4X32_RBOX(N * 8 + 3); \ 99 MCKL_RANDOM_INTERNAL_THREEFRY_SSE2_4X32_RBOX(N * 8 + 4); \ 100 MCKL_RANDOM_INTERNAL_THREEFRY_SSE2_4X32_KBOX(N * 8 + 4); \ 101 MCKL_RANDOM_INTERNAL_THREEFRY_SSE2_4X32_RBOX(N * 8 + 5); \ 102 MCKL_RANDOM_INTERNAL_THREEFRY_SSE2_4X32_RBOX(N * 8 + 6); \ 103 MCKL_RANDOM_INTERNAL_THREEFRY_SSE2_4X32_RBOX(N * 8 + 7); \ 104 MCKL_RANDOM_INTERNAL_THREEFRY_SSE2_4X32_RBOX(N * 8 + 8); \ 105 MCKL_RANDOM_INTERNAL_THREEFRY_SSE2_4X32_KBOX(N * 8 + 8); 111 template <
typename T>
114 static_assert(std::numeric_limits<T>::digits == 32,
115 "**Threefry4x32GeneratorSSE2Impl** 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(__m128i) * S / (
sizeof(T) * K);
168 _mm_set_epi64x(static_cast<MCKL_INT64>(std::get<1>(ctr)),
169 static_cast<MCKL_INT64>(std::get<0>(ctr)));
172 __m128i *rptr =
reinterpret_cast<__m128i *
>(r);
174 __m128i xmms0 = _mm_add_epi64(xmmc, _mm_set_epi64x(0, 1));
175 __m128i xmms1 = _mm_add_epi64(xmmc, _mm_set_epi64x(0, 2));
176 __m128i xmms2 = _mm_add_epi64(xmmc, _mm_set_epi64x(0, 3));
177 __m128i xmms3 = _mm_add_epi64(xmmc, _mm_set_epi64x(0, 4));
178 __m128i xmms4 = _mm_add_epi64(xmmc, _mm_set_epi64x(0, 5));
179 __m128i xmms5 = _mm_add_epi64(xmmc, _mm_set_epi64x(0, 6));
180 __m128i xmms6 = _mm_add_epi64(xmmc, _mm_set_epi64x(0, 7));
181 __m128i xmms7 = _mm_add_epi64(xmmc, _mm_set_epi64x(0, 8));
203 xmmt0 = _mm_unpacklo_epi32(xmms0, xmms1);
204 xmmt1 = _mm_unpacklo_epi32(xmms2, xmms3);
205 xmmt2 = _mm_unpackhi_epi32(xmms0, xmms1);
206 xmmt3 = _mm_unpackhi_epi32(xmms2, xmms3);
207 xmmt4 = _mm_unpacklo_epi32(xmms4, xmms5);
208 xmmt5 = _mm_unpacklo_epi32(xmms6, xmms7);
209 xmmt6 = _mm_unpackhi_epi32(xmms4, xmms5);
210 xmmt7 = _mm_unpackhi_epi32(xmms6, xmms7);
211 xmms0 = _mm_unpacklo_epi64(xmmt0, xmmt1);
212 xmms1 = _mm_unpackhi_epi64(xmmt0, xmmt1);
213 xmms2 = _mm_unpacklo_epi64(xmmt2, xmmt3);
214 xmms3 = _mm_unpackhi_epi64(xmmt2, xmmt3);
215 xmms4 = _mm_unpacklo_epi64(xmmt4, xmmt5);
216 xmms5 = _mm_unpackhi_epi64(xmmt4, xmmt5);
217 xmms6 = _mm_unpacklo_epi64(xmmt6, xmmt7);
218 xmms7 = _mm_unpackhi_epi64(xmmt6, xmmt7);
225 xmmt0 = _mm_unpacklo_epi32(xmms0, xmms1);
226 xmmt1 = _mm_unpacklo_epi32(xmms2, xmms3);
227 xmmt2 = _mm_unpackhi_epi32(xmms0, xmms1);
228 xmmt3 = _mm_unpackhi_epi32(xmms2, xmms3);
229 xmmt4 = _mm_unpacklo_epi32(xmms4, xmms5);
230 xmmt5 = _mm_unpacklo_epi32(xmms6, xmms7);
231 xmmt6 = _mm_unpackhi_epi32(xmms4, xmms5);
232 xmmt7 = _mm_unpackhi_epi32(xmms6, xmms7);
233 xmms0 = _mm_unpacklo_epi64(xmmt0, xmmt1);
234 xmms1 = _mm_unpackhi_epi64(xmmt0, xmmt1);
235 xmms2 = _mm_unpacklo_epi64(xmmt2, xmmt3);
236 xmms3 = _mm_unpackhi_epi64(xmmt2, xmmt3);
237 xmms4 = _mm_unpacklo_epi64(xmmt4, xmmt5);
238 xmms5 = _mm_unpackhi_epi64(xmmt4, xmmt5);
239 xmms6 = _mm_unpacklo_epi64(xmmt6, xmmt7);
240 xmms7 = _mm_unpackhi_epi64(xmmt6, xmmt7);
254 _mm_storeu_si128(rptr++, xmms0);
255 _mm_storeu_si128(rptr++, xmms1);
256 _mm_storeu_si128(rptr++, xmms2);
257 _mm_storeu_si128(rptr++, xmms3);
258 _mm_storeu_si128(rptr++, xmms4);
259 _mm_storeu_si128(rptr++, xmms5);
260 _mm_storeu_si128(rptr++, xmms6);
261 _mm_storeu_si128(rptr++, xmms7);
263 std::array<__m128i, S> s;
264 std::get<0>(s) = xmms0;
265 std::get<1>(s) = xmms1;
266 std::get<2>(s) = xmms2;
267 std::get<3>(s) = xmms3;
268 std::get<4>(s) = xmms4;
269 std::get<5>(s) = xmms5;
270 std::get<6>(s) = xmms6;
271 std::get<7>(s) = xmms7;
272 std::memcpy(rptr, s.data(), n *
sizeof(T) * K);
285 #endif // MCKL_RANDOM_INTERNAL_THREEFRY_SSE2_4X32_HPP
#define MCKL_PUSH_GCC_WARNING(warning)
static void eval(std::array< std::uint64_t, 2 > &ctr, ResultType *r, const std::array< T, K+4 > &par)
static void eval(const void *plain, void *cipher, const std::array< T, K+4 > &par)
static void eval(const void *plain, void *cipher, const std::array< T, K+4 > &par)
#define MCKL_RANDOM_INTERNAL_THREEFRY_SSE2_4X32_CYCLE_8(N)
Default Threefry constants.
#define MCKL_RANDOM_INTERNAL_THREEFRY_SSE2_4X32_KBOX(N)
#define MCKL_RANDOM_INTERNAL_THREEFRY_SSE2_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