32 #ifndef MCKL_RANDOM_INTERNAL_PHILOX_SSE2_4X32_HPP 33 #define MCKL_RANDOM_INTERNAL_PHILOX_SSE2_4X32_HPP 47 template <
typename T,
typename Constants>
50 static_assert(std::numeric_limits<T>::digits == 32,
51 "**Philox4x32GeneratorSSE2Impl** used with T other than a 32-bit " 54 static constexpr std::size_t K = 4;
55 static constexpr std::size_t Rounds = 10;
59 const void *plain,
void *cipher,
const std::array<T, K / 2> &key)
64 template <
typename ResultType>
65 static void eval(std::array<std::uint64_t, 2> &ctr, ResultType *r,
66 const std::array<T, K / 2> &key)
71 template <
typename ResultType>
72 static void eval(std::array<std::uint64_t, 2> &ctr, std::size_t n,
73 ResultType *r,
const std::array<T, K / 2> &key)
75 constexpr std::size_t R =
sizeof(T) * K /
sizeof(ResultType);
77 const std::size_t n0 =
78 static_cast<std::size_t
>(std::min(static_cast<std::uint64_t>(n),
79 std::numeric_limits<std::uint64_t>::max() - ctr.front()));
81 eval_kernel(ctr, n0, r, key);
91 eval_kernel(ctr, n, r, key);
95 template <
typename ResultType>
96 static void eval_kernel(std::array<std::uint64_t, 2> &ctr, std::size_t n,
97 ResultType *r,
const std::array<T, K / 2> &key)
99 #if MCKL_USE_ASM_LIBRARY 100 constexpr T m0 = Constants::multiplier::value[0];
101 constexpr T m1 = Constants::multiplier::value[1];
102 constexpr T w0 = Constants::weyl::value[0];
103 constexpr T w1 = Constants::weyl::value[1];
105 const T mwk[12] = {m0, 0, m1, 0, 0, w0, 0, w1, 0, std::get<0>(key), 0,
108 #else // MCKL_USE_ASM_LIBRARY 109 constexpr std::size_t
S = 8;
110 constexpr std::size_t N =
sizeof(__m128i) * S / (
sizeof(T) * K);
112 const int k0 =
static_cast<int>(std::get<0>(key));
113 const int k1 =
static_cast<int>(std::get<1>(key));
114 const __m128i xmmk0 = _mm_set_epi32(k1, 0, k0, 0);
117 _mm_set_epi64x(static_cast<MCKL_INT64>(std::get<1>(ctr)),
118 static_cast<MCKL_INT64>(std::get<0>(ctr)));
121 __m128i *rptr =
reinterpret_cast<__m128i *
>(r);
123 __m128i xmm0 = _mm_add_epi64(xmmc, _mm_set_epi64x(0, 1));
124 __m128i xmm1 = _mm_add_epi64(xmmc, _mm_set_epi64x(0, 2));
125 __m128i xmm2 = _mm_add_epi64(xmmc, _mm_set_epi64x(0, 3));
126 __m128i xmm3 = _mm_add_epi64(xmmc, _mm_set_epi64x(0, 4));
127 __m128i xmm4 = _mm_add_epi64(xmmc, _mm_set_epi64x(0, 5));
128 __m128i xmm5 = _mm_add_epi64(xmmc, _mm_set_epi64x(0, 6));
129 __m128i xmm6 = _mm_add_epi64(xmmc, _mm_set_epi64x(0, 7));
130 __m128i xmm7 = _mm_add_epi64(xmmc, _mm_set_epi64x(0, 8));
133 xmm0 = _mm_shuffle_epi32(xmm0, 0xC6);
134 xmm1 = _mm_shuffle_epi32(xmm1, 0xC6);
135 xmm2 = _mm_shuffle_epi32(xmm2, 0xC6);
136 xmm3 = _mm_shuffle_epi32(xmm3, 0xC6);
137 xmm4 = _mm_shuffle_epi32(xmm4, 0xC6);
138 xmm5 = _mm_shuffle_epi32(xmm5, 0xC6);
139 xmm6 = _mm_shuffle_epi32(xmm6, 0xC6);
140 xmm7 = _mm_shuffle_epi32(xmm7, 0xC6);
155 _mm_storeu_si128(rptr++, xmm0);
156 _mm_storeu_si128(rptr++, xmm1);
157 _mm_storeu_si128(rptr++, xmm2);
158 _mm_storeu_si128(rptr++, xmm3);
159 _mm_storeu_si128(rptr++, xmm4);
160 _mm_storeu_si128(rptr++, xmm5);
161 _mm_storeu_si128(rptr++, xmm6);
162 _mm_storeu_si128(rptr++, xmm7);
164 std::array<__m128i, S> s;
165 std::get<0>(s) = xmm0;
166 std::get<1>(s) = xmm1;
167 std::get<2>(s) = xmm2;
168 std::get<3>(s) = xmm3;
169 std::get<4>(s) = xmm4;
170 std::get<5>(s) = xmm5;
171 std::get<6>(s) = xmm6;
172 std::get<7>(s) = xmm7;
173 std::memcpy(rptr, s.data(), n *
sizeof(T) * K);
177 #endif // MCKL_USE_ASM_LIBRARY 187 #endif // MCKL_RANDOM_INTERNAL_PHILOX_SSE2_4X32_HPP static void eval(const void *plain, void *cipher, const std::array< T, K/2 > &key)
#define MCKL_PUSH_GCC_WARNING(warning)
void mckl_philox4x32_sse2_kernel(uint64_t *, size_t, void *, const void *)
#define MCKL_RANDOM_INTERNAL_PHILOX_SSE2_32_RBOX(K, N, imm8)
static void eval(std::array< std::uint64_t, 2 > &ctr, std::size_t n, ResultType *r, const std::array< T, K/2 > &key)
static void eval(std::array< std::uint64_t, 2 > &ctr, ResultType *r, const std::array< T, K/2 > &key)
#define MCKL_POP_GCC_WARNING