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-2015, 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_STATIC_ASSERT_RNG_SEED_GENERATOR_RESULT_TYPE(T) \
39  VSMC_STATIC_ASSERT((std::is_unsigned<T>::value), \
40  "**SeedGenerator** USED WITH ResultType NOT AN UNSIGNED INTEGER")
41 
42 #define VSMC_RUNTIME_ASSERT_RNG_SEED_GENERATOR_MODULO(div, rem) \
43  VSMC_RUNTIME_ASSERT((div > rem), \
44  "**SeedGenerator::modulo** " \
45  "REMAINDER IS NOT SMALLER THAN THE DIVISOR")
46 
47 #define VSMC_RUNTIME_WARNING_RNG_SEED_GENERATOR_MODULO(div, rem) \
48  VSMC_RUNTIME_WARNING((div == 1 && rem == 0), \
49  "**SeedGenerator::modulo** " \
50  "COUNTER TYPE SEED DOES NOT SUPPORT MODULO")
51 
52 #define VSMC_RUNTIME_ASSERT_RNG_SEED_MAX(seed_max) \
53  VSMC_RUNTIME_ASSERT((seed_max > 1), \
54  "**SeedGenerator::modulo** " \
55  "THE MAXIMUM OF THE INTERNAL SEED IS NO LARGER THAN 1")
56 
59 #ifndef VSMC_SEED_RESULT_TYPE
60 #define VSMC_SEED_RESULT_TYPE unsigned
61 #endif
62 
63 namespace vsmc
64 {
65 
88 template <typename ID, typename ResultType = VSMC_SEED_RESULT_TYPE>
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 VSMC_MNE();
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  {
227 
228  modulo(divisor_, remainder_);
229  }
230 }; // class SeedGenerator
231 
252 template <typename ID, typename T, std::size_t K>
253 class SeedGenerator<ID, std::array<T, K>>
254 {
255  public:
256  using result_type = std::array<T, K>;
257  using skip_type = T;
258 
259  SeedGenerator(const SeedGenerator<ID, std::array<T, K>> &) = delete;
260 
262  const SeedGenerator<ID, std::array<T, K>> &) = delete;
263 
265  {
267 
268  return seed;
269  }
270 
277  template <typename RNGType>
278  void seed_rng(RNGType &rng)
279  {
280  seed_rng_dispatch(rng,
281  std::integral_constant<bool,
282  std::is_same<result_type,
283  internal::KeyType<RNGType>>::value>());
284  }
285 
287  {
288  std::lock_guard<std::mutex> lock_(mtx_);
289  skip();
290 
291  return seed_;
292  }
293 
295  {
296  result_type s1(get());
297  result_type s2(get());
298  for (std::size_t k = 0; k != K; ++k)
299  if (s1[k] != s2[k])
300  return s2[k];
301 
302  return std::get<0>(s2);
303  }
304 
305  void set(T s)
306  {
307  seed_.fill(0);
308  seed_.front() = s;
309  }
310 
311  void set(result_type seed) { seed_ = seed; }
312 
313  result_type seed() const { return seed_; }
314 
315  result_type seed_max() const { return seed_max_; }
316 
317  skip_type divisor() const { return divisor_; }
318 
319  skip_type remainder() const { return remainder_; }
320 
322  {
324 
325  divisor_ = div;
326  remainder_ = rem;
327  seed_max_.fill(std::numeric_limits<skip_type>::max VSMC_MNE());
328 
329  set(seed_);
330  }
331 
332  void skip(skip_type steps) { increment(seed_, steps); }
333 
334  void skip() { increment(seed_); }
335 
336  template <typename CharT, typename Traits>
337  friend std::basic_ostream<CharT, Traits> &operator<<(
338  std::basic_ostream<CharT, Traits> &os,
339  const SeedGenerator<ID, std::array<T, K>> &sg)
340  {
341  if (!os.good())
342  return os;
343 
344  os << sg.seed_ << ' ';
345  os << sg.divisor_ << ' ';
346  os << sg.remainder_ << ' ';
347 
348  return os;
349  }
350 
351  template <typename CharT, typename Traits>
352  friend std::basic_istream<CharT, Traits> &operator>>(
353  std::basic_istream<CharT, Traits> &is,
354  SeedGenerator<ID, std::array<T, K>> &sg)
355  {
356  if (!is.good())
357  return is;
358 
359  result_type s;
360  skip_type div;
361  skip_type rem;
362  is >> std::ws >> s;
363  is >> std::ws >> div;
364  is >> std::ws >> rem;
365 
366  if (is.good()) {
367  sg.modulo(div, rem);
368  sg.set(s);
369  }
370 
371  return is;
372  }
373 
374  private:
375  result_type seed_;
376  result_type seed_max_;
377  skip_type divisor_;
378  skip_type remainder_;
379  std::mutex mtx_;
380 
381  SeedGenerator() : divisor_(1), remainder_(0)
382  {
384 
385  seed_.fill(0);
386  seed_max_.fill(0);
387  modulo(divisor_, remainder_);
388  }
389 
390  template <typename RNGType>
391  void seed_rng_dispatch(RNGType &rng, std::true_type)
392  {
393  rng.seed(get());
394  }
395 
396  template <typename RNGType>
397  void seed_rng_dispatch(RNGType &rng, std::false_type)
398  {
399  rng.seed(get_scalar());
400  }
401 }; // class SeedGenerator
402 
406 
407 } // namespace vsmc
408 
409 #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
friend std::basic_istream< CharT, Traits > & operator>>(std::basic_istream< CharT, Traits > &is, SeedGenerator< ID, std::array< T, K >> &sg)
Definition: seed.hpp:352
result_type seed_max() const
The maximum of the internal seed integer.
Definition: seed.hpp:139
SeedGenerator< ID, ResultType > & operator=(const SeedGenerator< ID, ResultType > &)=delete
typename KeyTypeTrait< T >::type KeyType
Definition: common.hpp:325
skip_type divisor() const
The divisor of the output seed.
Definition: seed.hpp:142
#define VSMC_MNE
Definition: defines.hpp:38
friend std::basic_ostream< CharT, Traits > & operator<<(std::basic_ostream< CharT, Traits > &os, const SeedGenerator< ID, std::array< T, K >> &sg)
Definition: seed.hpp:337
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:47
#define VSMC_RUNTIME_ASSERT_RNG_SEED_GENERATOR_MODULO(div, rem)
Definition: seed.hpp:42
Seed generator.
Definition: seed.hpp:89
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
#define VSMC_STATIC_ASSERT_RNG_SEED_GENERATOR_RESULT_TYPE(T)
Definition: seed.hpp:38
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
static SeedGenerator< ID, std::array< T, K > > & instance()
Definition: seed.hpp:264
void seed_rng(RNGType &rng)
Equivalent to rng.seed(get()) or rng.seed(std::get<0>(get())).
Definition: seed.hpp:278
#define VSMC_RUNTIME_ASSERT_RNG_SEED_MAX(seed_max)
Definition: seed.hpp:52
void modulo(skip_type div, skip_type rem)
Definition: seed.hpp:321
void skip()
Skip the internal seed by 1 step.
Definition: seed.hpp:172