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,2014, 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 
37 #define VSMC_STATIC_ASSERT_RNG_SEED_GENERATOR_RESULT_TYPE(T) \
38  VSMC_STATIC_ASSERT((::vsmc::cxx11::is_unsigned<T>::value), \
39  USE_SeedGenerator_WITH_A_RESULT_TYPE_NOT_AN_UNSIGNED_INTEGER)
40 
41 #define VSMC_RUNTIME_ASSERT_RNG_SEED_GENERATOR_MODULO(div, rem) \
42  VSMC_RUNTIME_ASSERT((div > rem), \
43  ("**SeedGenerator::modulo** " \
44  "REMAINDER IS NOT SMALLER THAN THE DIVISOR"))
45 
46 #define VSMC_RUNTIME_WARNING_RNG_SEED_GENERATOR_MODULO(div, rem) \
47  VSMC_RUNTIME_WARNING((div == 1 && rem == 0), \
48  ("**SeedGenerator::modulo** " \
49  "COUNTER TYPE SEED DOES NOT SUPPORT MODULO"))
50 
51 #define VSMC_RUNTIME_ASSERT_RNG_SEED_MAX(seed_max) \
52  VSMC_RUNTIME_ASSERT((seed_max > 1), \
53  ("**SeedGenerator::modulo** " \
54  "THE MAXIMUM OF THE INTERNAL SEED IS NO LARGER THAN 1"))
55 
58 #ifndef VSMC_SEED_RESULT_TYPE
59 #define VSMC_SEED_RESULT_TYPE unsigned
60 #endif
61 
62 namespace vsmc {
63 
86 template <typename ID, typename ResultType = VSMC_SEED_RESULT_TYPE>
88 {
89  public :
90 
91  typedef ResultType result_type;
92  typedef ResultType skip_type;
93 
95  {
97 
98  return seed;
99  }
100 
102  result_type get () {skip(); return seed_ * divisor_ + remainder_;}
103 
110  void set (result_type seed) {seed_ = seed % seed_max_;}
111 
113  result_type seed () const {return seed_;}
114 
116  result_type seed_max () const {return seed_max_;}
117 
119  skip_type divisor () const {return divisor_;}
120 
122  skip_type remainder () const {return remainder_;}
123 
125  void modulo (skip_type div, skip_type rem)
126  {
128 
129  divisor_ = div;
130  remainder_ = rem;
131  seed_max_ = static_cast<skip_type>(~static_cast<skip_type>(0));
132  seed_max_ -= seed_max_ % divisor_;
133  seed_max_ /= divisor_;
134 
136 
137  set(seed_);
138  }
139 
141  void skip (skip_type steps)
142  {
143  result_type incr = steps % seed_max_;
144  result_type diff = seed_max_ - seed_;
145  seed_ = incr <= diff ? (seed_ + incr) : (incr - diff);
146  }
147 
149  void skip () {seed_ = seed_ == seed_max_ ? 1 : (seed_ + 1);}
150 
151  template <typename CharT, typename Traits>
152  friend inline std::basic_ostream<CharT, Traits> &operator<< (
153  std::basic_ostream<CharT, Traits> &os,
155  {
156  if (!os.good())
157  return os;
158 
159  os << sg.seed_ << ' ';
160  os << sg.divisor_ << ' ';
161  os << sg.remainder_;
162 
163  return os;
164  }
165 
166  template <typename CharT, typename Traits>
167  friend inline std::basic_istream<CharT, Traits> &operator>> (
168  std::basic_istream<CharT, Traits> &is,
170  {
171  if (!is.good())
172  return is;
173 
174  result_type s;
175  skip_type div;
176  skip_type rem;
177  is >> std::ws >> s;
178  is >> std::ws >> div;
179  is >> std::ws >> rem;
180 
181  if (is.good()) {
182  sg.modulo(div, rem);
183  sg.set(s);
184  }
185 
186  return is;
187  }
188 
189  private :
190 
191  result_type seed_;
192  result_type seed_max_;
193  skip_type divisor_;
194  skip_type remainder_;
195 
196  SeedGenerator () : seed_(0), seed_max_(0), divisor_(1), remainder_(0)
197  {
199 
200  modulo(divisor_, remainder_);
201  }
202 
203  SeedGenerator (const SeedGenerator<ID, ResultType> &);
204 
205  SeedGenerator<ID, ResultType> &operator= (
206  const SeedGenerator<ID, ResultType> &);
207 }; // class SeedGenerator
208 
229 template <typename ID, typename T, std::size_t K>
230 class SeedGenerator<ID, Array<T, K> >
231 {
232  public :
233 
235  typedef T skip_type;
236 
238  {
240 
241  return seed;
242  }
243 
244  result_type get () {skip(); return seed_;}
245 
246  void set (result_type seed) {seed_ = seed;}
247 
248  result_type seed () const {return seed_;}
249 
250  result_type seed_max () const {return seed_max_;}
251 
252  skip_type divisor () const {return divisor_;}
253 
254  skip_type remainder () const {return remainder_;}
255 
256  void modulo (skip_type div, skip_type rem)
257  {
259 
260  divisor_ = div;
261  remainder_ = rem;
262  seed_max_.fill(static_cast<skip_type>(~static_cast<skip_type>(0)));
263 
264  set(seed_);
265  }
266 
267  void skip (skip_type steps)
268  {Counter<result_type>::increment(seed_, steps);}
269 
271 
272  template <typename CharT, typename Traits>
273  friend inline std::basic_ostream<CharT, Traits> &operator<< (
274  std::basic_ostream<CharT, Traits> &os,
275  const SeedGenerator<ID, Array<T, K> > &sg)
276  {
277  if (!os.good())
278  return os;
279 
280  os << sg.seed_ << ' ';
281  os << sg.divisor_ << ' ';
282  os << sg.remainder_ << ' ';
283 
284  return os;
285  }
286 
287  template <typename CharT, typename Traits>
288  friend inline std::basic_istream<CharT, Traits> &operator>> (
289  std::basic_istream<CharT, Traits> &is,
290  SeedGenerator<ID, Array<T, K> > &sg)
291  {
292  if (!is.good())
293  return is;
294 
295  result_type s;
296  skip_type div;
297  skip_type rem;
298  is >> std::ws >> s;
299  is >> std::ws >> div;
300  is >> std::ws >> rem;
301 
302  if (is.good()) {
303  sg.modulo(div, rem);
304  sg.set(s);
305  }
306 
307  return is;
308  }
309 
310  private :
311 
312  result_type seed_;
313  result_type seed_max_;
314  skip_type divisor_;
315  skip_type remainder_;
316 
317  SeedGenerator () : divisor_(1), remainder_(0)
318  {
320 
321  seed_.fill(0);
322  seed_max_.fill(0);
323  modulo(divisor_, remainder_);
324  }
325 
326  SeedGenerator<ID, Array<T, K> > (const SeedGenerator<ID, Array<T, K> > &);
327 
328  SeedGenerator<ID, Array<T, K> > &operator= (
329  const SeedGenerator<ID, Array<T, K> > &);
330 }; // class SeedGenerator
331 
335 
336 } // namespace vsmc
337 
338 #endif // VSMC_RNG_SEED_HPP
static SeedGenerator< ID, ResultType > & instance()
Definition: seed.hpp:94
Definition: adapter.hpp:37
void modulo(skip_type div, skip_type rem)
Definition: seed.hpp:256
ResultType result_type
Definition: seed.hpp:91
void skip(skip_type steps)
Skip the internal seed by a given steps.
Definition: seed.hpp:141
void set(result_type seed)
Definition: seed.hpp:246
#define VSMC_STATIC_ASSERT_RNG_SEED_GENERATOR_RESULT_TYPE(T)
Definition: seed.hpp:37
#define VSMC_RUNTIME_ASSERT_RNG_SEED_GENERATOR_MODULO(div, rem)
Definition: seed.hpp:41
friend std::basic_istream< CharT, Traits > & operator>>(std::basic_istream< CharT, Traits > &is, SeedGenerator< ID, ResultType > &sg)
Definition: seed.hpp:167
void set(result_type seed)
Set the internal seed.
Definition: seed.hpp:110
#define VSMC_RUNTIME_WARNING_RNG_SEED_GENERATOR_MODULO(div, rem)
Definition: seed.hpp:46
result_type seed_max() const
The maximum of the internal seed integer.
Definition: seed.hpp:116
SeedGenerator< NullType, unsigned > Seed
The default Seed type.
Definition: seed.hpp:334
skip_type divisor() const
The divisor of the output seed.
Definition: seed.hpp:119
skip_type remainder() const
The remainder of the output seed.
Definition: seed.hpp:122
#define VSMC_RUNTIME_ASSERT_RNG_SEED_MAX(seed_max)
Definition: seed.hpp:51
ResultType skip_type
Definition: seed.hpp:92
Seed generator.
Definition: seed.hpp:87
friend std::basic_ostream< CharT, Traits > & operator<<(std::basic_ostream< CharT, Traits > &os, const SeedGenerator< ID, ResultType > &sg)
Definition: seed.hpp:152
result_type seed() const
The current internal seed.
Definition: seed.hpp:113
void modulo(skip_type div, skip_type rem)
Set the divisor and the remainder.
Definition: seed.hpp:125
Static array.
Definition: array.hpp:79
void skip()
Skip the internal seed by 1 step.
Definition: seed.hpp:149
static SeedGenerator< ID, Array< T, K > > & instance()
Definition: seed.hpp:237