MCKL
Monte Carlo Kernel Library
philox_generic_4x.hpp
Go to the documentation of this file.
1 //============================================================================
2 // MCKL/include/mckl/random/internal/philox_generic_4x.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_GENERIC_4X_HPP
33 #define MCKL_RANDOM_INTERNAL_PHILOX_GENERIC_4X_HPP
34 
39 
40 #define MCKL_RANDOM_INTERNAL_PHILOX_GENERIC_4X_RBOX(N) \
41  { \
42  constexpr T w0 = Constants::weyl::value[0] * static_cast<T>(N - 1); \
43  constexpr T w1 = Constants::weyl::value[1] * static_cast<T>(N - 1); \
44  constexpr T m2 = Constants::multiplier::value[0]; \
45  constexpr T m0 = Constants::multiplier::value[1]; \
46  \
47  t1 = s1; \
48  t3 = s3; \
49  s1 = PhiloxHiLo<T>::eval(s2, m2, t2); \
50  s3 = PhiloxHiLo<T>::eval(s0, m0, t0); \
51  s0 = (k0 + w0) ^ (t1 ^ t2); \
52  s2 = (k1 + w1) ^ (t3 ^ t0); \
53  }
54 
55 #define MCKL_RANDOM_INTERNAL_PHILOX_GENERIC_4X_ROUND_10 \
56  T k0 = std::get<0>(key); \
57  T k1 = std::get<1>(key); \
58  T s0 = std::get<0>(buf.s); \
59  T s1 = std::get<1>(buf.s); \
60  T s2 = std::get<2>(buf.s); \
61  T s3 = std::get<3>(buf.s); \
62  T t0; \
63  T t1; \
64  T t2; \
65  T t3; \
66  MCKL_RANDOM_INTERNAL_PHILOX_GENERIC_4X_RBOX(0x1) \
67  MCKL_RANDOM_INTERNAL_PHILOX_GENERIC_4X_RBOX(0x2) \
68  MCKL_RANDOM_INTERNAL_PHILOX_GENERIC_4X_RBOX(0x3) \
69  MCKL_RANDOM_INTERNAL_PHILOX_GENERIC_4X_RBOX(0x4) \
70  MCKL_RANDOM_INTERNAL_PHILOX_GENERIC_4X_RBOX(0x5) \
71  MCKL_RANDOM_INTERNAL_PHILOX_GENERIC_4X_RBOX(0x6) \
72  MCKL_RANDOM_INTERNAL_PHILOX_GENERIC_4X_RBOX(0x7) \
73  MCKL_RANDOM_INTERNAL_PHILOX_GENERIC_4X_RBOX(0x8) \
74  MCKL_RANDOM_INTERNAL_PHILOX_GENERIC_4X_RBOX(0x9) \
75  MCKL_RANDOM_INTERNAL_PHILOX_GENERIC_4X_RBOX(0xA) \
76  std::get<0>(buf.s) = s0; \
77  std::get<1>(buf.s) = s1; \
78  std::get<2>(buf.s) = s2; \
79  std::get<3>(buf.s) = s3;
80 
81 namespace mckl {
82 
83 namespace internal {
84 
85 template <typename T, typename Constants>
87 {
88  static constexpr std::size_t K = 4;
89  static constexpr std::size_t Rounds = 10;
90 
91  public:
92  static void eval(
93  const void *plain, void *cipher, const std::array<T, K / 2> &key)
94  {
95  alignas(MCKL_ALIGNMENT) union {
96  std::array<T, K> s;
97  std::array<char, sizeof(T) * K> r;
98  } buf;
99 
100  std::memcpy(buf.s.data(), plain, sizeof(T) * K);
101  union_le<char>(buf.s);
103  union_le<T>(buf.r);
104  std::memcpy(cipher, buf.s.data(), sizeof(T) * K);
105  }
106 
107  template <typename ResultType>
108  static void eval(
109  Counter<T, K> &ctr, ResultType *r, const std::array<T, K / 2> &key)
110  {
111  alignas(MCKL_ALIGNMENT) union {
112  std::array<T, K> s;
113  Counter<T, K> c;
114  std::array<ResultType, sizeof(T) * K / sizeof(ResultType)> r;
115  } buf;
116 
118  buf.c = ctr;
119 #if MCKL_REQUIRE_ENDIANNESS_NEUTURAL
120  union_le<typename Counter<T, K>::value_type>(buf.s);
121 #endif
123 #if MCKL_REQUIRE_ENDIANNESS_NEUTURAL
124  union_le<T>(buf.r);
125 #endif
126  std::memcpy(r, buf.r.data(), sizeof(T) * K);
127  }
128 
129  template <typename ResultType>
130  static void eval(Counter<T, K> &ctr, std::size_t n, ResultType *r,
131  const std::array<T, K / 2> &key)
132  {
133  constexpr std::size_t R = sizeof(T) * K / sizeof(ResultType);
134 
135  for (std::size_t i = 0; i != n; ++i, r += R) {
136  eval(ctr, r, key);
137  }
138  }
139 }; // class Philox4xGeneratorGenericImpl
140 
141 template <typename T, typename Constants>
143 {
144  static_assert(std::numeric_limits<T>::digits == 64,
145  "**Philox4x64GeneratorGenericImpl** used with T other than a 64-bit "
146  "unsigned integers");
147 
148  static constexpr std::size_t K = 4;
149  static constexpr std::size_t Rounds = 10;
150 
151  public:
152  static void eval(
153  const void *plain, void *cipher, const std::array<T, K / 2> &key)
154  {
155  alignas(MCKL_ALIGNMENT) union {
156  std::array<T, K> s;
157  std::array<char, sizeof(T) * K> r;
158  } buf;
159 
160  std::memcpy(buf.s.data(), plain, sizeof(T) * K);
161  union_le<char>(buf.s);
163  union_le<T>(buf.r);
164  std::memcpy(cipher, buf.s.data(), sizeof(T) * K);
165  }
166 
167  template <typename ResultType>
168  static void eval(
169  Counter<T, K> &ctr, ResultType *r, const std::array<T, K / 2> &key)
170  {
171  alignas(MCKL_ALIGNMENT) union {
172  std::array<T, K> s;
173  Counter<T, K> c;
174  std::array<ResultType, sizeof(T) * K / sizeof(ResultType)> r;
175  } buf;
176 
178  buf.c = ctr;
179 #if MCKL_REQUIRE_ENDIANNESS_NEUTURAL
180  union_le<typename Counter<T, K>::value_type>(buf.s);
181 #endif
183 #if MCKL_REQUIRE_ENDIANNESS_NEUTURAL
184  union_le<T>(buf.r);
185 #endif
186  std::memcpy(r, buf.r.data(), sizeof(T) * K);
187  }
188 
189 #if MCKL_USE_ASM_LIBRARY && MCKL_USE_BMI2
190  template <typename ResultType>
191  static void eval(Counter<T, K> &ctr, std::size_t n, ResultType *r,
192  const std::array<T, K / 2> &key)
193  {
194  constexpr T w0 = Constants::weyl::value[0];
195  constexpr T w1 = Constants::weyl::value[1];
196  constexpr T m0 = Constants::multiplier::value[0];
197  constexpr T m1 = Constants::multiplier::value[1];
198 
199  const T mwk[6] = {m0, m1, w0, w1, std::get<0>(key), std::get<1>(key)};
200  mckl_philox4x64_bmi2_kernel(ctr.data(), n, r, mwk);
201  }
202 #else // MCKL_USE_ASM_LIBRARY && MCKL_USE_BMI2
203  template <typename ResultType>
204  static void eval(Counter<T, K> &ctr, std::size_t n, ResultType *r,
205  const std::array<T, K / 2> &key)
206  {
207  constexpr std::size_t R = sizeof(T) * K / sizeof(ResultType);
208 
209  for (std::size_t i = 0; i != n; ++i, r += R)
210  eval(ctr, r, key);
211  }
212 #endif // MCKL_USE_ASM_LIBRARY && MCKL_USE_BMI2
213 }; // class Philox4x64GeneratorGenericImpl
214 
215 } // namespace internal
216 
217 } // namespace mckl
218 
219 #endif // MCKL_RANDOM_INTERNAL_PHILOX_GENERIC_4X_HPP
static void eval(Counter< T, K > &ctr, std::size_t n, ResultType *r, const std::array< T, K/2 > &key)
#define MCKL_INLINE_CALL
Definition: intel.h:142
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
static void eval(const void *plain, void *cipher, const std::array< T, K/2 > &key)
void mckl_philox4x64_bmi2_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.
static void eval(const void *plain, void *cipher, const std::array< T, K/2 > &key)
Definition: mcmc.hpp:40
#define MCKL_ALIGNMENT
The default alignment for scalar type.
Definition: config.h:187
static void eval(Counter< T, K > &ctr, ResultType *r, const std::array< T, K/2 > &key)
static void eval(Counter< T, K > &ctr, std::size_t n, ResultType *r, const std::array< T, K/2 > &key)
#define MCKL_RANDOM_INTERNAL_PHILOX_GENERIC_4X_ROUND_10
static void eval(Counter< T, K > &ctr, ResultType *r, const std::array< T, K/2 > &key)