MCKL
Monte Carlo Kernel Library
philox_sse2_2x32.hpp
Go to the documentation of this file.
1 //============================================================================
2 // MCKL/include/mckl/random/internal/philox_sse2_2x32.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_2X32_HPP
33 #define MCKL_RANDOM_INTERNAL_PHILOX_SSE2_2X32_HPP
34 
40 
41 MCKL_PUSH_GCC_WARNING("-Wignored-attributes")
42 
43 namespace mckl {
44 
45 namespace internal {
46 
47 template <typename T, typename Constants>
49 {
50  static_assert(std::numeric_limits<T>::digits == 32,
51  "**Philox2x32GeneratorSSE2Impl** used with T other than a 32-bit "
52  "unsigned integers");
53 
54  static constexpr std::size_t K = 2;
55  static constexpr std::size_t Rounds = 10;
56 
57  public:
58  static void eval(
59  const void *plain, void *cipher, const std::array<T, K / 2> &key)
60  {
62  }
63 
64  template <typename ResultType>
65  static void eval(std::array<std::uint64_t, 1> &ctr, ResultType *r,
66  const std::array<T, K / 2> &key)
67  {
69  }
70 
71  template <typename ResultType>
72  static void eval(std::array<std::uint64_t, 1> &ctr, std::size_t n,
73  ResultType *r, const std::array<T, K / 2> &key)
74  {
75  constexpr std::size_t R = sizeof(T) * K / sizeof(ResultType);
76 
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()));
80 
81  eval_kernel(ctr, n0, r, key);
82  n -= n0;
83  r += n0 * R;
84 
85  if (n != 0) {
86  eval(ctr, r, key);
87  n -= 1;
88  r += R;
89  }
90 
91  eval_kernel(ctr, n, r, key);
92  }
93 
94  private:
95  template <typename ResultType>
96  static void eval_kernel(std::array<std::uint64_t, 1> &ctr, std::size_t n,
97  ResultType *r, const std::array<T, K / 2> &key)
98  {
99 #if MCKL_USE_ASM_LIBRARY
100  constexpr T m0 = Constants::multiplier::value[0];
101  constexpr T w0 = Constants::weyl::value[0];
102 
103  const T mwk[6] = {m0, 0, 0, w0, 0, std::get<0>(key)};
104  mckl_philox2x32_sse2_kernel(ctr.data(), n, r, mwk);
105 #else // MCKL_USE_ASM_LIBRARY
106  constexpr std::size_t S = 8;
107  constexpr std::size_t N = sizeof(__m128i) * S / (sizeof(T) * K);
108 
109  const int k0 = static_cast<int>(std::get<0>(key));
110  const __m128i xmmk0 = _mm_set_epi32(k0, 0, k0, 0);
111 
112  __m128i xmmc =
113  _mm_set1_epi64x(static_cast<MCKL_INT64>(std::get<0>(ctr)));
114  ctr.front() += n;
115 
116  __m128i *rptr = reinterpret_cast<__m128i *>(r);
117  while (n != 0) {
118  __m128i xmm0 = _mm_add_epi64(xmmc, _mm_set_epi64x(0x02, 0x01));
119  __m128i xmm1 = _mm_add_epi64(xmmc, _mm_set_epi64x(0x04, 0x03));
120  __m128i xmm2 = _mm_add_epi64(xmmc, _mm_set_epi64x(0x06, 0x05));
121  __m128i xmm3 = _mm_add_epi64(xmmc, _mm_set_epi64x(0x08, 0x07));
122  __m128i xmm4 = _mm_add_epi64(xmmc, _mm_set_epi64x(0x0A, 0x09));
123  __m128i xmm5 = _mm_add_epi64(xmmc, _mm_set_epi64x(0x0C, 0x0B));
124  __m128i xmm6 = _mm_add_epi64(xmmc, _mm_set_epi64x(0x0E, 0x0D));
125  __m128i xmm7 = _mm_add_epi64(xmmc, _mm_set_epi64x(0x10, 0x0F));
126  xmmc = _mm_add_epi64(xmmc, _mm_set1_epi64x(0x10));
127 
138 
139  if (n >= N) {
140  n -= N;
141  _mm_storeu_si128(rptr++, xmm0);
142  _mm_storeu_si128(rptr++, xmm1);
143  _mm_storeu_si128(rptr++, xmm2);
144  _mm_storeu_si128(rptr++, xmm3);
145  _mm_storeu_si128(rptr++, xmm4);
146  _mm_storeu_si128(rptr++, xmm5);
147  _mm_storeu_si128(rptr++, xmm6);
148  _mm_storeu_si128(rptr++, xmm7);
149  } else {
150  std::array<__m128i, S> s;
151  std::get<0>(s) = xmm0;
152  std::get<1>(s) = xmm1;
153  std::get<2>(s) = xmm2;
154  std::get<3>(s) = xmm3;
155  std::get<4>(s) = xmm4;
156  std::get<5>(s) = xmm5;
157  std::get<6>(s) = xmm6;
158  std::get<7>(s) = xmm7;
159  std::memcpy(rptr, s.data(), n * sizeof(T) * K);
160  break;
161  }
162  }
163 #endif // MCKL_USE_ASM_LIBRARY
164  }
165 }; // class Philox2x32GeneratorSSE2Impl
166 
167 } // namespace internal
168 
169 } // namespace mckl
170 
172 
173 #endif // MCKL_RANDOM_INTERNAL_PHILOX_SSE2_2X32_HPP
static void eval(std::array< std::uint64_t, 1 > &ctr, ResultType *r, const std::array< T, K/2 > &key)
#define MCKL_PUSH_GCC_WARNING(warning)
Definition: compiler.h:78
void mckl_philox2x32_sse2_kernel(uint64_t *, size_t, void *, const void *)
static void eval(const void *plain, void *cipher, const std::array< T, K/2 > &key)
#define MCKL_RANDOM_INTERNAL_PHILOX_SSE2_32_RBOX(K, N, imm8)
Definition: mcmc.hpp:40
#define MCKL_POP_GCC_WARNING
Definition: compiler.h:79
static void eval(std::array< std::uint64_t, 1 > &ctr, std::size_t n, ResultType *r, const std::array< T, K/2 > &key)