MCKL
Monte Carlo Kernel Library
seed.hpp
Go to the documentation of this file.
1 //============================================================================
2 // MCKL/include/mckl/random/seed.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_SEED_HPP
33 #define MCKL_RANDOM_SEED_HPP
34 
36 #include <mckl/random/skein.hpp>
37 #include <mckl/random/threefry.hpp>
38 #include <atomic>
39 
42 #ifndef MCKL_SEED_RANDOMIZE
43 #define MCKL_SEED_RANDOMIZE 1
44 #endif
45 
48 #ifndef MCKL_SEED_ATOMIC
49 #define MCKL_SEED_ATOMIC 1
50 #endif
51 
52 namespace mckl {
53 
56 template <typename ResultType,
57  typename ID = std::integral_constant<std::size_t, sizeof(ResultType)>,
58 #if MCKL_SEED_RANDOMIZE
59  bool Randomize = true,
60 #else
61  bool Randomize = false,
62 #endif
63 #if MCKL_SEED_ATOMIC
64  bool Atomic = true
65 #else
66  bool Atomic = false
67 #endif
68  >
70 {
71  static_assert(sizeof(ResultType) % sizeof(std::uint32_t) == 0,
72  "**SeedGenerator** size of ResultType is not a multiple of uint32_t");
73 
74  public:
76  using seed_type =
77  std::conditional_t<sizeof(ResultType) % sizeof(std::uint64_t) == 0,
79 
80  using result_type = ResultType;
81 
84 
87 
89  {
91 
92  return seed;
93  }
94 
96  void set(seed_type s) { seed_ = s; }
97 
99  result_type get() { return get(std::integral_constant<bool, (M_ > 1)>()); }
100 
102  seed_type np() const { return np_; }
103 
105  seed_type rank() const { return rank_; }
106 
109  {
110  partition(np, rank, std::integral_constant<bool, (M_ > 1)>());
111  }
112 
113  template <typename CharT, typename Traits>
114  friend std::basic_ostream<CharT, Traits> &operator<<(
115  std::basic_ostream<CharT, Traits> &os,
117  {
118  if (!os) {
119  return os;
120  }
121 
122  os << sg.np_ << ' ';
123  os << sg.rank_ << ' ';
124  os << sg.maxs_ << ' ';
125  os << sg.seed_ << ' ';
126 
127  return os;
128  }
129 
130  template <typename CharT, typename Traits>
131  friend std::basic_istream<CharT, Traits> &operator>>(
132  std::basic_istream<CharT, Traits> &is,
134  {
135  if (!is) {
136  return is;
137  }
138 
139  seed_type np;
140  seed_type rank;
141  seed_type maxs;
142  seed_type seed;
143  is >> std::ws >> np;
144  is >> std::ws >> rank;
145  is >> std::ws >> maxs;
146  is >> std::ws >> seed;
147 
148  if (is) {
149  sg.np_ = np;
150  sg.rank_ = rank;
151  sg.maxs_ = maxs;
152  sg.seed_ = seed;
153  }
154 
155  return is;
156  }
157 
158  private:
159  static constexpr std::size_t M_ = sizeof(result_type) / sizeof(seed_type);
160 
161  seed_type np_;
162  seed_type rank_;
163  seed_type maxs_;
164  std::conditional_t<Atomic, std::atomic<seed_type>, seed_type> seed_;
165 
166  SeedGenerator() : seed_(1) { partition(1, 0); }
167 
168  void partition(seed_type np, seed_type rank, std::true_type)
169  {
170  np_ = np;
171  rank_ = rank;
172  maxs_ = std::numeric_limits<seed_type>::max();
173  }
174 
175  void partition(seed_type np, seed_type rank, std::false_type)
176  {
177  runtime_assert(np > 0,
178  "**SeedGenerator::partition** the number of the partitions is "
179  "zero");
180  if (np < 1) {
181  np = 1;
182  }
183 
184  runtime_assert(np > rank,
185  "**SeedGenerator::partition** the rank is not smaller than the "
186  "number of partitions");
187  if (rank >= np) {
188  rank = 0;
189  }
190 
191  seed_type maxs = std::numeric_limits<seed_type>::max();
192  if (np > 1) {
193  maxs = (maxs - rank) / np + 1;
194  }
195 
196  np_ = np;
197  rank_ = rank;
198  maxs_ = maxs;
199  }
200 
201  result_type get(std::true_type)
202  {
203  seed_type s = seed_++;
204  std::array<seed_type, M_> k = {{0}};
205  k.front() = s;
206  k.back() = rank_;
207 
208  return randomize(k, std::integral_constant<bool, Randomize>());
209  }
210 
211  result_type get(std::false_type)
212  {
213  seed_type s = seed_++;
214  s %= maxs_;
215  s *= np_;
216  s += rank_;
217  std::array<seed_type, M_> k = {{s}};
218 
219  return randomize(k, std::integral_constant<bool, Randomize>());
220  }
221 
222  result_type randomize(const std::array<seed_type, M_> &k, std::false_type)
223  {
224  union {
225  std::array<seed_type, M_> k;
226  result_type result;
227  } buf;
228 
229  buf.k = k;
230  internal::union_le<seed_type>(buf.result);
231 
232  return buf.result;
233  }
234 
235  result_type randomize(const std::array<seed_type, M_> &k, std::true_type)
236  {
237  return randomize(k,
238  std::integral_constant<int,
239  std::numeric_limits<seed_type>::digits * M_>());
240  }
241 
242  template <int D>
243  result_type randomize(
244  const std::array<seed_type, M_> &k, std::integral_constant<int, D>)
245  {
246  union {
247  std::array<char, sizeof(seed_type) * M_> state;
248  std::array<seed_type, M_> k;
249  result_type result;
250  } buf;
251 
252  buf.k = k;
253  internal::union_le<seed_type>(buf.state);
255  Skein512::param_type(D, buf.state.data()), D, buf.state.data());
256  internal::union_le<char>(buf.result);
257 
258  return buf.result;
259  }
260 
261  result_type randomize(
262  const std::array<seed_type, M_> &k, std::integral_constant<int, 32>)
263  {
264  union {
265  std::array<std::uint16_t, 2> state;
266  std::array<seed_type, M_> k;
267  result_type result;
268  } buf;
269 
270  buf.k = k;
271  internal::union_le<seed_type>(buf.state);
272  std::uint16_t x = std::get<0>(buf.state);
273  std::uint16_t y = std::get<1>(buf.state);
274  for (int i = 0; i != 22; ++i) {
275  x = static_cast<std::uint16_t>((x << 9) | (x >> 7));
276  x += y;
277  y = static_cast<std::uint16_t>((y << 2) | (y >> 14));
278  y ^= x;
279  }
280  std::get<0>(buf.state) = x;
281  std::get<1>(buf.state) = y;
282  internal::union_le<std::uint16_t>(buf.result);
283 
284  return buf.result;
285  }
286 
287  result_type randomize(
288  const std::array<seed_type, M_> &k, std::integral_constant<int, 64>)
289  {
290  return randomize<Threefry2x32>(k);
291  }
292 
293  result_type randomize(
294  const std::array<seed_type, M_> &k, std::integral_constant<int, 128>)
295  {
296  return randomize<Threefry2x64>(k);
297  }
298 
299  result_type randomize(
300  const std::array<seed_type, M_> &k, std::integral_constant<int, 256>)
301  {
302  return randomize<Threefry4x64>(k);
303  }
304 
305  result_type randomize(
306  const std::array<seed_type, M_> &k, std::integral_constant<int, 512>)
307  {
308  return randomize<Threefry8x64>(k);
309  }
310 
311  result_type randomize(
312  const std::array<seed_type, M_> &k, std::integral_constant<int, 1024>)
313  {
314  return randomize<Threefry16x64>(k);
315  }
316 
317  template <typename RNGType>
318  result_type randomize(const std::array<seed_type, M_> &k)
319  {
320  union {
321  std::array<char, sizeof(seed_type) * M_> state;
322  std::array<seed_type, M_> k;
323  result_type result;
324  } buf;
325 
326  buf.k = k;
327  internal::union_le<seed_type>(buf.state);
328  RNGType rng(0);
329  rng.generator()(buf.state.data(), buf.state.data());
330  internal::union_le<char>(buf.result);
331 
332  return buf.result;
333  }
334 }; // class Seed
335 
338 template <typename RNGType>
339 class Seed : public SeedGenerator<SeedType<RNGType>>
340 {
341 }; // class Seed
342 
343 } // namespace mckl
344 
345 #endif // MCKL_RANDOM_SEED_HPP
void partition(seed_type np, seed_type rank)
Set the number of partitions and the rank of this partition.
Definition: seed.hpp:108
SeedGenerator< ResultType, ID, Randomize, Atomic > & operator=(const SeedGenerator< ResultType, ID, Randomize, Atomic > &)=delete
friend std::basic_istream< CharT, Traits > & operator>>(std::basic_istream< CharT, Traits > &is, SeedGenerator< ResultType, ID, Randomize, Atomic > &sg)
Definition: seed.hpp:131
seed_type np() const
The number of partitions.
Definition: seed.hpp:102
const char * data() const
The address of the string.
Definition: skein.hpp:108
static SeedGenerator< ResultType, ID, Randomize, Atomic > & instance()
Definition: seed.hpp:88
uint uint32_t
Definition: opencl.h:41
ulong uint64_t
Definition: opencl.h:42
seed_type rank() const
The rank of this partition.
Definition: seed.hpp:105
static void hash(const param_type &M, std::size_t N, void *H)
Simple hashing.
Definition: skein.hpp:269
std::conditional_t< sizeof(ResultType) % sizeof(std::uint64_t)==0, std::uint64_t, std::uint32_t > seed_type
The type of the internal seed.
Definition: seed.hpp:78
Seed generator.
Definition: seed.hpp:69
Definition: mcmc.hpp:40
Type of input paramters such as keys and messages.
Definition: skein.hpp:84
RNG default seed generator.
Definition: seed.hpp:339
void runtime_assert(bool cond, const char *msg, bool soft=false)
Definition: assert.hpp:65
friend std::basic_ostream< CharT, Traits > & operator<<(std::basic_ostream< CharT, Traits > &os, const SeedGenerator< ResultType, ID, Randomize, Atomic > &sg)
Definition: seed.hpp:114