wfmath  1.0.3
A math library for the Worldforge system.
MersenneTwister.h
1 // MersenneTwister.h
2 //
3 // The WorldForge Project
4 // Copyright (C) 2013 The WorldForge Project
5 //
6 // This program is free software; you can redistribute it and/or modify
7 // it under the terms of the GNU General Public License as published by
8 // the Free Software Foundation; either version 2 of the License, or
9 // (at your option) any later version.
10 //
11 // This program is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 // GNU General Public License for more details.
15 //
16 // You should have received a copy of the GNU General Public License along
17 // with this program; if not, write to the Free Software Foundation, Inc.,
18 // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19 //
20 // For information about WorldForge and its authors, please contact
21 // the Worldforge Web Site at http://www.worldforge.org.
22 //
23 #ifndef WFMATH_MERSENNE_TWISTER_H_
24 #define WFMATH_MERSENNE_TWISTER_H_
25 
26 #include <iosfwd>
27 #include <cstdint>
28 
29 namespace WFMath {
30 
31 class MTRand {
32 public:
33  typedef uint32_t uint32;
34 
35  static const uint32 state_size = 624;
36 
37 public:
38  MTRand();
39  explicit MTRand(uint32 oneSeed);
40  explicit MTRand(uint32 bigSeed[], uint32 seedLength = state_size);
41 
42  // real-valued random numbers on [0, 1] or [0, n]
43  template<typename FloatT>
44  FloatT rand();
45  double rand();
46  double rand(const double& n);
47 
48  // integer-valued random numbers on [0, 2^32-1] or [0, n]
49  uint32 randInt();
50  uint32 randInt(uint32 n);
51 
52  void seed();
53  void seed(uint32 oneSeed);
54  void seed(const uint32 init_vector[], uint32 init_vector_length = state_size);
55 
56  std::ostream& save(std::ostream&) const;
57  std::istream& load(std::istream&);
58 
59  static MTRand instance;
60 
61 private:
62  uint32 state[state_size];
63  uint32 index;
64 };
65 
66 
67 inline MTRand::MTRand(uint32 oneSeed)
68 : index(0)
69 { seed(oneSeed); }
70 
71 inline MTRand::MTRand(uint32 bigSeed[], uint32 seedLength)
72 : index(0)
73 { seed(bigSeed, seedLength); }
74 
75 inline MTRand::MTRand()
76 : index(0)
77 { seed(); }
78 
79 template<>
80 inline float MTRand::rand<float>()
81 { return float(randInt()) * (1.0f/4294967295.0f); }
82 
83 template<>
84 inline double MTRand::rand<double>()
85 { return double(randInt()) * (1.0/4294967295.0); }
86 
87 inline double MTRand::rand()
88 { return double(randInt()) * (1.0/4294967295.0); }
89 
90 inline double MTRand::rand( const double& n )
91 { return rand() * n; }
92 
93 
94 inline MTRand::uint32 MTRand::randInt(uint32 n)
95 {
96  uint32 used = n;
97  used |= used >> 1u;
98  used |= used >> 2u;
99  used |= used >> 4u;
100  used |= used >> 8u;
101  used |= used >> 16u;
102 
103  uint32 i;
104  do
105  i = randInt() & used;
106  while( i > n );
107  return i;
108 }
109 
110 
111 #if 0
112 inline void MTRand::save(uint32* saveArray) const
113 {
114  uint32 *sa = saveArray;
115  const uint32 *s = state;
116  int i = state_size;
117  for( ; i--; *sa++ = *s++ ) {}
118  *sa = left;
119 }
120 
121 
122 inline void MTRand::load(uint32 *const loadArray)
123 {
124  uint32 *s = state;
125  uint32 *la = loadArray;
126  int i = state_size;
127  for( ; i--; *s++ = *la++ ) {}
128  left = *la;
129  pNext = &state[state_size-left];
130 }
131 #endif
132 
133 std::ostream& operator<<(std::ostream& os, MTRand const& mtrand);
134 std::istream& operator>>(std::istream& is, MTRand& mtrand);
135 
136 } // namespace
137 
138 #endif // WFMATH_MERSENNE_TWISTER_H_
Generic library namespace.
Definition: shape.h:41