MCKL
Monte Carlo Kernel Library
aes_aesni_ars.hpp
Go to the documentation of this file.
1 //============================================================================
2 // MCKL/include/mckl/random/internal/aes_aesni_ars.hpp
3 //----------------------------------------------------------------------------
4 // MCKL: Monte Carlo Kernel Library
5 //----------------------------------------------------------------------------
6 // Copyright (c) 2013-2018, Yan Zhou
7 // All rights reserved.
8 //
9 // Redistribution and use in source and binary forms, with or without
10 // modification, are permitted provided that the following conditions are met:
11 //
12 // Redistributions of source code must retain the above copyright notice,
13 // this list of conditions and the following disclaimer.
14 //
15 // Redistributions in binary form must reproduce the above copyright notice,
16 // this list of conditions and the following disclaimer in the documentation
17 // and/or other materials provided with the distribution.
18 //
19 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS AS IS
20 // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
23 // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 // POSSIBILITY OF SUCH DAMAGE.
30 //============================================================================
31 
32 #ifndef MCKL_RANDOM_INTERNAL_AES_AESNI_ARS_HPP
33 #define MCKL_RANDOM_INTERNAL_AES_AESNI_ARS_HPP
34 
39 
40 MCKL_PUSH_GCC_WARNING("-Wignored-attributes")
41 
42 namespace mckl {
43 
44 namespace internal {
45 
46 template <typename Constants>
48 {
49  public:
50  using key_type = std::array<std::uint32_t, 4>;
51  using rk_type = __m128i;
52 
53  template <std::size_t Rp1>
54  static key_type key(const std::array<__m128i, Rp1> &rk)
55  {
56  key_type key;
57  std::memcpy(key.data(), rk.data(), sizeof(key_type));
58 
59  return key;
60  }
61 
62  template <std::size_t Rp1>
63  void operator()(const key_type &key, std::array<__m128i, Rp1> &rk)
64  {
65  key_ = _mm_set_epi32(static_cast<int>(std::get<3>(key)),
66  static_cast<int>(std::get<2>(key)),
67  static_cast<int>(std::get<1>(key)),
68  static_cast<int>(std::get<0>(key)));
69  generate<0>(rk, std::integral_constant<bool, 0 < Rp1>());
70  }
71 
72  private:
73  __m128i key_;
74 
75  template <std::size_t, std::size_t Rp1>
76  void generate(std::array<__m128i, Rp1> &, std::false_type) const
77  {
78  }
79 
80  template <std::size_t N, std::size_t Rp1>
81  void generate(std::array<__m128i, Rp1> &rk, std::true_type) const
82  {
83  constexpr MCKL_INT64 w0 =
84  static_cast<MCKL_INT64>(Constants::weyl::value[0] * N);
85  constexpr MCKL_INT64 w1 =
86  static_cast<MCKL_INT64>(Constants::weyl::value[1] * N);
87 
88  __m128i w = _mm_set_epi64x(w1, w0);
89  std::get<N>(rk) = _mm_add_epi64(key_, w);
90  generate<N + 1>(rk, std::integral_constant<bool, N + 1 < Rp1>());
91  }
92 }; // class ARSKeySeqGeneratorAESNIImpl
93 
94 template <typename Constants>
96 {
97  using KeySeqType =
99 
100  public:
101  static void eval(const void *plain, void *cipher, const KeySeqType &ks)
102  {
103  constexpr MCKL_INT64 w0 =
104  static_cast<MCKL_INT64>(Constants::weyl::value[0]);
105  constexpr MCKL_INT64 w1 =
106  static_cast<MCKL_INT64>(Constants::weyl::value[1]);
107  const __m128i xmmw = _mm_set_epi64x(w1, w0);
108 
109  auto &&key = ks.key();
110  __m128i xmmk =
111  _mm_set_epi64x(static_cast<MCKL_INT64>(std::get<1>(key)),
112  static_cast<MCKL_INT64>(std::get<0>(key)));
113 
114  __m128i xmm0 =
115  _mm_loadu_si128(reinterpret_cast<const __m128i *>(plain));
116 
117  xmm0 = _mm_xor_si128(xmm0, xmmk);
118  xmmk = _mm_add_epi64(xmmk, xmmw);
119  xmm0 = _mm_aesenc_si128(xmm0, xmmk);
120  xmmk = _mm_add_epi64(xmmk, xmmw);
121  xmm0 = _mm_aesenc_si128(xmm0, xmmk);
122  xmmk = _mm_add_epi64(xmmk, xmmw);
123  xmm0 = _mm_aesenc_si128(xmm0, xmmk);
124  xmmk = _mm_add_epi64(xmmk, xmmw);
125  xmm0 = _mm_aesenc_si128(xmm0, xmmk);
126  xmmk = _mm_add_epi64(xmmk, xmmw);
127  xmm0 = _mm_aesenclast_si128(xmm0, xmmk);
128 
129  _mm_storeu_si128(reinterpret_cast<__m128i *>(cipher), xmm0);
130  }
131 
132  template <typename ResultType>
133  static void eval(
134  std::array<std::uint64_t, 2> &ctr, ResultType *r, const KeySeqType &ks)
135  {
137 
138  constexpr MCKL_INT64 w0 =
139  static_cast<MCKL_INT64>(Constants::weyl::value[0]);
140  constexpr MCKL_INT64 w1 =
141  static_cast<MCKL_INT64>(Constants::weyl::value[1]);
142  const __m128i xmmw = _mm_set_epi64x(w1, w0);
143 
144  auto &&key = ks.key();
145  __m128i xmmk =
146  _mm_set_epi64x(static_cast<MCKL_INT64>(std::get<1>(key)),
147  static_cast<MCKL_INT64>(std::get<0>(key)));
148 
149  __m128i xmm0 =
150  _mm_set_epi64x(static_cast<MCKL_INT64>(std::get<1>(ctr)),
151  static_cast<MCKL_INT64>(std::get<0>(ctr)));
152 
153  xmm0 = _mm_xor_si128(xmm0, xmmk);
154  xmmk = _mm_add_epi64(xmmk, xmmw);
155  xmm0 = _mm_aesenc_si128(xmm0, xmmk);
156  xmmk = _mm_add_epi64(xmmk, xmmw);
157  xmm0 = _mm_aesenc_si128(xmm0, xmmk);
158  xmmk = _mm_add_epi64(xmmk, xmmw);
159  xmm0 = _mm_aesenc_si128(xmm0, xmmk);
160  xmmk = _mm_add_epi64(xmmk, xmmw);
161  xmm0 = _mm_aesenc_si128(xmm0, xmmk);
162  xmmk = _mm_add_epi64(xmmk, xmmw);
163  xmm0 = _mm_aesenclast_si128(xmm0, xmmk);
164 
165  _mm_storeu_si128(reinterpret_cast<__m128i *>(r), xmm0);
166  }
167 
169 
170  private:
171  template <typename ResultType>
172  static void eval_kernel(std::array<std::uint64_t, 2> &ctr, std::size_t n,
173  ResultType *r, const KeySeqType &ks)
174  {
175 #if MCKL_USE_ASM_LIBRARY
176  constexpr std::uint64_t w0 = Constants::weyl::value[0];
177  constexpr std::uint64_t w1 = Constants::weyl::value[1];
178 
179  auto &&key = ks.key();
180 
181  const std::uint64_t wk[4] = {w0, w1,
182  static_cast<std::uint64_t>(std::get<0>(key)) +
183  (static_cast<std::uint64_t>(std::get<1>(key)) << 32),
184  static_cast<std::uint64_t>(std::get<2>(key)) +
185  (static_cast<std::uint64_t>(std::get<3>(key)) << 32)};
186 #if MCKL_USE_AVX2
187  mckl_ars_aesni_avx2_kernel(ctr.data(), n, r, wk);
188 #else
189  mckl_ars_aesni_sse2_kernel(ctr.data(), n, r, wk);
190 #endif
191 #else // MCKL_USE_ASM_LIBRARY
192  constexpr std::size_t S = 8;
193  constexpr std::size_t N = S;
194 
195  constexpr MCKL_INT64 w0 =
196  static_cast<MCKL_INT64>(Constants::weyl::value[0]);
197  constexpr MCKL_INT64 w1 =
198  static_cast<MCKL_INT64>(Constants::weyl::value[1]);
199  const __m128i xmmw = _mm_set_epi64x(w1, w0);
200 
201  auto &&key = ks.key();
202  const __m128i xmmk0 =
203  _mm_set_epi64x(static_cast<MCKL_INT64>(std::get<1>(key)),
204  static_cast<MCKL_INT64>(std::get<0>(key)));
205  const __m128i xmmk1 = _mm_add_epi64(xmmk0, xmmw);
206  const __m128i xmmk2 = _mm_add_epi64(xmmk1, xmmw);
207  const __m128i xmmk3 = _mm_add_epi64(xmmk2, xmmw);
208  const __m128i xmmk4 = _mm_add_epi64(xmmk3, xmmw);
209  const __m128i xmmk5 = _mm_add_epi64(xmmk4, xmmw);
210 
211  __m128i xmmc =
212  _mm_set_epi64x(static_cast<MCKL_INT64>(std::get<1>(ctr)),
213  static_cast<MCKL_INT64>(std::get<0>(ctr)));
214  ctr.front() += n;
215 
216  __m128i *rptr = reinterpret_cast<__m128i *>(r);
217  while (n != 0) {
218  __m128i xmm0 = _mm_add_epi64(xmmc, _mm_set_epi64x(0, 1));
219  __m128i xmm1 = _mm_add_epi64(xmmc, _mm_set_epi64x(0, 2));
220  __m128i xmm2 = _mm_add_epi64(xmmc, _mm_set_epi64x(0, 3));
221  __m128i xmm3 = _mm_add_epi64(xmmc, _mm_set_epi64x(0, 4));
222  __m128i xmm4 = _mm_add_epi64(xmmc, _mm_set_epi64x(0, 5));
223  __m128i xmm5 = _mm_add_epi64(xmmc, _mm_set_epi64x(0, 6));
224  __m128i xmm6 = _mm_add_epi64(xmmc, _mm_set_epi64x(0, 7));
225  __m128i xmm7 = _mm_add_epi64(xmmc, _mm_set_epi64x(0, 8));
226  xmmc = xmm7;
227 
235  }
236 #endif // MCKL_USE_ASM_LIBRARY
237  }
238 }; // class ARSGeneratorAESNIImpl
239 
240 } // namespace internal
241 
242 } // namespace mckl
243 
245 
246 #endif // MCKL_RANDOM_INTERNAL_AES_AESNI_ARS_HPP
#define MCKL_PUSH_GCC_WARNING(warning)
Definition: compiler.h:78
static void eval(const void *plain, void *cipher, const KeySeqType &ks)
#define MCKL_INLINE_CALL
Definition: intel.h:142
#define MCKL_INT64
Definition: clang.h:134
ulong uint64_t
Definition: opencl.h:42
static void eval(std::array< std::uint64_t, 2 > &ctr, ResultType *r, const KeySeqType &ks)
#define MCKL_RANDOM_INTERNAL_AES_AESNI_ENC(xmmk)
#define MCKL_RANDOM_INTERNAL_AES_AESNI_STORE(n, N, rptr)
std::array< std::uint32_t, 4 > key_type
#define MCKL_RANDOM_INTERNAL_AES_AESNI_ENCFIRST(xmmk)
const key_type & key() const
#define MCKL_RANDOM_INTERNAL_AES_AESNI_EVAL
void mckl_ars_aesni_sse2_kernel(uint64_t *, size_t, void *, const void *)
void mckl_ars_aesni_avx2_kernel(uint64_t *, size_t, void *, const void *)
void increment(std::array< T, K > &ctr, std::integral_constant< T, NSkip >)
Increment a counter by given steps.
Definition: mcmc.hpp:40
void operator()(const key_type &key, std::array< __m128i, Rp1 > &rk)
#define MCKL_RANDOM_INTERNAL_AES_AESNI_ENCLAST(xmmk)
#define MCKL_POP_GCC_WARNING
Definition: compiler.h:79
static key_type key(const std::array< __m128i, Rp1 > &rk)