vSMC
vSMC: Scalable Monte Carlo
aes_ni.hpp
Go to the documentation of this file.
1 //============================================================================
2 // vSMC/include/vsmc/rng/aes_ni.hpp
3 //----------------------------------------------------------------------------
4 // vSMC: Scalable Monte Carlo
5 //----------------------------------------------------------------------------
6 // Copyright (c) 2013-2016, 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 VSMC_RNG_AES_NI_HPP
33 #define VSMC_RNG_AES_NI_HPP
34 
36 #include <vsmc/rng/counter.hpp>
37 #include <wmmintrin.h>
38 
39 namespace vsmc
40 {
41 
44 template <typename ResultType, typename KeySeqType, std::size_t Rounds,
45  std::size_t Blocks>
47 {
48  static_assert(std::is_unsigned<ResultType>::value,
49  "**AESNIGenerator** USED WITH ResultType OTHER THAN UNSIGNED INTEGER "
50  "TYPES");
51 
52  static_assert(
53  Blocks != 0, "**AESNIGenerator** USED WITH Blocks EQUAL TO ZERO");
54 
55  public:
56  using result_type = ResultType;
57  using ctr_type = std::array<ResultType, M128I<ResultType>::size()>;
58  using key_type = typename KeySeqType::key_type;
59 
60  static constexpr std::size_t size()
61  {
62  return Blocks * M128I<ResultType>::size();
63  }
64 
65  void reset(const key_type &key) { key_seq_.reset(key); }
66 
67  void operator()(ctr_type &ctr, const key_type &key,
68  std::array<ResultType, size()> &buffer) const
69  {
70  union {
71  std::array<M128I<>, Blocks> state;
72  std::array<ctr_type, Blocks> ctr_block;
73  std::array<ResultType, size()> result;
74  } buf;
75 
76  std::array<M128I<>, Rounds + 1> rk;
77  key_seq_(key, rk);
78  increment(ctr, buf.ctr_block);
79  enc_first(buf.state, rk);
80  enc_round<1>(
81  buf.state, rk, std::integral_constant<bool, 1 < Rounds>());
82  enc_last(buf.state, rk);
83  buffer = buf.result;
84  }
85 
86  void operator()(ctr_type &ctr, const key_type &key, std::size_t n,
87  std::array<ResultType, size()> *buffer) const
88  {
89  if (n == 0)
90  return;
91 
92  union {
93  std::array<M128I<>, Blocks> state;
94  std::array<ctr_type, Blocks> ctr_block;
95  std::array<ResultType, size()> result;
96  } buf;
97 
98  std::array<M128I<>, Rounds + 1> rk;
99  key_seq_(key, rk);
100  for (std::size_t i = 0; i != n; ++i) {
101  increment(ctr, buf.ctr_block);
102  enc_first(buf.state, rk);
103  enc_round<1>(
104  buf.state, rk, std::integral_constant<bool, 1 < Rounds>());
105  enc_last(buf.state, rk);
106  buffer[i] = buf.result;
107  }
108  }
109 
110  private:
111  KeySeqType key_seq_;
112 
113  template <std::size_t K>
114  void enc_first(std::array<M128I<>, K> &state,
115  const std::array<M128I<>, Rounds + 1> &rk) const
116  {
117  enc_first<0>(state, rk, std::true_type());
118  }
119 
120  template <std::size_t, std::size_t K>
121  void enc_first(std::array<M128I<>, K> &,
122  const std::array<M128I<>, Rounds + 1> &, std::false_type) const
123  {
124  }
125 
126  template <std::size_t B, std::size_t K>
127  void enc_first(std::array<M128I<>, K> &state,
128  const std::array<M128I<>, Rounds + 1> &rk, std::true_type) const
129  {
130  std::get<B>(state) ^= std::get<0>(rk);
131  enc_first<B + 1>(state, rk, std::integral_constant<bool, B + 1 < K>());
132  }
133 
134  template <std::size_t, std::size_t K>
135  void enc_round(std::array<M128I<>, K> &,
136  const std::array<M128I<>, Rounds + 1> &, std::false_type) const
137  {
138  }
139 
140  template <std::size_t N, std::size_t K>
141  void enc_round(std::array<M128I<>, K> &state,
142  const std::array<M128I<>, Rounds + 1> &rk, std::true_type) const
143  {
144  enc_round_block<0, N>(state, rk, std::true_type());
145  enc_round<N + 1>(
146  state, rk, std::integral_constant<bool, N + 1 < Rounds>());
147  }
148 
149  template <std::size_t, std::size_t, std::size_t K>
150  void enc_round_block(std::array<M128I<>, K> &,
151  const std::array<M128I<>, Rounds + 1> &, std::false_type) const
152  {
153  }
154 
155  template <std::size_t B, std::size_t N, std::size_t K>
156  void enc_round_block(std::array<M128I<>, K> &state,
157  const std::array<M128I<>, Rounds + 1> &rk, std::true_type) const
158 
159  {
160  std::get<B>(state) = _mm_aesenc_si128(
161  std::get<B>(state).value(), std::get<N>(rk).value());
162  enc_round_block<B + 1, N>(
163  state, rk, std::integral_constant<bool, B + 1 < K>());
164  }
165 
166  template <std::size_t K>
167  void enc_last(std::array<M128I<>, K> &state,
168  const std::array<M128I<>, Rounds + 1> &rk) const
169  {
170  enc_last<0>(state, rk, std::true_type());
171  }
172 
173  template <std::size_t, std::size_t K>
174  void enc_last(std::array<M128I<>, K> &,
175  const std::array<M128I<>, Rounds + 1> &, std::false_type) const
176  {
177  }
178 
179  template <std::size_t B, std::size_t K>
180  void enc_last(std::array<M128I<>, K> &state,
181  const std::array<M128I<>, Rounds + 1> &rk, std::true_type) const
182  {
183  std::get<B>(state) = _mm_aesenclast_si128(
184  std::get<B>(state).value(), std::get<Rounds>(rk).value());
185  enc_last<B + 1>(state, rk, std::integral_constant<bool, B + 1 < K>());
186  }
187 }; // class AESNIGenerator
188 
191 template <typename ResultType, typename KeySeqType, std::size_t Rounds,
192  std::size_t Blocks>
193 using AESNIEngine =
195 
196 } // namespace vsmc
197 
198 #endif // VSMC_RNG_AES_NI_HPP
Definition: monitor.hpp:49
void increment(std::array< T, K > &ctr)
Increment a counter by one.
Definition: counter.hpp:62
Counter based RNG engine.
Definition: counter.hpp:289
void operator()(ctr_type &ctr, const key_type &key, std::size_t n, std::array< ResultType, size()> *buffer) const
Definition: aes_ni.hpp:86
static constexpr std::size_t size()
Definition: aes_ni.hpp:60
std::array< ResultType, M128I< ResultType >::size()> ctr_type
Definition: aes_ni.hpp:57
void reset(const key_type &key)
Definition: aes_ni.hpp:65
typename KeySeqType::key_type key_type
Definition: aes_ni.hpp:58
static constexpr std::size_t size()
Definition: simd.hpp:135
ResultType result_type
Definition: aes_ni.hpp:56
void operator()(ctr_type &ctr, const key_type &key, std::array< ResultType, size()> &buffer) const
Definition: aes_ni.hpp:67
RNG generator using AES-NI instructions.
Definition: aes_ni.hpp:46