dcmt-cpp  1.0.0
dcmt.h
Go to the documentation of this file.
1 #ifndef DCMT_CPP_DCMT_H
2 #define DCMT_CPP_DCMT_H
3 
4 #include <cassert>
5 #include <cstddef> // std::size_t
6 #include <cstdint>
7 #include <istream>
8 #include <limits>
9 #include <memory> // std::unique_ptr
10 #include <ostream>
11 #include <type_traits>
12 #include <utility> // std::move, std::swap
13 
17 namespace dcmt {
18 
22 namespace detail {
23 
24 struct mt_struct {
25  std::uint32_t aaa;
26  int mm, nn, rr, ww;
27  std::uint32_t wmask, umask, lmask;
29  std::uint32_t maskB, maskC;
30  int i;
31  std::uint32_t* state;
32 };
33 
34 void* alloc_memory(std::size_t size);
35 void free_memory(void* ptr);
36 void free_mt_struct(mt_struct* mts);
37 
38 inline bool operator==(const mt_struct& a, const mt_struct& b) {
39  if (a.aaa != b.aaa || a.mm != b.mm || a.nn != b.nn || a.rr != b.rr ||
40  a.ww != b.ww || a.wmask != b.wmask || a.umask != b.umask ||
41  a.lmask != b.lmask || a.shift0 != b.shift0 || a.shift1 != b.shift1 ||
42  a.shiftB != b.shiftB || a.shiftC != b.shiftC || a.maskB != b.maskB ||
43  a.maskC != b.maskC || a.i != b.i) {
44  return false;
45  }
46  for (int i = 0; i < a.nn; i++) {
47  if (a.state[i] != b.state[i]) {
48  return false;
49  }
50  }
51  return true;
52 }
53 
54 template <class CharT, class Traits>
55 inline std::basic_ostream<CharT, Traits>& operator<<(
56  std::basic_ostream<CharT, Traits>& os, const mt_struct& mt) {
57  os << mt.aaa << ' ' << mt.mm << ' ' << mt.nn << ' ' << mt.rr << ' ' << mt.ww
58  << ' ' << mt.wmask << ' ' << mt.umask << ' ' << mt.lmask << ' '
59  << mt.shift0 << ' ' << mt.shift1 << ' ' << mt.shiftB << ' ' << mt.shiftC
60  << ' ' << mt.maskB << ' ' << mt.maskC << ' ' << mt.i;
61  for (int i = 0; i < mt.nn; i++) {
62  os << ' ' << mt.state[i];
63  }
64  return os;
65 }
66 
67 template <class CharT, class Traits>
68 inline std::basic_istream<CharT, Traits>& operator>>(
69  std::basic_istream<CharT, Traits>& is, mt_struct& mt) {
70  mt_struct tmp; // NOLINT(cppcoreguidelines-pro-type-member-init)
71 
72  is >> tmp.aaa >> std::ws >> tmp.mm >> std::ws >> tmp.nn >> std::ws >>
73  tmp.rr >> std::ws >> tmp.ww >> std::ws >> tmp.wmask >> std::ws >>
74  tmp.umask >> std::ws >> tmp.lmask >> std::ws >> tmp.shift0 >> std::ws >>
75  tmp.shift1 >> std::ws >> tmp.shiftB >> std::ws >> tmp.shiftC >> std::ws >>
76  tmp.maskB >> std::ws >> tmp.maskC >> std::ws >> tmp.i;
77 
78  tmp.state =
79  static_cast<std::uint32_t*>(alloc_memory(sizeof(std::uint32_t) * tmp.nn));
80 
81  for (int i = 0; i < mt.nn; i++) {
82  is >> std::ws >> tmp.state[i];
83  }
84 
85  std::swap(tmp, mt);
86 
87  free_memory(tmp.state);
88 
89  return is;
90 }
91 
93  void operator()(mt_struct* ptr) { free_mt_struct(ptr); }
94 };
95 
97  public:
98  dcmt_engine_impl(int w, int p, int id, std::uint32_t seed);
99  dcmt_engine_impl(const dcmt_engine_impl& impl); // deep copy
100  dcmt_engine_impl(dcmt_engine_impl&&) noexcept = default;
101  ~dcmt_engine_impl() = default;
102  dcmt_engine_impl& operator=(const dcmt_engine_impl& impl); // deep copy
103  dcmt_engine_impl& operator=(dcmt_engine_impl&&) noexcept = default;
104 
105  void sgenrand(std::uint32_t seed);
106  std::uint32_t genrand();
107  void discard(unsigned long long z); // NOLINT(google-runtime-int)
108 
109  friend bool operator==(const dcmt_engine_impl& a, const dcmt_engine_impl& b) {
110  // See https://bugs.llvm.org/show_bug.cgi?id=28480
111  // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-array-to-pointer-decay)
112  assert(a.ptr_);
113  // See https://bugs.llvm.org/show_bug.cgi?id=28480
114  // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-array-to-pointer-decay)
115  assert(b.ptr_);
116  return *a.ptr_ == *b.ptr_;
117  }
118 
119  template <class CharT, class Traits>
120  friend std::basic_ostream<CharT, Traits>& operator<<(
121  std::basic_ostream<CharT, Traits>& os, const dcmt_engine_impl& impl) {
122  // See https://bugs.llvm.org/show_bug.cgi?id=28480
123  // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-array-to-pointer-decay)
124  assert(impl.ptr_);
125  return os << *impl.ptr_;
126  }
127 
128  template <class CharT, class Traits>
129  friend std::basic_istream<CharT, Traits>& operator>>(
130  std::basic_istream<CharT, Traits>& is, dcmt_engine_impl& impl) {
131  // See https://bugs.llvm.org/show_bug.cgi?id=28480
132  // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-array-to-pointer-decay)
133  assert(impl.ptr_);
134  return is >> *impl.ptr_;
135  }
136 
137  private:
138  std::unique_ptr<mt_struct, mt_struct_deleter> ptr_;
139 };
140 
141 } // namespace detail
142 
150 template <class UIntType, std::size_t WordSize, std::size_t p>
151 class dcmt_param {
152  static_assert(std::is_integral<UIntType>::value &&
153  std::is_unsigned<UIntType>::value,
154  "UIntType must be an unsigned integral type");
155 
156  static_assert(WordSize == 31 || WordSize == 32, "WordSize must be 31 or 32");
157 
158  static_assert((WordSize == 31 &&
159  std::numeric_limits<UIntType>::max() >= 0x7fffffffU) ||
160  (WordSize == 32 &&
161  std::numeric_limits<UIntType>::max() >= 0xffffffffU),
162  "size of UIntType must be equal to or larger than WordSize");
163 
164  static_assert(
165  p == 521 || p == 607 || p == 1279 || p == 2203 || p == 2281 ||
166  p == 3217 || p == 4253 || p == 4423 || p == 9689 || p == 9941 ||
167  p == 11213 || p == 19937 || p == 21701 || p == 23209 || p == 44497,
168  "p must be in the range of 521 to 44497 and 2^p-1 must be a prime");
169 
171 
172  public:
176  using result_type = UIntType;
177 
181  static constexpr std::size_t word_size = WordSize;
182 
186  static constexpr std::size_t prime_exponent = p;
187 
191  static constexpr result_type default_id = 0;
192 
196  static constexpr result_type default_seed = 4172;
197 
204  // NOTE: currently, only lower 32 bits are used for the seed.
205  explicit dcmt_param(result_type id = default_id,
206  result_type seed = default_seed)
207  : impl_(word_size, prime_exponent, id, seed) {}
208 
209  private:
210  impl impl_;
211 
212  template <class U, std::size_t W, std::size_t P>
213  friend class dcmt_engine;
214 };
215 
223 template <class UIntType, std::size_t WordSize, std::size_t p>
224 class dcmt_engine {
226 
227  public:
232 
236  using result_type = UIntType;
237 
241  static constexpr std::size_t word_size = WordSize;
242 
246  static constexpr std::size_t prime_exponent = p;
247 
251  static constexpr result_type default_seed = 3241;
252 
258  explicit dcmt_engine(result_type seed = default_seed)
259  : dcmt_engine(param_type(), seed) {}
260 
267  explicit dcmt_engine(const param_type& param, result_type seed = default_seed)
268  : impl_(param.impl_) {
269  this->seed(seed);
270  }
271 
278  explicit dcmt_engine(param_type&& param, result_type seed = default_seed)
279  : impl_(std::move(param.impl_)) {
280  this->seed(seed);
281  }
282 
288  // NOTE: currently, only lower 32 bits are used for the seed.
289  void seed(result_type value = default_seed) { impl_.sgenrand(value); }
290 
296  result_type operator()() { return impl_.genrand(); }
297 
303  // NOTE: intentionally use "unsigned long long" for consistency with the
304  // standard <random> library.
305  // NOLINTNEXTLINE(google-runtime-int)
306  void discard(unsigned long long z) { impl_.discard(z); }
307 
313  static constexpr result_type min() { return 0U; }
314 
320  static constexpr result_type max() { return 0xffffffffU >> (32 - word_size); }
321 
330  friend bool operator==(const dcmt_engine& a, const dcmt_engine& b) {
331  return a.impl_ == b.impl_;
332  }
333 
342  friend bool operator!=(const dcmt_engine& a, const dcmt_engine& b) {
343  return !(a == b);
344  }
345 
353  template <class CharT, class Traits>
354  friend std::basic_ostream<CharT, Traits>& operator<<(
355  std::basic_ostream<CharT, Traits>& os, const dcmt_engine& e) {
356  return os << e.impl_;
357  }
358 
366  template <class CharT, class Traits>
367  friend std::basic_istream<CharT, Traits>& operator>>(
368  std::basic_istream<CharT, Traits>& is, dcmt_engine& e) {
369  return is >> e.impl_;
370  }
371 
372  private:
373  impl impl_;
374 };
375 
376 // Constant members.
377 
378 template <class UIntType, std::size_t WordSize, std::size_t p>
380 
381 template <class UIntType, std::size_t WordSize, std::size_t p>
383 
384 template <class UIntType, std::size_t WordSize, std::size_t p>
386 
387 template <class UIntType, std::size_t WordSize, std::size_t p>
389 
390 template <class UIntType, std::size_t WordSize, std::size_t p>
392 
393 template <class UIntType, std::size_t WordSize, std::size_t p>
395 
396 template <class UIntType, std::size_t WordSize, std::size_t p>
398 
399 // Predefined engine.
400 
406 
407 } // namespace dcmt
408 
409 #endif // DCMT_CPP_DCMT_H
int mm
Definition: dcmt.h:26
void free_memory(void *ptr)
Definition: dcmt.cpp:43
std::uint32_t * state
Definition: dcmt.h:31
friend std::basic_ostream< CharT, Traits > & operator<<(std::basic_ostream< CharT, Traits > &os, const dcmt_engine_impl &impl)
Definition: dcmt.h:120
std::uint32_t umask
Definition: dcmt.h:27
static constexpr result_type max()
Returns the maximum value potentially generated by the engine.
Definition: dcmt.h:320
void * alloc_memory(std::size_t size)
Definition: dcmt.cpp:32
bool operator==(const mt_struct &a, const mt_struct &b)
Definition: dcmt.h:38
static constexpr result_type min()
Returns the minimum value potentially generated by the engine, which is 0.
Definition: dcmt.h:313
std::basic_istream< CharT, Traits > & operator>>(std::basic_istream< CharT, Traits > &is, mt_struct &mt)
Definition: dcmt.h:68
std::uint32_t wmask
Definition: dcmt.h:27
int shift1
Definition: dcmt.h:28
Definition: dcmt.h:96
Definition: dcmt.h:24
Definition: dcmt.h:92
int shiftC
Definition: dcmt.h:28
int rr
Definition: dcmt.h:26
dcmt_engine(const param_type &param, result_type seed=default_seed)
Constructs the engine.
Definition: dcmt.h:267
dcmt_engine(result_type seed=default_seed)
Constructs the engine.
Definition: dcmt.h:258
dcmt_param(result_type id=default_id, result_type seed=default_seed)
Searches for a set of parameters for pseudo-random number generators.
Definition: dcmt.h:205
int i
Definition: dcmt.h:30
void operator()(mt_struct *ptr)
Definition: dcmt.h:93
void seed(result_type value=default_seed)
Reinitializes the engine by a new seed value.
Definition: dcmt.h:289
std::basic_ostream< CharT, Traits > & operator<<(std::basic_ostream< CharT, Traits > &os, const mt_struct &mt)
Definition: dcmt.h:55
int ww
Definition: dcmt.h:26
int shift0
Definition: dcmt.h:28
UIntType result_type
Integral type for generators.
Definition: dcmt.h:176
friend bool operator==(const dcmt_engine &a, const dcmt_engine &b)
Compares two engines.
Definition: dcmt.h:330
void free_mt_struct(mt_struct *mts)
dcmt_engine(param_type &&param, result_type seed=default_seed)
Constructs the engine.
Definition: dcmt.h:278
int shiftB
Definition: dcmt.h:28
std::uint32_t lmask
Definition: dcmt.h:27
Mersenne Twister pseudo-random number generator engine.
Definition: dcmt.h:224
friend std::basic_istream< CharT, Traits > & operator>>(std::basic_istream< CharT, Traits > &is, dcmt_engine_impl &impl)
Definition: dcmt.h:129
friend std::basic_ostream< CharT, Traits > & operator<<(std::basic_ostream< CharT, Traits > &os, const dcmt_engine &e)
Serializes the state of the given engine into a stream.
Definition: dcmt.h:354
Namespace for classes that wraps the DCMT library.
Definition: dcmt.h:17
std::uint32_t maskC
Definition: dcmt.h:29
void discard(unsigned long long z)
Advances the internal state.
Definition: dcmt.h:306
UIntType result_type
Integral type generated by the engine.
Definition: dcmt.h:236
friend bool operator==(const dcmt_engine_impl &a, const dcmt_engine_impl &b)
Definition: dcmt.h:109
std::uint32_t aaa
Definition: dcmt.h:25
result_type operator()()
Returns the next pseudo-random number.
Definition: dcmt.h:296
friend bool operator!=(const dcmt_engine &a, const dcmt_engine &b)
Compares two engines.
Definition: dcmt.h:342
std::uint32_t maskB
Definition: dcmt.h:29
int nn
Definition: dcmt.h:26
friend std::basic_istream< CharT, Traits > & operator>>(std::basic_istream< CharT, Traits > &is, dcmt_engine &e)
Deserializes the state of the given engine from a stream.
Definition: dcmt.h:367
Set of parameters for Mersenne Twister pseudo-random number generators.
Definition: dcmt.h:151