vSMC
vSMC: Scalable Monte Carlo
seed.hpp
Go to the documentation of this file.
1 //============================================================================
2 // vSMC/include/vsmc/rng/seed.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_SEED_HPP
33 #define VSMC_RNG_SEED_HPP
34 
36 #include <vsmc/rng/counter.hpp>
37 
38 #define VSMC_RUNTIME_ASSERT_RNG_SEED_GENERATOR_MODULO(div, rem) \
39  VSMC_RUNTIME_ASSERT((div > rem), \
40  "**SeedGenerator::modulo** " \
41  "REMAINDER IS NOT SMALLER THAN THE DIVISOR")
42 
43 #define VSMC_RUNTIME_WARNING_RNG_SEED_GENERATOR_MODULO(div, rem) \
44  VSMC_RUNTIME_WARNING((div == 1 && rem == 0), \
45  "**SeedGenerator::modulo** " \
46  "COUNTER TYPE SEED DOES NOT SUPPORT MODULO")
47 
48 #define VSMC_RUNTIME_ASSERT_RNG_SEED_MAX(seed_max) \
49  VSMC_RUNTIME_ASSERT((seed_max > 1), \
50  "**SeedGenerator::modulo** " \
51  "THE MAXIMUM OF THE INTERNAL SEED IS NO LARGER THAN 1")
52 
55 #ifndef VSMC_SEED_RESULT_TYPE
56 #define VSMC_SEED_RESULT_TYPE unsigned
57 #endif
58 
59 namespace vsmc
60 {
61 
84 template <typename ID, typename ResultType = VSMC_SEED_RESULT_TYPE>
86 {
87  static_assert(std::is_unsigned<ResultType>::value,
88  "**SeedGenerator** USED WITH ResultType OTHER THAN UNSIGEND INTEGER "
89  "TYPES");
90 
91  public:
92  using result_type = ResultType;
93  using skip_type = ResultType;
94 
96 
98  const SeedGenerator<ID, ResultType> &) = delete;
99 
101  {
103 
104  return seed;
105  }
106 
108  template <typename RNGType>
109  void seed_rng(RNGType &rng)
110  {
111  rng.seed(get());
112  }
113 
119  {
120  skip();
121 
122  return seed_ * divisor_ + remainder_;
123  }
124 
125  result_type get_scalar() { return get(); }
126 
133  void set(result_type seed) { seed_ = seed % seed_max_; }
134 
136  result_type seed() const { return seed_; }
137 
139  result_type seed_max() const { return seed_max_; }
140 
142  skip_type divisor() const { return divisor_; }
143 
145  skip_type remainder() const { return remainder_; }
146 
149  {
151 
152  divisor_ = div;
153  remainder_ = rem;
154  seed_max_ = std::numeric_limits<skip_type>::max();
155  seed_max_ -= seed_max_ % divisor_;
156  seed_max_ /= divisor_;
157 
159 
160  set(seed_);
161  }
162 
164  void skip(skip_type steps)
165  {
166  result_type incr = steps % seed_max_;
167  result_type diff = seed_max_ - seed_;
168  seed_ = incr <= diff ? (seed_ + incr) : (incr - diff);
169  }
170 
172  void skip()
173  {
174  if (seed_ < seed_max_)
175  ++seed_;
176  else
177  seed_ = 1;
178  }
179 
180  template <typename CharT, typename Traits>
181  friend std::basic_ostream<CharT, Traits> &operator<<(
182  std::basic_ostream<CharT, Traits> &os,
184  {
185  if (!os.good())
186  return os;
187 
188  os << sg.seed_ << ' ';
189  os << sg.divisor_ << ' ';
190  os << sg.remainder_;
191 
192  return os;
193  }
194 
195  template <typename CharT, typename Traits>
196  friend std::basic_istream<CharT, Traits> &operator>>(
197  std::basic_istream<CharT, Traits> &is,
199  {
200  if (!is.good())
201  return is;
202 
203  result_type s;
204  skip_type div;
205  skip_type rem;
206  is >> std::ws >> s;
207  is >> std::ws >> div;
208  is >> std::ws >> rem;
209 
210  if (is.good()) {
211  sg.modulo(div, rem);
212  sg.set(s);
213  }
214 
215  return is;
216  }
217 
218  private:
219  std::atomic<result_type> seed_;
220  result_type seed_max_;
221  skip_type divisor_;
222  skip_type remainder_;
223 
224  SeedGenerator() : seed_(0), seed_max_(0), divisor_(1), remainder_(0)
225  {
226  modulo(divisor_, remainder_);
227  }
228 }; // class SeedGenerator
229 
250 template <typename ID, typename ResultType, std::size_t K>
251 class SeedGenerator<ID, std::array<ResultType, K>>
252 {
253  static_assert(std::is_unsigned<ResultType>::value,
254  "**SeedGenerator** USED WITH ResultType OTHER THAN UNSIGEND INTEGER "
255  "TYPES");
256 
257  public:
258  using result_type = std::array<ResultType, K>;
259  using skip_type = ResultType;
260 
262  const SeedGenerator<ID, std::array<ResultType, K>> &) = delete;
263 
265  const SeedGenerator<ID, std::array<ResultType, K>> &) = delete;
266 
268  {
270 
271  return seed;
272  }
273 
280  template <typename RNGType>
281  void seed_rng(RNGType &rng)
282  {
283  seed_rng_dispatch(rng,
284  std::integral_constant<bool,
285  std::is_same<result_type,
286  internal::KeyType<RNGType>>::value>());
287  }
288 
290  {
291  std::lock_guard<std::mutex> lock_(mtx_);
292  skip();
293 
294  return seed_;
295  }
296 
297  ResultType get_scalar()
298  {
299  result_type s1(get());
300  result_type s2(get());
301  for (std::size_t k = 0; k != K; ++k)
302  if (s1[k] != s2[k])
303  return s2[k];
304 
305  return std::get<0>(s2);
306  }
307 
308  void set(ResultType s)
309  {
310  seed_.fill(0);
311  seed_.front() = s;
312  }
313 
314  void set(result_type seed) { seed_ = seed; }
315 
316  result_type seed() const { return seed_; }
317 
318  result_type seed_max() const { return seed_max_; }
319 
320  skip_type divisor() const { return divisor_; }
321 
322  skip_type remainder() const { return remainder_; }
323 
325  {
327 
328  divisor_ = div;
329  remainder_ = rem;
330  seed_max_.fill(std::numeric_limits<skip_type>::max());
331 
332  set(seed_);
333  }
334 
335  void skip(skip_type steps) { increment(seed_, steps); }
336 
337  void skip() { increment(seed_); }
338 
339  template <typename CharT, typename Traits>
340  friend std::basic_ostream<CharT, Traits> &operator<<(
341  std::basic_ostream<CharT, Traits> &os,
342  const SeedGenerator<ID, std::array<ResultType, K>> &sg)
343  {
344  if (!os.good())
345  return os;
346 
347  os << sg.seed_ << ' ';
348  os << sg.divisor_ << ' ';
349  os << sg.remainder_ << ' ';
350 
351  return os;
352  }
353 
354  template <typename CharT, typename Traits>
355  friend std::basic_istream<CharT, Traits> &operator>>(
356  std::basic_istream<CharT, Traits> &is,
357  SeedGenerator<ID, std::array<ResultType, K>> &sg)
358  {
359  if (!is.good())
360  return is;
361 
362  result_type s;
363  skip_type div;
364  skip_type rem;
365  is >> std::ws >> s;
366  is >> std::ws >> div;
367  is >> std::ws >> rem;
368 
369  if (is.good()) {
370  sg.modulo(div, rem);
371  sg.set(s);
372  }
373 
374  return is;
375  }
376 
377  private:
378  result_type seed_;
379  result_type seed_max_;
380  skip_type divisor_;
381  skip_type remainder_;
382  std::mutex mtx_;
383 
384  SeedGenerator() : divisor_(1), remainder_(0)
385  {
386  seed_.fill(0);
387  seed_max_.fill(0);
388  modulo(divisor_, remainder_);
389  }
390 
391  template <typename RNGType>
392  void seed_rng_dispatch(RNGType &rng, std::true_type)
393  {
394  rng.seed(get());
395  }
396 
397  template <typename RNGType>
398  void seed_rng_dispatch(RNGType &rng, std::false_type)
399  {
400  rng.seed(get_scalar());
401  }
402 }; // class SeedGenerator
403 
407 
408 } // namespace vsmc
409 
410 #endif // VSMC_RNG_SEED_HPP
static SeedGenerator< ID, ResultType > & instance()
Definition: seed.hpp:100
Definition: monitor.hpp:49
result_type get_scalar()
Definition: seed.hpp:125
ResultType result_type
Definition: seed.hpp:92
void skip(skip_type steps)
Skip the internal seed by a given steps.
Definition: seed.hpp:164
void increment(std::array< T, K > &ctr)
Increment a counter by one.
Definition: counter.hpp:62
STL namespace.
friend std::basic_istream< CharT, Traits > & operator>>(std::basic_istream< CharT, Traits > &is, SeedGenerator< ID, ResultType > &sg)
Definition: seed.hpp:196
void set(result_type seed)
Set the internal seed.
Definition: seed.hpp:133
void seed_rng(RNGType &rng)
Equivalent to rng.seed(get())
Definition: seed.hpp:109
result_type seed_max() const
The maximum of the internal seed integer.
Definition: seed.hpp:139
static SeedGenerator< ID, std::array< ResultType, K > > & instance()
Definition: seed.hpp:267
SeedGenerator< ID, ResultType > & operator=(const SeedGenerator< ID, ResultType > &)=delete
typename KeyTypeTrait< T >::type KeyType
Definition: common.hpp:430
skip_type divisor() const
The divisor of the output seed.
Definition: seed.hpp:142
friend std::basic_ostream< CharT, Traits > & operator<<(std::basic_ostream< CharT, Traits > &os, const SeedGenerator< ID, std::array< ResultType, K >> &sg)
Definition: seed.hpp:340
skip_type remainder() const
The remainder of the output seed.
Definition: seed.hpp:145
#define VSMC_RUNTIME_WARNING_RNG_SEED_GENERATOR_MODULO(div, rem)
Definition: seed.hpp:43
void modulo(skip_type div, skip_type rem)
Definition: seed.hpp:324
#define VSMC_RUNTIME_ASSERT_RNG_SEED_GENERATOR_MODULO(div, rem)
Definition: seed.hpp:38
friend std::basic_istream< CharT, Traits > & operator>>(std::basic_istream< CharT, Traits > &is, SeedGenerator< ID, std::array< ResultType, K >> &sg)
Definition: seed.hpp:355
Seed generator.
Definition: seed.hpp:85
void div(std::size_t n, const float *a, const float *b, float *y)
Definition: vmath.hpp:128
friend std::basic_ostream< CharT, Traits > & operator<<(std::basic_ostream< CharT, Traits > &os, const SeedGenerator< ID, ResultType > &sg)
Definition: seed.hpp:181
ResultType skip_type
Definition: seed.hpp:93
result_type seed() const
The current internal seed.
Definition: seed.hpp:136
void modulo(skip_type div, skip_type rem)
Set the divisor and the remainder.
Definition: seed.hpp:148
#define VSMC_RUNTIME_ASSERT_RNG_SEED_MAX(seed_max)
Definition: seed.hpp:48
void seed_rng(RNGType &rng)
Equivalent to rng.seed(get()) or rng.seed(std::get<0>(get())).
Definition: seed.hpp:281
void skip()
Skip the internal seed by 1 step.
Definition: seed.hpp:172