MCKL
Monte Carlo Kernel Library
threefry_common.hpp
Go to the documentation of this file.
1 //============================================================================
2 // MCKL/include/mckl/random/internal/threefry_common.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_THREEFRY_COMMON_HPP
33 #define MCKL_RANDOM_INTERNAL_THREEFRY_COMMON_HPP
34 
37 
38 namespace mckl {
39 
40 namespace internal {
41 
42 template <typename T, std::size_t K, typename Constants>
44 {
45  public:
46  static void eval(std::array<T, K> &s)
47  {
48  std::array<T, K> tmp;
49  eval<0>(s, tmp, std::integral_constant<bool, 0 < K>());
50  std::memcpy(s.data(), tmp.data(), sizeof(T) * K);
51  }
52 
53  static void eval(T *s)
54  {
55  std::array<T, K> tmp;
56  eval<0>(s, tmp, std::integral_constant<bool, 0 < K>());
57  std::memcpy(s, tmp.data(), sizeof(T) * K);
58  }
59 
60  private:
61  template <std::size_t>
62  static void eval(
63  const std::array<T, K> &, std::array<T, K> &, std::false_type)
64  {
65  }
66 
67  template <std::size_t I>
68  static void eval(
69  const std::array<T, K> &s, std::array<T, K> &tmp, std::true_type)
70  {
71  constexpr std::size_t P = Constants::permute::value[I];
72 
73  std::get<I>(tmp) = std::get<P>(s);
74  eval<I + 1>(s, tmp, std::integral_constant<bool, I + 1 < K>());
75  }
76 
77  template <std::size_t>
78  static void eval(const T *, std::array<T, K> &, std::false_type)
79  {
80  }
81 
82  template <std::size_t I>
83  static void eval(const T *s, std::array<T, K> &tmp, std::true_type)
84  {
85  constexpr std::size_t P = Constants::permute::value[I];
86 
87  std::get<I>(tmp) = s[P];
88  eval<I + 1>(s, tmp, std::integral_constant<bool, I + 1 < K>());
89  }
90 }; // class ThreefryPBox
91 
92 template <typename T, typename U>
93 class ThreefryPBox<T, 2, ThreefryConstants<U, 2>>
94 {
95  public:
96  static void eval(std::array<T, 2> &) {}
97 
98  static void eval(T *) {}
99 }; // class ThreefryPBox
100 
101 template <typename T, typename U>
102 class ThreefryPBox<T, 4, ThreefryConstants<U, 4>>
103 {
104  public:
105  static void eval(std::array<T, 4> &s)
106  {
107  T s1 = std::get<1>(s);
108  std::get<1>(s) = std::get<3>(s);
109  std::get<3>(s) = s1;
110  }
111 
112  static void eval(T *s)
113  {
114  T s1 = s[1];
115  s[1] = s[3];
116  s[3] = s1;
117  }
118 }; // class ThreefryPBox
119 
120 template <typename T, typename U>
121 class ThreefryPBox<T, 8, ThreefryConstants<U, 8>>
122 {
123  public:
124  static void eval(std::array<T, 8> &s)
125  {
126  T s0 = std::get<0>(s);
127  T s3 = std::get<3>(s);
128 
129  std::get<0>(s) = std::get<2>(s);
130  std::get<3>(s) = std::get<7>(s);
131 
132  std::get<2>(s) = std::get<4>(s);
133  std::get<4>(s) = std::get<6>(s);
134 
135  std::get<6>(s) = s0;
136  std::get<7>(s) = s3;
137  }
138 
139  static void eval(T *s)
140  {
141  T s0 = s[0];
142  T s3 = s[3];
143 
144  s[0] = s[2];
145  s[3] = s[7];
146 
147  s[2] = s[4];
148  s[4] = s[6];
149 
150  s[6] = s0;
151  s[7] = s3;
152  }
153 }; // class ThreefryPBox
154 
155 template <typename T, typename U>
156 class ThreefryPBox<T, 16, ThreefryConstants<U, 16>>
157 {
158  public:
159  static void eval(std::array<T, 16> &s)
160  {
161  T s1 = std::get<0x1>(s);
162  T s3 = std::get<0x3>(s);
163  T s4 = std::get<0x4>(s);
164  T s8 = std::get<0x8>(s);
165 
166  std::get<0x1>(s) = std::get<0x9>(s);
167  std::get<0x3>(s) = std::get<0xD>(s);
168  std::get<0x4>(s) = std::get<0x6>(s);
169  std::get<0x8>(s) = std::get<0xA>(s);
170 
171  std::get<0x9>(s) = std::get<0x7>(s);
172  std::get<0xD>(s) = std::get<0x5>(s);
173  std::get<0xA>(s) = std::get<0xC>(s);
174 
175  std::get<0x7>(s) = std::get<0xF>(s);
176  std::get<0x5>(s) = std::get<0xB>(s);
177  std::get<0xC>(s) = std::get<0xE>(s);
178 
179  std::get<0xF>(s) = s1;
180  std::get<0xB>(s) = s3;
181  std::get<0x6>(s) = s4;
182  std::get<0xE>(s) = s8;
183  }
184 
185  static void eval(T *s)
186  {
187  T s1 = s[0x1];
188  T s3 = s[0x3];
189  T s4 = s[0x4];
190  T s8 = s[0x8];
191 
192  s[0x1] = s[0x9];
193  s[0x3] = s[0xD];
194  s[0x4] = s[0x6];
195  s[0x8] = s[0xA];
196 
197  s[0x9] = s[0x7];
198  s[0xD] = s[0x5];
199  s[0xA] = s[0xC];
200 
201  s[0x7] = s[0xF];
202  s[0x5] = s[0xB];
203  s[0xC] = s[0xE];
204 
205  s[0xF] = s1;
206  s[0xB] = s3;
207  s[0x6] = s4;
208  s[0xE] = s8;
209  }
210 }; // class ThreefryPBox
211 
212 template <typename T, std::size_t K, std::size_t N>
214 {
215  public:
216  template <std::size_t I>
217  static T key(const std::array<T, K + 4> &par)
218  {
219  constexpr std::size_t S = N / 4;
220 
221  const T p = (I + 1 == K ? S : 0) +
222  (I + 2 == K ? std::get<K + 1 + (S + 1) % 3>(par) : 0) +
223  (I + 3 == K ? std::get<K + 1 + (S + 0) % 3>(par) : 0);
224 
225  return std::get<(S + I) % (K + 1)>(par) + p;
226  }
227 
228  static void eval(std::array<T, K> &s, const std::array<T, K + 4> &par)
229  {
230  eval<0>(s, par, std::integral_constant<bool, 0 < K>());
231  }
232 
233  private:
234  template <std::size_t>
235  static void eval(
236  std::array<T, K> &, const std::array<T, K + 4> &, std::false_type)
237  {
238  }
239 
240  template <std::size_t I>
241  static void eval(
242  std::array<T, K> &s, const std::array<T, K + 4> &par, std::true_type)
243  {
244  std::get<I>(s) += key<I>(par);
245  eval<I + 1>(s, par, std::integral_constant<bool, I + 1 < K>());
246  }
247 }; // class ThreefryKBox
248 
249 template <typename T, std::size_t K, std::size_t N, typename Constants>
251 {
252  public:
253  static void eval(std::array<T, K> &s)
254  {
255  sbox<0>(s, std::integral_constant<bool, 0 < K / 2>());
257  }
258 
259  private:
260  template <std::size_t>
261  static void sbox(std::array<T, K> &, std::false_type)
262  {
263  }
264 
265  template <std::size_t I>
266  static void sbox(std::array<T, K> &s, std::true_type)
267  {
268  constexpr std::size_t I0 = I * 2;
269  constexpr std::size_t I1 = I * 2 + 1;
270  constexpr int L = Constants::rotate::value[I][(N - 1) % 8];
271  constexpr int R = std::numeric_limits<T>::digits - L;
272 
273  T x = std::get<I1>(s);
274  std::get<I0>(s) += x;
275  x = (x << L) | (x >> R);
276  x ^= std::get<I0>(s);
277  std::get<I1>(s) = x;
278  sbox<I + 1>(s, std::integral_constant<bool, I + 1 < K / 2>());
279  }
280 }; // class ThreefryRBox
281 
282 } // namespace internal
283 
284 } // namespace mckl
285 
286 #endif // MCKL_RANDOM_INTERNAL_THREEFRY_COMMON_HPP
static T key(const std::array< T, K+4 > &par)
static void eval(std::array< T, K > &s)
static void eval(std::array< T, K > &s)
Default Threefry constants.
Definition: mcmc.hpp:40
static void eval(std::array< T, K > &s, const std::array< T, K+4 > &par)