vSMC
vSMC: Scalable Monte Carlo
threefry.hpp
Go to the documentation of this file.
1 //============================================================================
2 // vSMC/include/vsmc/rng/threefry.hpp
3 //----------------------------------------------------------------------------
4 // vSMC: Scalable Monte Carlo
5 //----------------------------------------------------------------------------
6 // Copyright (c) 2013-2016, 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 VSMC_RNG_THREEFRY_HPP
33 #define VSMC_RNG_THREEFRY_HPP
34 
36 #include <vsmc/rng/counter.hpp>
37 
38 #define VSMC_DEFINE_RNG_THREEFRY_ROTATE_CONSTANT(T, K, N, I, val) \
39  template <> \
40  class ThreefryRotateConstant<T, K, N, I> \
41  : public std::integral_constant<int, val> \
42  { \
43  }; // class ThreefryRotateConstant
44 
47 #ifndef VSMC_RNG_THREEFRY_ROUNDS
48 #define VSMC_RNG_THREEFRY_ROUNDS 20
49 #endif
50 
53 #ifndef VSMC_RNG_THREEFRY_VECTOR_LENGTH
54 #define VSMC_RNG_THREEFRY_VECTOR_LENGTH 4
55 #endif
56 
57 namespace vsmc
58 {
59 
60 namespace internal
61 {
62 
63 template <typename>
65 
66 template <typename T, template <typename> class SIMD>
67 class ThreefryKSConstant<SIMD<T>> : public ThreefryKSConstant<T>
68 {
69 }; // class ThreefryKSConstant
70 
71 template <>
73  : public std::integral_constant<std::uint32_t, UINT32_C(0x1BD11BDA)>
74 {
75 }; // class ThreefryKSConstant
76 
77 template <>
79  : public std::integral_constant<std::uint64_t,
80  UINT64_C(0x1BD11BDAA9FC1A22)>
81 {
82 }; // class ThreefryKSConstant
83 
84 template <typename, std::size_t, std::size_t, std::size_t>
86 
87 template <typename T, template <typename> class SIMD, std::size_t K,
88  std::size_t N, std::size_t I>
89 class ThreefryRotateConstant<SIMD<T>, K, N, I>
90  : public ThreefryRotateConstant<T, K, N, I>
91 {
92 }; // class ThreefryRotateConstant
93 
96 VSMC_DEFINE_RNG_THREEFRY_ROTATE_CONSTANT(std::uint32_t, 2, 2, 0, 26)
97 VSMC_DEFINE_RNG_THREEFRY_ROTATE_CONSTANT(std::uint32_t, 2, 3, 0, 6)
98 VSMC_DEFINE_RNG_THREEFRY_ROTATE_CONSTANT(std::uint32_t, 2, 4, 0, 17)
99 VSMC_DEFINE_RNG_THREEFRY_ROTATE_CONSTANT(std::uint32_t, 2, 5, 0, 29)
100 VSMC_DEFINE_RNG_THREEFRY_ROTATE_CONSTANT(std::uint32_t, 2, 6, 0, 16)
101 VSMC_DEFINE_RNG_THREEFRY_ROTATE_CONSTANT(std::uint32_t, 2, 7, 0, 24)
102 
103 VSMC_DEFINE_RNG_THREEFRY_ROTATE_CONSTANT(std::uint32_t, 4, 0, 0, 10)
104 VSMC_DEFINE_RNG_THREEFRY_ROTATE_CONSTANT(std::uint32_t, 4, 1, 0, 11)
105 VSMC_DEFINE_RNG_THREEFRY_ROTATE_CONSTANT(std::uint32_t, 4, 2, 0, 13)
106 VSMC_DEFINE_RNG_THREEFRY_ROTATE_CONSTANT(std::uint32_t, 4, 3, 0, 23)
108 VSMC_DEFINE_RNG_THREEFRY_ROTATE_CONSTANT(std::uint32_t, 4, 5, 0, 17)
109 VSMC_DEFINE_RNG_THREEFRY_ROTATE_CONSTANT(std::uint32_t, 4, 6, 0, 25)
110 VSMC_DEFINE_RNG_THREEFRY_ROTATE_CONSTANT(std::uint32_t, 4, 7, 0, 18)
111 
112 VSMC_DEFINE_RNG_THREEFRY_ROTATE_CONSTANT(std::uint32_t, 4, 0, 1, 26)
113 VSMC_DEFINE_RNG_THREEFRY_ROTATE_CONSTANT(std::uint32_t, 4, 1, 1, 21)
114 VSMC_DEFINE_RNG_THREEFRY_ROTATE_CONSTANT(std::uint32_t, 4, 2, 1, 27)
116 VSMC_DEFINE_RNG_THREEFRY_ROTATE_CONSTANT(std::uint32_t, 4, 4, 1, 20)
117 VSMC_DEFINE_RNG_THREEFRY_ROTATE_CONSTANT(std::uint32_t, 4, 5, 1, 11)
118 VSMC_DEFINE_RNG_THREEFRY_ROTATE_CONSTANT(std::uint32_t, 4, 6, 1, 10)
119 VSMC_DEFINE_RNG_THREEFRY_ROTATE_CONSTANT(std::uint32_t, 4, 7, 1, 20)
120 
122 VSMC_DEFINE_RNG_THREEFRY_ROTATE_CONSTANT(std::uint64_t, 2, 1, 0, 42)
123 VSMC_DEFINE_RNG_THREEFRY_ROTATE_CONSTANT(std::uint64_t, 2, 2, 0, 12)
124 VSMC_DEFINE_RNG_THREEFRY_ROTATE_CONSTANT(std::uint64_t, 2, 3, 0, 31)
125 VSMC_DEFINE_RNG_THREEFRY_ROTATE_CONSTANT(std::uint64_t, 2, 4, 0, 16)
126 VSMC_DEFINE_RNG_THREEFRY_ROTATE_CONSTANT(std::uint64_t, 2, 5, 0, 32)
127 VSMC_DEFINE_RNG_THREEFRY_ROTATE_CONSTANT(std::uint64_t, 2, 6, 0, 24)
128 VSMC_DEFINE_RNG_THREEFRY_ROTATE_CONSTANT(std::uint64_t, 2, 7, 0, 21)
129 
130 VSMC_DEFINE_RNG_THREEFRY_ROTATE_CONSTANT(std::uint64_t, 4, 0, 0, 14)
131 VSMC_DEFINE_RNG_THREEFRY_ROTATE_CONSTANT(std::uint64_t, 4, 1, 0, 52)
132 VSMC_DEFINE_RNG_THREEFRY_ROTATE_CONSTANT(std::uint64_t, 4, 2, 0, 23)
134 VSMC_DEFINE_RNG_THREEFRY_ROTATE_CONSTANT(std::uint64_t, 4, 4, 0, 25)
135 VSMC_DEFINE_RNG_THREEFRY_ROTATE_CONSTANT(std::uint64_t, 4, 5, 0, 46)
136 VSMC_DEFINE_RNG_THREEFRY_ROTATE_CONSTANT(std::uint64_t, 4, 6, 0, 58)
137 VSMC_DEFINE_RNG_THREEFRY_ROTATE_CONSTANT(std::uint64_t, 4, 7, 0, 32)
138 
139 VSMC_DEFINE_RNG_THREEFRY_ROTATE_CONSTANT(std::uint64_t, 4, 0, 1, 16)
140 VSMC_DEFINE_RNG_THREEFRY_ROTATE_CONSTANT(std::uint64_t, 4, 1, 1, 57)
141 VSMC_DEFINE_RNG_THREEFRY_ROTATE_CONSTANT(std::uint64_t, 4, 2, 1, 40)
142 VSMC_DEFINE_RNG_THREEFRY_ROTATE_CONSTANT(std::uint64_t, 4, 3, 1, 37)
143 VSMC_DEFINE_RNG_THREEFRY_ROTATE_CONSTANT(std::uint64_t, 4, 4, 1, 33)
144 VSMC_DEFINE_RNG_THREEFRY_ROTATE_CONSTANT(std::uint64_t, 4, 5, 1, 12)
145 VSMC_DEFINE_RNG_THREEFRY_ROTATE_CONSTANT(std::uint64_t, 4, 6, 1, 22)
146 VSMC_DEFINE_RNG_THREEFRY_ROTATE_CONSTANT(std::uint64_t, 4, 7, 1, 32)
147 
148 template <typename T, std::size_t K>
150 {
151  public:
152  static void eval(const std::array<T, K> &key, std::array<T, K + 1> &par)
153  {
154  par.back() = ThreefryKSConstant<T>::value;
155  par_xor<0>(key, par, std::integral_constant<bool, 0 < K>());
156  }
157 
158  private:
159  template <std::size_t>
160  static void par_xor(
161  const std::array<T, K> &, std::array<T, K + 1> &, std::false_type)
162  {
163  }
164 
165  template <std::size_t N>
166  static void par_xor(
167  const std::array<T, K> &key, std::array<T, K + 1> &par, std::true_type)
168  {
169  std::get<N>(par) = std::get<N>(key);
170  par.back() ^= std::get<N>(key);
171  par_xor<N + 1>(key, par, std::integral_constant<bool, N + 1 < K>());
172  }
173 }; // class ThreefryInitPar
174 
175 template <typename T>
176 class ThreefryRotateBits : public std::integral_constant<int, sizeof(T) * 8>
177 {
178 }; // class ThreefryRotateBits
179 
180 template <typename T, template <typename> class SIMD>
181 class ThreefryRotateBits<SIMD<T>> : public ThreefryRotateBits<T>
182 {
183 }; // class ThreefryRotateBits
184 
185 template <typename T, int R>
187 {
188  public:
189  static T eval(const T &x)
190  {
191  return (x << R) | (x >> (ThreefryRotateBits<T>::value - R));
192  }
193 }; // class ThreefryRotateImpl
194 
195 template <typename T, std::size_t K, std::size_t N, bool = (N > 0)>
197 {
198  public:
199  static void eval(std::array<T, K> &) {}
200 }; // class ThreefryRotate
201 
202 template <typename T, std::size_t N>
203 class ThreefryRotate<T, 2, N, true>
204 {
205  public:
206  static void eval(std::array<T, 2> &state)
207  {
208  std::get<0>(state) += std::get<1>(state);
209  std::get<1>(state) =
211  0>::value>::eval(std::get<1>(state));
212  std::get<1>(state) ^= std::get<0>(state);
213  }
214 
215  private:
216  static constexpr std::size_t r_ = (N - 1) % 8;
217 }; // class ThreefryRotate
218 
219 template <typename T, std::size_t N>
220 class ThreefryRotate<T, 4, N, true>
221 {
222  public:
223  static void eval(std::array<T, 4> &state)
224  {
225  std::get<0>(state) += std::get<i0_>(state);
226  std::get<i0_>(state) =
228  0>::value>::eval(std::get<i0_>(state));
229  std::get<i0_>(state) ^= std::get<0>(state);
230 
231  std::get<2>(state) += std::get<i2_>(state);
232  std::get<i2_>(state) =
234  1>::value>::eval(std::get<i2_>(state));
235  std::get<i2_>(state) ^= std::get<2>(state);
236  }
237 
238  private:
239  static constexpr std::size_t i0_ = N % 2 ? 1 : 3;
240  static constexpr std::size_t i2_ = N % 2 ? 3 : 1;
241  static constexpr std::size_t r_ = (N - 1) % 8;
242 }; // class ThreefryRotate
243 
244 template <typename T, std::size_t Inc>
246  : public std::integral_constant<T, static_cast<T>(Inc)>
247 {
248 }; // class ThreefryInsertKeyInc
249 
250 template <typename T, template <typename> class SIMD, std::size_t Inc>
251 class ThreefryInsertKeyInc<SIMD<T>, Inc> : public ThreefryInsertKeyInc<T, Inc>
252 {
253 }; // class ThreefryInsertKeyInc
254 
255 template <typename T, std::size_t K, std::size_t N, bool = (N % 4 == 0)>
257 {
258  public:
259  static void eval(std::array<T, K> &, const std::array<T, K + 1> &) {}
260 }; // class ThreefryInsertKey
261 
262 template <typename T, std::size_t N>
263 class ThreefryInsertKey<T, 2, N, true>
264 {
265  public:
266  static void eval(std::array<T, 2> &state, const std::array<T, 3> &par)
267  {
268  std::get<0>(state) += std::get<i0_>(par);
269  std::get<1>(state) += std::get<i1_>(par);
270  std::get<1>(state) += ThreefryInsertKeyInc<T, inc_>::value;
271  }
272 
273  private:
274  static constexpr std::size_t inc_ = N / 4;
275  static constexpr std::size_t i0_ = (inc_ + 0) % 3;
276  static constexpr std::size_t i1_ = (inc_ + 1) % 3;
277 }; // class ThreefryInsertKey
278 
279 template <typename T, std::size_t N>
280 class ThreefryInsertKey<T, 4, N, true>
281 {
282  public:
283  static void eval(std::array<T, 4> &state, const std::array<T, 5> &par)
284  {
285  std::get<0>(state) += std::get<i0_>(par);
286  std::get<1>(state) += std::get<i1_>(par);
287  std::get<2>(state) += std::get<i2_>(par);
288  std::get<3>(state) += std::get<i3_>(par);
289  std::get<3>(state) += ThreefryInsertKeyInc<T, inc_>::value;
290  }
291 
292  private:
293  static constexpr std::size_t inc_ = N / 4;
294  static constexpr std::size_t i0_ = (inc_ + 0) % 5;
295  static constexpr std::size_t i1_ = (inc_ + 1) % 5;
296  static constexpr std::size_t i2_ = (inc_ + 2) % 5;
297  static constexpr std::size_t i3_ = (inc_ + 3) % 5;
298 }; // class ThreefryInsertKey
299 
300 } // namespace vsmc::internal
301 
304 template <typename ResultType, std::size_t K = VSMC_RNG_THREEFRY_VECTOR_LENGTH,
305  std::size_t Rounds = VSMC_RNG_THREEFRY_ROUNDS>
307 {
308  static_assert(std::is_unsigned<ResultType>::value,
309  "**ThreefryGenerator** USED WITH ResultType OTHER THAN UNSIGNED "
310  "INTEGER TYPES");
311 
312  static_assert(sizeof(ResultType) == sizeof(std::uint32_t) ||
313  sizeof(ResultType) == sizeof(std::uint64_t),
314  "**ThreefryGenerator** USED WITH ResultType OF SIZE OTHER THAN 32 OR "
315  "64 BITS");
316 
317  static_assert(K == 2 || K == 4,
318  "**ThreefryGenerator** USED WITH K OTHER THAN 2 OR 4");
319 
320  public:
321  using result_type = ResultType;
322  using ctr_type = std::array<ResultType, K>;
323  using key_type = std::array<ResultType, K>;
324 
325  static constexpr std::size_t size() { return K; }
326 
327  void reset(const key_type &) {}
328 
329  void operator()(ctr_type &ctr, const key_type &key, ctr_type &buffer) const
330  {
331  std::array<ResultType, K + 1> par;
333  increment(ctr);
334  buffer = ctr;
335  generate<0>(buffer, par, std::true_type());
336  }
337 
338  void operator()(ctr_type &ctr, const key_type &key, std::size_t n,
339  ctr_type *buffer) const
340  {
341  if (n == 0)
342  return;
343 
344  std::array<ResultType, K + 1> par;
346  increment(ctr, n, buffer);
347  for (std::size_t i = 0; i != n; ++i)
348  generate<0>(buffer[i], par, std::true_type());
349  }
350 
351  private:
352  template <std::size_t>
353  void generate(std::array<ResultType, K> &,
354  const std::array<ResultType, K + 1> &, std::false_type) const
355  {
356  }
357 
358  template <std::size_t N>
359  void generate(std::array<ResultType, K> &state,
360  const std::array<ResultType, K + 1> &par, std::true_type) const
361  {
364  generate<N + 1>(
365  state, par, std::integral_constant<bool, (N < Rounds)>());
366  }
367 }; // class ThreefryGenerator
368 
371 template <typename ResultType, std::size_t K = VSMC_RNG_THREEFRY_VECTOR_LENGTH,
372  std::size_t Rounds = VSMC_RNG_THREEFRY_ROUNDS>
374 
378 
382 
386 
390 
394 
398 
399 #if VSMC_HAS_SSE2
400 
401 namespace internal
402 {
403 
404 template <typename ResultType, std::size_t K>
406 {
407  public:
408  static void eval(const std::array<ResultType, K + 1> &p,
409  std::array<M128I<ResultType>, K + 1> &par)
410  {
411  pack<0>(p, par, std::integral_constant<bool, 0 < K + 1>());
412  }
413 
414  private:
415  template <std::size_t>
416  static void pack(const std::array<ResultType, K + 1> &,
417  std::array<M128I<ResultType>, K + 1> &, std::false_type)
418  {
419  }
420 
421  template <std::size_t N>
422  static void pack(const std::array<ResultType, K + 1> &p,
423  std::array<M128I<ResultType>, K + 1> &par, std::true_type)
424  {
425  std::get<N>(par).set1(std::get<N>(p));
426  pack<N + 1>(p, par, std::integral_constant<bool, N + 1 < K + 1>());
427  }
428 }; // class ThreefryParPackSSE2
429 
430 template <typename ResultType, std::size_t K>
432 {
433  public:
434  static void eval(std::array<ResultType, K> &ctr,
435  std::array<M128I<ResultType>, K> &state)
436  {
437  std::array<std::array<ResultType, K>, M128I<ResultType>::size()>
438  ctr_block;
439  increment(ctr, ctr_block);
440  pack<0>(ctr_block, state, std::integral_constant<bool, 0 < K>());
441  }
442 
443  private:
444  template <std::size_t N>
445  static void pack(const std::array<std::array<ResultType, K>,
447  std::array<M128I<ResultType>, K> &, std::false_type)
448  {
449  }
450 
451  template <std::size_t N>
452  static void pack(const std::array<std::array<ResultType, K>,
453  M128I<ResultType>::size()> &ctr_block,
454  std::array<M128I<ResultType>, K> &state, std::true_type)
455  {
456  set<N>(ctr_block, state,
457  std::integral_constant<std::size_t, sizeof(ResultType)>());
458  pack<N + 1>(
459  ctr_block, state, std::integral_constant<bool, N + 1 < K>());
460  }
461 
462  template <std::size_t N>
463  static void set(const std::array<std::array<ResultType, K>,
464  M128I<ResultType>::size()> &ctr_block,
465  std::array<M128I<ResultType>, K> &state,
466  std::integral_constant<std::size_t, 4>)
467  {
468  std::get<N>(state).set(std::get<N>(std::get<0>(ctr_block)),
469  std::get<N>(std::get<1>(ctr_block)),
470  std::get<N>(std::get<2>(ctr_block)),
471  std::get<N>(std::get<3>(ctr_block)));
472  }
473 
474  template <std::size_t N>
475  static void set(const std::array<std::array<ResultType, K>,
476  M128I<ResultType>::size()> &ctr_block,
477  std::array<M128I<ResultType>, K> &state,
478  std::integral_constant<std::size_t, 8>)
479  {
480  std::get<N>(state).set(std::get<N>(std::get<0>(ctr_block)),
481  std::get<N>(std::get<1>(ctr_block)));
482  }
483 }; // class ThreefryCtrPackSSE2
484 
485 } // namespace vsmc::internal
486 
489 template <typename ResultType, std::size_t K = VSMC_RNG_THREEFRY_VECTOR_LENGTH,
490  std::size_t Rounds = VSMC_RNG_THREEFRY_ROUNDS>
492 {
493  static_assert(std::is_unsigned<ResultType>::value,
494  "**ThreefryGeneratorSSE2** USED WITH ResultType OTHER THAN UNSIGNED "
495  "INTEGER TYPES");
496 
497  static_assert(sizeof(ResultType) == sizeof(std::uint32_t) ||
498  sizeof(ResultType) == sizeof(std::uint64_t),
499  "**ThreefryGeneratorSSE2** USED WITH ResultType OF SIZE OTHER THAN "
500  "32 OR 64 BITS");
501 
502  static_assert(K == 2 || K == 4,
503  "**ThreefryGeneratorSSE2** USED WITH K OTHER THAN 2 OR 4");
504 
505  public:
506  using result_type = ResultType;
507  using ctr_type = std::array<ResultType, K>;
508  using key_type = std::array<ResultType, K>;
509 
510  static constexpr std::size_t size()
511  {
512  return K * M128I<ResultType>::size();
513  }
514 
515  void reset(const key_type &) {}
516 
517  void operator()(ctr_type &ctr, const key_type &key,
518  std::array<ResultType, size()> &buffer) const
519  {
520  union {
521  std::array<M128I<ResultType>, K> state;
522  std::array<ResultType, size()> result;
523  } buf;
524 
525  std::array<ResultType, K + 1> p;
526  std::array<M128I<ResultType>, K + 1> par;
530  generate<0>(buf.state, par, std::true_type());
531  buffer = buf.result;
532  }
533 
534  void operator()(ctr_type &ctr, const key_type &key, std::size_t n,
535  std::array<ResultType, size()> *buffer) const
536  {
537  if (n == 0)
538  return;
539 
540  union {
541  std::array<M128I<ResultType>, K> state;
542  std::array<ResultType, size()> result;
543  } buf;
544 
545  std::array<ResultType, K + 1> p;
546  std::array<M128I<ResultType>, K + 1> par;
549  for (std::size_t i = 0; i != n; ++i) {
551  generate<0>(buf.state, par, std::true_type());
552  buffer[i] = buf.result;
553  }
554  }
555 
556  private:
557  template <std::size_t>
558  void generate(std::array<M128I<ResultType>, K> &,
559  const std::array<M128I<ResultType>, K + 1> &, std::false_type) const
560  {
561  }
562 
563  template <std::size_t N>
564  void generate(std::array<M128I<ResultType>, K> &state,
565  const std::array<M128I<ResultType>, K + 1> &par, std::true_type) const
566  {
567  internal::ThreefryRotate<M128I<ResultType>, K, N>::eval(state);
568  internal::ThreefryInsertKey<M128I<ResultType>, K, N>::eval(state, par);
569  generate<N + 1>(
570  state, par, std::integral_constant<bool, (N < Rounds)>());
571  }
572 }; // class ThreefryGeneratorSSE2
573 
576 template <typename ResultType, std::size_t K = VSMC_RNG_THREEFRY_VECTOR_LENGTH,
577  std::size_t Rounds = VSMC_RNG_THREEFRY_ROUNDS>
578 using ThreefryEngineSSE2 =
580 
584 
588 
592 
596 
600 
604 
605 #endif // VSMC_HAS_SSE2
606 
607 #if VSMC_HAS_AVX2
608 
609 namespace internal
610 {
611 
612 template <typename ResultType, std::size_t K>
614 {
615  public:
616  static void eval(const std::array<ResultType, K + 1> &p,
617  std::array<M256I<ResultType>, K + 1> &par)
618  {
619  pack<0>(p, par, std::integral_constant<bool, 0 < K + 1>());
620  }
621 
622  private:
623  template <std::size_t>
624  static void pack(const std::array<ResultType, K + 1> &,
625  std::array<M256I<ResultType>, K + 1> &, std::false_type)
626  {
627  }
628 
629  template <std::size_t N>
630  static void pack(const std::array<ResultType, K + 1> &p,
631  std::array<M256I<ResultType>, K + 1> &par, std::true_type)
632  {
633  std::get<N>(par).set1(std::get<N>(p));
634  pack<N + 1>(p, par, std::integral_constant<bool, N + 1 < K + 1>());
635  }
636 }; // class ThreefryParPackAVX2
637 
638 template <typename ResultType, std::size_t K>
640 {
641  public:
642  static void eval(std::array<ResultType, K> &ctr,
643  std::array<M256I<ResultType>, K> &state)
644  {
645  std::array<std::array<ResultType, K>, M256I<ResultType>::size()>
646  ctr_block;
647  increment(ctr, ctr_block);
648  pack<0>(ctr_block, state, std::integral_constant<bool, 0 < K>());
649  }
650 
651  private:
652  template <std::size_t N>
653  static void pack(const std::array<std::array<ResultType, K>,
655  std::array<M256I<ResultType>, K> &, std::false_type)
656  {
657  }
658 
659  template <std::size_t N>
660  static void pack(const std::array<std::array<ResultType, K>,
661  M256I<ResultType>::size()> &ctr_block,
662  std::array<M256I<ResultType>, K> &state, std::true_type)
663  {
664  set<N>(ctr_block, state,
665  std::integral_constant<std::size_t, sizeof(ResultType)>());
666  pack<N + 1>(
667  ctr_block, state, std::integral_constant<bool, N + 1 < K>());
668  }
669 
670  template <std::size_t N>
671  static void set(const std::array<std::array<ResultType, K>,
672  M256I<ResultType>::size()> &ctr_block,
673  std::array<M256I<ResultType>, K> &state,
674  std::integral_constant<std::size_t, 4>)
675  {
676  std::get<N>(state).set(std::get<N>(std::get<0>(ctr_block)),
677  std::get<N>(std::get<1>(ctr_block)),
678  std::get<N>(std::get<2>(ctr_block)),
679  std::get<N>(std::get<3>(ctr_block)),
680  std::get<N>(std::get<4>(ctr_block)),
681  std::get<N>(std::get<5>(ctr_block)),
682  std::get<N>(std::get<6>(ctr_block)),
683  std::get<N>(std::get<7>(ctr_block)));
684  }
685 
686  template <std::size_t N>
687  static void set(const std::array<std::array<ResultType, K>,
688  M256I<ResultType>::size()> &ctr_block,
689  std::array<M256I<ResultType>, K> &state,
690  std::integral_constant<std::size_t, 8>)
691  {
692  std::get<N>(state).set(std::get<N>(std::get<0>(ctr_block)),
693  std::get<N>(std::get<1>(ctr_block)),
694  std::get<N>(std::get<2>(ctr_block)),
695  std::get<N>(std::get<3>(ctr_block)));
696  }
697 }; // class ThreefryCtrPackAVX2
698 
699 } // namespace vsmc::internal
700 
703 template <typename ResultType, std::size_t K = VSMC_RNG_THREEFRY_VECTOR_LENGTH,
704  std::size_t Rounds = VSMC_RNG_THREEFRY_ROUNDS>
706 {
707  static_assert(std::is_unsigned<ResultType>::value,
708  "**ThreefryGeneratorAVX2** USED WITH ResultType OTHER THAN UNSIGNED "
709  "INTEGER TYPES");
710 
711  static_assert(sizeof(ResultType) == sizeof(std::uint32_t) ||
712  sizeof(ResultType) == sizeof(std::uint64_t),
713  "**ThreefryGeneratorAVX2** USED WITH ResultType OF SIZE OTHER THAN "
714  "32 OR 64 BITS");
715 
716  static_assert(K == 2 || K == 4,
717  "**ThreefryGeneratorAVX2** USED WITH K OTHER THAN 2 OR 4");
718 
719  public:
720  using result_type = ResultType;
721  using ctr_type = std::array<ResultType, K>;
722  using key_type = std::array<ResultType, K>;
723 
724  static constexpr std::size_t size()
725  {
726  return K * M256I<ResultType>::size();
727  }
728 
729  void reset(const key_type &) {}
730 
731  void operator()(ctr_type &ctr, const key_type &key,
732  std::array<ResultType, size()> &buffer) const
733  {
734  union {
735  std::array<M256I<ResultType>, K> state;
736  std::array<ResultType, size()> result;
737  } buf;
738 
739  std::array<ResultType, K + 1> p;
740  std::array<M256I<ResultType>, K + 1> par;
744  generate<0>(buf.state, par, std::true_type());
745  buffer = buf.result;
746  }
747 
748  void operator()(ctr_type &ctr, const key_type &key, std::size_t n,
749  std::array<ResultType, size()> *buffer) const
750  {
751  if (n == 0)
752  return;
753 
754  union {
755  std::array<M256I<ResultType>, K> state;
756  std::array<ResultType, size()> result;
757  } buf;
758 
759  std::array<ResultType, K + 1> p;
760  std::array<M256I<ResultType>, K + 1> par;
763  for (std::size_t i = 0; i != n; ++i) {
765  generate<0>(buf.state, par, std::true_type());
766  buffer[i] = buf.result;
767  }
768  }
769 
770  private:
771  template <std::size_t>
772  void generate(std::array<M256I<ResultType>, K> &,
773  const std::array<M256I<ResultType>, K + 1> &, std::false_type) const
774  {
775  }
776 
777  template <std::size_t N>
778  void generate(std::array<M256I<ResultType>, K> &state,
779  const std::array<M256I<ResultType>, K + 1> &par, std::true_type) const
780  {
781  internal::ThreefryRotate<M256I<ResultType>, K, N>::eval(state);
782  internal::ThreefryInsertKey<M256I<ResultType>, K, N>::eval(state, par);
783  generate<N + 1>(
784  state, par, std::integral_constant<bool, (N < Rounds)>());
785  }
786 }; // class ThreefryGeneratorAVX2
787 
790 template <typename ResultType, std::size_t K = VSMC_RNG_THREEFRY_VECTOR_LENGTH,
791  std::size_t Rounds = VSMC_RNG_THREEFRY_ROUNDS>
792 using ThreefryEngineAVX2 =
794 
798 
802 
806 
810 
814 
818 
819 #endif // VSMC_HAS_AVX2
820 
821 } // namespace vsmc
822 
823 #endif // VSMC_RNG_THREEFRY_HPP
static void eval(std::array< T, K > &, const std::array< T, K+1 > &)
Definition: threefry.hpp:259
std::array< ResultType, K > key_type
Definition: threefry.hpp:323
void operator()(ctr_type &ctr, const key_type &key, std::array< ResultType, size()> &buffer) const
Definition: threefry.hpp:731
Definition: monitor.hpp:49
void operator()(ctr_type &ctr, const key_type &key, std::size_t n, ctr_type *buffer) const
Definition: threefry.hpp:338
#define VSMC_RNG_THREEFRY_ROUNDS
ThreefryGenerator default rounds.
Definition: threefry.hpp:48
Using __mm256i as integer vector.
Definition: simd.hpp:804
std::array< ResultType, K > ctr_type
Definition: threefry.hpp:322
static constexpr std::size_t size()
Definition: threefry.hpp:724
uint uint32_t
Definition: opencl.h:39
void increment(std::array< T, K > &ctr)
Increment a counter by one.
Definition: counter.hpp:62
Using __m128i as integer vector.
Definition: simd.hpp:113
static constexpr std::size_t size()
Definition: simd.hpp:826
ulong uint64_t
Definition: opencl.h:40
STL namespace.
Counter based RNG engine.
Definition: counter.hpp:289
static void eval(std::array< ResultType, K > &ctr, std::array< M128I< ResultType >, K > &state)
Definition: threefry.hpp:434
Threefry RNG generator using AVX2.
Definition: threefry.hpp:705
static void eval(const std::array< T, K > &key, std::array< T, K+1 > &par)
Definition: threefry.hpp:152
static constexpr std::size_t size()
Definition: threefry.hpp:325
std::array< ResultType, K > ctr_type
Definition: threefry.hpp:507
Threefry RNG generator.
Definition: threefry.hpp:306
static constexpr std::size_t size()
Definition: threefry.hpp:510
#define VSMC_RNG_THREEFRY_VECTOR_LENGTH
ThreefryGenerator default vector length.
Definition: threefry.hpp:54
std::array< ResultType, K > key_type
Definition: threefry.hpp:722
static void eval(std::array< T, K > &)
Definition: threefry.hpp:199
void operator()(ctr_type &ctr, const key_type &key, std::size_t n, std::array< ResultType, size()> *buffer) const
Definition: threefry.hpp:748
std::array< ResultType, K > ctr_type
Definition: threefry.hpp:721
void reset(const key_type &)
Definition: threefry.hpp:729
void operator()(ctr_type &ctr, const key_type &key, std::size_t n, std::array< ResultType, size()> *buffer) const
Definition: threefry.hpp:534
static constexpr std::size_t size()
Definition: simd.hpp:135
void operator()(ctr_type &ctr, const key_type &key, std::array< ResultType, size()> &buffer) const
Definition: threefry.hpp:517
static void eval(std::array< T, 4 > &state)
Definition: threefry.hpp:223
static void eval(std::array< ResultType, K > &ctr, std::array< M256I< ResultType >, K > &state)
Definition: threefry.hpp:642
void reset(const key_type &)
Definition: threefry.hpp:327
static void eval(const std::array< ResultType, K+1 > &p, std::array< M128I< ResultType >, K+1 > &par)
Definition: threefry.hpp:408
static void eval(std::array< T, 2 > &state, const std::array< T, 3 > &par)
Definition: threefry.hpp:266
std::array< ResultType, K > key_type
Definition: threefry.hpp:508
void reset(const key_type &)
Definition: threefry.hpp:515
static void eval(std::array< T, 2 > &state)
Definition: threefry.hpp:206
void operator()(ctr_type &ctr, const key_type &key, ctr_type &buffer) const
Definition: threefry.hpp:329
Threefry RNG generator using SSE2.
Definition: threefry.hpp:491
#define VSMC_DEFINE_RNG_THREEFRY_ROTATE_CONSTANT(T, K, N, I, val)
Definition: threefry.hpp:38
static void eval(std::array< T, 4 > &state, const std::array< T, 5 > &par)
Definition: threefry.hpp:283
static void eval(const std::array< ResultType, K+1 > &p, std::array< M256I< ResultType >, K+1 > &par)
Definition: threefry.hpp:616