MCKL
Monte Carlo Kernel Library
threefry_generic_4x32.hpp
Go to the documentation of this file.
1 //============================================================================
2 // MCKL/include/mckl/random/internal/threefry_generic_4x32.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_GENERIC_4X32_HPP
33 #define MCKL_RANDOM_INTERNAL_THREEFRY_GENERIC_4X32_HPP
34 
39 
40 #define MCKL_RANDOM_INTERNAL_THREEFRY_GENERIC_4X32_KBOX(N) \
41  s0 += ThreefryKBox<T, K, N>::template key<0>(par); \
42  s1 += ThreefryKBox<T, K, N>::template key<1>(par); \
43  s2 += ThreefryKBox<T, K, N>::template key<2>(par); \
44  s3 += ThreefryKBox<T, K, N>::template key<3>(par);
45 
46 #define MCKL_RANDOM_INTERNAL_THREEFRY_GENERIC_4X32_RBOX(N) \
47  { \
48  constexpr int L0 = Constants::rotate::value[0][(N - 1) % 8]; \
49  constexpr int L1 = Constants::rotate::value[1][(N - 1) % 8]; \
50  constexpr int R0 = 32 - L0; \
51  constexpr int R1 = 32 - L1; \
52  s0 += s1; \
53  s2 += s3; \
54  t1 = (s1 << L0) | (s1 >> R0); \
55  t3 = (s3 << L1) | (s3 >> R1); \
56  s1 = s2 ^ t3; \
57  s3 = s0 ^ t1; \
58  }
59 
60 #define MCKL_RANDOM_INTERNAL_THREEFRY_GENERIC_4X32_CYCLE_4(N) \
61  MCKL_RANDOM_INTERNAL_THREEFRY_GENERIC_4X32_RBOX(N * 8 + 1); \
62  MCKL_RANDOM_INTERNAL_THREEFRY_GENERIC_4X32_RBOX(N * 8 + 2); \
63  MCKL_RANDOM_INTERNAL_THREEFRY_GENERIC_4X32_RBOX(N * 8 + 3); \
64  MCKL_RANDOM_INTERNAL_THREEFRY_GENERIC_4X32_RBOX(N * 8 + 4); \
65  MCKL_RANDOM_INTERNAL_THREEFRY_GENERIC_4X32_KBOX(N * 8 + 4);
66 
67 #define MCKL_RANDOM_INTERNAL_THREEFRY_GENERIC_4X32_CYCLE_8(N) \
68  MCKL_RANDOM_INTERNAL_THREEFRY_GENERIC_4X32_RBOX(N * 8 + 1); \
69  MCKL_RANDOM_INTERNAL_THREEFRY_GENERIC_4X32_RBOX(N * 8 + 2); \
70  MCKL_RANDOM_INTERNAL_THREEFRY_GENERIC_4X32_RBOX(N * 8 + 3); \
71  MCKL_RANDOM_INTERNAL_THREEFRY_GENERIC_4X32_RBOX(N * 8 + 4); \
72  MCKL_RANDOM_INTERNAL_THREEFRY_GENERIC_4X32_KBOX(N * 8 + 4); \
73  MCKL_RANDOM_INTERNAL_THREEFRY_GENERIC_4X32_RBOX(N * 8 + 5); \
74  MCKL_RANDOM_INTERNAL_THREEFRY_GENERIC_4X32_RBOX(N * 8 + 6); \
75  MCKL_RANDOM_INTERNAL_THREEFRY_GENERIC_4X32_RBOX(N * 8 + 7); \
76  MCKL_RANDOM_INTERNAL_THREEFRY_GENERIC_4X32_RBOX(N * 8 + 8); \
77  MCKL_RANDOM_INTERNAL_THREEFRY_GENERIC_4X32_KBOX(N * 8 + 8);
78 
79 #define MCKL_RANDOM_INTERNAL_THREEFRY_GENERIC_4X32_ROUND_20 \
80  T s0 = std::get<0>(buf.s); \
81  T s1 = std::get<1>(buf.s); \
82  T s2 = std::get<2>(buf.s); \
83  T s3 = std::get<3>(buf.s); \
84  T t1; \
85  T t3; \
86  MCKL_RANDOM_INTERNAL_THREEFRY_GENERIC_4X32_KBOX(0) \
87  MCKL_RANDOM_INTERNAL_THREEFRY_GENERIC_4X32_CYCLE_8(0) \
88  MCKL_RANDOM_INTERNAL_THREEFRY_GENERIC_4X32_CYCLE_8(1) \
89  MCKL_RANDOM_INTERNAL_THREEFRY_GENERIC_4X32_CYCLE_4(2) \
90  std::get<0>(buf.s) = s0; \
91  std::get<1>(buf.s) = s1; \
92  std::get<2>(buf.s) = s2; \
93  std::get<3>(buf.s) = s3;
94 
95 namespace mckl {
96 
97 namespace internal {
98 
99 template <typename T>
101 {
102  static_assert(std::numeric_limits<T>::digits == 32,
103  "**Threefry4x32GeneratorGenericImpl** used with T other than a "
104  "32-bit unsigned integers");
105 
106  static constexpr std::size_t K = 4;
107  static constexpr std::size_t Rounds = 20;
109 
110  public:
111  static void eval(
112  const void *plain, void *cipher, const std::array<T, K + 4> &par)
113  {
114  alignas(MCKL_ALIGNMENT) union {
115  std::array<T, K> s;
116  std::array<char, sizeof(T) * K> r;
117  } buf;
118 
119  std::memcpy(buf.s.data(), plain, sizeof(T) * K);
120  union_le<char>(buf.s);
122  union_le<T>(buf.r);
123  std::memcpy(cipher, buf.s.data(), sizeof(T) * K);
124  }
125 
126  template <typename ResultType>
127  static void eval(
128  Counter<T, K> &ctr, ResultType *r, const std::array<T, K + 4> &par)
129  {
130  alignas(MCKL_ALIGNMENT) union {
131  std::array<T, K> s;
132  Counter<T, K> c;
133  std::array<ResultType, sizeof(T) * K / sizeof(ResultType)> r;
134  } buf;
135 
137  buf.c = ctr;
138 #if MCKL_REQUIRE_ENDIANNESS_NEUTURAL
139  union_le<typename Counter<T, K>::value_type>(buf.s);
140 #endif
142 #if MCKL_REQUIRE_ENDIANNESS_NEUTURAL
143  union_le<T>(buf.r);
144 #endif
145  std::memcpy(r, buf.r.data(), sizeof(T) * K);
146  }
147 
148  template <typename ResultType>
149  static void eval(Counter<T, K> &ctr, std::size_t n, ResultType *r,
150  const std::array<T, K + 4> &par)
151  {
152  constexpr std::size_t R = sizeof(T) * K / sizeof(ResultType);
153 
154  for (std::size_t i = 0; i != n; ++i, r += R) {
155  eval(ctr, r, par);
156  }
157  }
158 }; // class Threefry4x32GeneratorGenericImpl
159 
160 } // namespace internal
161 
162 } // namespace mckl
163 
164 #endif // MCKL_RANDOM_INTERNAL_THREEFRY_GENERIC_4X32_HPP
static void eval(Counter< T, K > &ctr, std::size_t n, ResultType *r, const std::array< T, K+4 > &par)
#define MCKL_INLINE_CALL
Definition: intel.h:142
static void eval(Counter< T, K > &ctr, ResultType *r, const std::array< T, K+4 > &par)
static void eval(const void *plain, void *cipher, const std::array< T, K+4 > &par)
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
#define MCKL_RANDOM_INTERNAL_THREEFRY_GENERIC_4X32_ROUND_20
Default Threefry constants.
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