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