WFMath  1.0.2
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 <climits>
28 #include <cmath>
29 #include <stdint.h>
30 
31 namespace WFMath {
32 
33 class MTRand {
34 public:
35  typedef uint32_t uint32;
36 
37  static const uint32 state_size = 624;
38 
39 public:
40  MTRand();
41  MTRand(uint32 oneSeed);
42  MTRand(uint32* const bigSeed, uint32 const seedLength = state_size);
43 
44  // real-valued random numbers on [0, 1] or [0, n]
45  template<typename FloatT>
46  FloatT rand();
47  double rand();
48  double rand(const double& n);
49 
50  // integer-valued random numbers on [0, 2^32-1] or [0, n]
51  uint32 randInt();
52  uint32 randInt(uint32 n);
53 
54  void seed();
55  void seed(uint32 oneSeed);
56  void seed(uint32* const init_vector, uint32 init_vector_length = state_size);
57 
58  std::ostream& save(std::ostream&) const;
59  std::istream& load(std::istream&);
60 
61  static MTRand instance;
62 
63 private:
64  uint32 state[state_size];
65  uint32 index;
66 };
67 
68 
69 inline MTRand::MTRand(uint32 s)
70 : index(0)
71 { seed(s); }
72 
73 inline MTRand::MTRand(uint32* const bigSeed, const uint32 seedLength)
74 : index(0)
75 { seed(bigSeed, seedLength); }
76 
77 inline MTRand::MTRand()
78 : index(0)
79 { seed(); }
80 
81 template<>
82 inline float MTRand::rand<float>()
83 { return float(randInt()) * (1.0f/4294967295.0f); }
84 
85 template<>
86 inline double MTRand::rand<double>()
87 { return double(randInt()) * (1.0/4294967295.0); }
88 
89 inline double MTRand::rand()
90 { return double(randInt()) * (1.0/4294967295.0); }
91 
92 inline double MTRand::rand( const double& n )
93 { return rand() * n; }
94 
95 
96 inline MTRand::uint32 MTRand::randInt(uint32 n)
97 {
98  uint32 used = n;
99  used |= used >> 1;
100  used |= used >> 2;
101  used |= used >> 4;
102  used |= used >> 8;
103  used |= used >> 16;
104 
105  uint32 i;
106  do
107  i = randInt() & used;
108  while( i > n );
109  return i;
110 }
111 
112 
113 #if 0
114 inline void MTRand::save(uint32* saveArray) const
115 {
116  register uint32 *sa = saveArray;
117  register const uint32 *s = state;
118  register int i = state_size;
119  for( ; i--; *sa++ = *s++ ) {}
120  *sa = left;
121 }
122 
123 
124 inline void MTRand::load(uint32 *const loadArray)
125 {
126  register uint32 *s = state;
127  register uint32 *la = loadArray;
128  register int i = state_size;
129  for( ; i--; *s++ = *la++ ) {}
130  left = *la;
131  pNext = &state[state_size-left];
132 }
133 #endif
134 
135 std::ostream& operator<<(std::ostream& os, MTRand const& mtrand);
136 std::istream& operator>>(std::istream& is, MTRand& mtrand);
137 
138 } // namespace
139 
140 #endif // WFMATH_MERSENNE_TWISTER_H_
Generic library namespace.
Definition: atlasconv.h:45