MCKL
Monte Carlo Kernel Library
philox_sse2_32.hpp
Go to the documentation of this file.
1 //============================================================================
2 // MCKL/include/mckl/random/internal/philox_sse2_32.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_PHILOX_SSE2_32_HPP
33 #define MCKL_RANDOM_INTERNAL_PHILOX_SSE2_32_HPP
34 
42 
43 MCKL_PUSH_GCC_WARNING("-Wignored-attributes")
44 
45 namespace mckl {
46 
47 namespace internal {
48 
49 template <std::size_t>
51 
52 template <>
54 {
55  public:
56  template <std::size_t S>
57  MCKL_INLINE static void first(std::array<__m128i, S> &)
58  {
59  }
60 
61  template <std::size_t S>
62  MCKL_INLINE static void round(std::array<__m128i, S> &s)
63  {
64  shuffle_epi32<0xB1>(s);
65  }
66 
67  template <std::size_t S>
68  MCKL_INLINE static void last(std::array<__m128i, S> &s)
69  {
70  shuffle_epi32<0xB1>(s);
71  }
72 }; // class PhiloxGeneratorSSE2Impl32Permute
73 
74 template <>
76 {
77  public:
78  template <std::size_t S>
79  MCKL_INLINE static void first(std::array<__m128i, S> &s)
80  {
81  shuffle_epi32<0xC6>(s);
82  }
83 
84  template <std::size_t S>
85  MCKL_INLINE static void round(std::array<__m128i, S> &s)
86  {
87  shuffle_epi32<0x93>(s);
88  }
89 
90  template <std::size_t S>
91  MCKL_INLINE static void last(std::array<__m128i, S> &s)
92  {
93  shuffle_epi32<0xB1>(s);
94  }
95 }; // class PhiloxGeneratorSSE2Impl32Permute
96 
97 template <typename T, std::size_t K, std::size_t Rounds, typename Constants>
99 {
100  public:
101  static void eval(
102  const void *plain, void *cipher, const std::array<T, K / 2> &key)
103  {
105  plain, cipher, key);
106  }
107 
108  template <typename ResultType>
109  static void eval(
110  Counter<T, K> &ctr, ResultType *r, const std::array<T, K / 2> &key)
111  {
113  }
114 
115  template <typename ResultType>
116  static void eval(Counter<T, K> &ctr, std::size_t n, ResultType *r,
117  const std::array<T, K / 2> &key)
118  {
119  constexpr std::size_t S = 8;
120  constexpr std::size_t N = sizeof(__m128i) * S / (sizeof(T) * K);
121  constexpr std::size_t R = sizeof(T) * K / sizeof(ResultType);
122 
123  const std::array<__m128i, Rounds> rk(round_key(key));
124  while (n >= N) {
125  std::array<__m128i, S> s;
130  std::memcpy(r, s.data(), sizeof(__m128i) * N);
131  n -= N;
132  r += N * R;
133  }
134 
135  alignas(MCKL_ALIGNMENT) std::array<ResultType, N * R> t;
137  ctr, n, t.data(), key);
138  std::memcpy(r, t.data(), sizeof(__m128i) * n);
139  }
140 
141  private:
142  template <std::size_t, std::size_t S>
143  static void round(std::array<__m128i, S> &,
144  const std::array<__m128i, Rounds> &, std::false_type)
145  {
146  }
147 
148  template <std::size_t N, std::size_t S>
149  static void round(std::array<__m128i, S> &s,
150  const std::array<__m128i, Rounds> &rk, std::true_type)
151  {
153  }
154 
155  template <std::size_t N, std::size_t S>
156  MCKL_INLINE static void rbox(
157  std::array<__m128i, S> &s, const std::array<__m128i, Rounds> &rk)
158  {
159  rbox<N>(s, rk, std::integral_constant<bool, (N > 0 && N <= Rounds)>());
160  }
161 
162  template <std::size_t, std::size_t S>
163  static void rbox(std::array<__m128i, S> &,
164  const std::array<__m128i, Rounds> &, std::false_type)
165  {
166  }
167 
168  template <std::size_t N, std::size_t S>
169  static void rbox(std::array<__m128i, S> &s,
170  const std::array<__m128i, Rounds> &rk, std::true_type)
171  {
172  constexpr int mul0 =
173  static_cast<int>(Constants::multiplier::value[0 % (K / 2)]);
174  constexpr int mul1 =
175  static_cast<int>(Constants::multiplier::value[1 % (K / 2)]);
176  constexpr int mask = static_cast<int>(0xFFFFFFFF);
177 
178  const __m128i m = _mm_set_epi32(0, mul1, 0, mul0);
179  const __m128i a = _mm_set_epi32(mask, 0, mask, 0);
180  const __m128i k = std::get<N - 1>(rk);
181 
182  std::array<__m128i, S> t;
183  mul_epu32(s, m, t);
184  and_si128(s, a);
185  xor_si128(s, k);
186  xor_si128(s, t);
187  permute<N>(s);
188  }
189 
190  MCKL_INLINE static std::array<__m128i, Rounds> round_key(
191  const std::array<T, K / 2> &key)
192  {
193  const int k0 = static_cast<int>(std::get<0 % (K / 2)>(key));
194  const int k1 = static_cast<int>(std::get<1 % (K / 2)>(key));
195 
196  std::array<__m128i, Rounds> rk;
197  set_key<0>(rk, _mm_set_epi32(k1, 0, k0, 0), std::true_type());
198 
199  return rk;
200  }
201 
202  template <std::size_t>
203  static void set_key(
204  std::array<__m128i, Rounds> &, const __m128i &, std::false_type)
205  {
206  }
207 
208  template <std::size_t N>
209  static void set_key(
210  std::array<__m128i, Rounds> &rk, const __m128i &k, std::true_type)
211  {
212  constexpr int w0 =
213  static_cast<int>(Constants::weyl::value[0 % (K / 2)] * N);
214  constexpr int w1 =
215  static_cast<int>(Constants::weyl::value[1 % (K / 2)] * N);
216 
217  std::get<N>(rk) = _mm_add_epi32(k, _mm_set_epi32(w1, 0, w0, 0));
218  set_key<N + 1>(rk, k, std::integral_constant<bool, N + 1 < Rounds>());
219  }
220 
221  template <std::size_t N, std::size_t S>
222  static void permute(std::array<__m128i, S> &s)
223  {
224  permute(s, std::integral_constant<bool, (N > 0 && N < Rounds)>());
225  }
226 
227  template <std::size_t S>
228  static void permute(std::array<__m128i, S> &, std::false_type)
229  {
230  }
231 
232  template <std::size_t S>
233  static void permute(std::array<__m128i, S> &s, std::true_type)
234  {
236  }
237 }; // class PhiloxGeneratorSSE2Impl32
238 
239 template <typename T, typename Constants>
240 class PhiloxGeneratorSSE2Impl32<T, 2, 10, Constants>
241  : public Philox2x32GeneratorSSE2Impl<T, Constants>
242 {
243 }; // class PhiloxGeneratorSSE2Impl32
244 
245 template <typename T, typename Constants>
246 class PhiloxGeneratorSSE2Impl32<T, 4, 10, Constants>
247  : public Philox4x32GeneratorSSE2Impl<T, Constants>
248 {
249 }; // class PhiloxGeneratorSSE2Impl32
250 
251 } // namespace internal
252 
253 } // namespace mckl
254 
256 
257 #endif // MCKL_RANDOM_INTERNAL_PHILOX_SSE2_32_HPP
static void eval(Counter< T, K > &ctr, std::size_t n, ResultType *r, const std::array< T, K/2 > &key)
#define MCKL_PUSH_GCC_WARNING(warning)
Definition: compiler.h:78
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)
Definition: vmf.hpp:310
#define MCKL_INLINE_CALL
Definition: intel.h:142
static void eval(const void *plain, void *cipher, const std::array< T, K/2 > &key)
typename internal::CounterImpl< T, K >::type Counter
A counter type with the same width as std::array<T, K> but with possibly fewer elements.
Definition: increment.hpp:104
#define MCKL_RANDOM_INTERNAL_PHILOX_UNROLL_ROUND(N, s, rk)
static void eval(Counter< T, K > &ctr, ResultType *r, const std::array< T, K/2 > &key)
Definition: mcmc.hpp:40
#define MCKL_ALIGNMENT
The default alignment for scalar type.
Definition: config.h:187
#define MCKL_INLINE
Definition: clang.h:147
#define MCKL_POP_GCC_WARNING
Definition: compiler.h:79