ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/include/rng.h
Revision: 1.8
Committed: Sat Apr 30 11:02:25 2011 UTC (13 years ago) by root
Content type: text/plain
Branch: MAIN
Changes since 1.7: +5 -1 lines
Log Message:
*** empty log message ***

File Contents

# Content
1 /*
2 * This file is part of Deliantra, the Roguelike Realtime MMORPG.
3 *
4 * Copyright (©) 2010,2011 Marc Alexander Lehmann / Robin Redeker / the Deliantra team
5 *
6 * Deliantra is free software: you can redistribute it and/or modify it under
7 * the terms of the Affero GNU General Public License as published by the
8 * Free Software Foundation, either version 3 of the License, or (at your
9 * 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 Affero GNU General Public License
17 * and the GNU General Public License along with this program. If not, see
18 * <http://www.gnu.org/licenses/>.
19 *
20 * The authors can be reached via e-mail to <support@deliantra.net>
21 */
22
23 #ifndef RNG_H__
24 #define RNG_H__
25
26 #include <compiler.h>
27
28 typedef uint32_t seed_t; // overkill
29
30 // P. L'Ecuyer, “Maximally Equidistributed Combined Tausworthe Generators”, Mathematics of Computation, 65, 213 (1996), 203–213.
31 // http://www.iro.umontreal.ca/~lecuyer/myftp/papers/tausme.ps
32 // http://www.iro.umontreal.ca/~lecuyer/myftp/papers/tausme2.ps
33 struct tausworthe_rng
34 {
35 uint32_t state [4];
36
37 void seed (uint32_t seed);
38 uint32_t next ();
39 };
40
41 // Xorshift RNGs, George Marsaglia
42 // http://www.jstatsoft.org/v08/i14/paper
43 // this one is about 40% faster than the tausworthe one above (i.e. not much),
44 // despite the inlining, and has the issue of only creating 2**32-1 numbers.
45 // see also http://www.iro.umontreal.ca/~lecuyer/myftp/papers/xorshift.pdf
46 struct xorshift_rng
47 {
48 uint32_t x, y;
49
50 void seed (uint32_t seed)
51 {
52 x = seed ? seed : 0xdeadbeef;
53 y = x * 69069U;
54 }
55
56 uint32_t next ()
57 {
58 uint32_t t = x ^ (x << 10);
59 x = y;
60 y = y ^ (y >> 13) ^ t ^ (t >> 10);
61 return y;
62 }
63 };
64
65 template<uint32_t A, uint32_t B>
66 struct lc_rng
67 {
68 uint32_t x;
69
70 void seed (uint32_t seed)
71 {
72 x = seed;
73 }
74
75 uint32_t next ()
76 {
77 x = x * A + B;
78 return x;
79 }
80 };
81
82 typedef lc_rng<3039177861U, 0U> borosh_niederreiter_rng;
83 typedef lc_rng<2147001325U, 715136305U> bcpl_rng;
84 typedef lc_rng< 1664525U, 1U> lavaux_janssens_rng;
85
86 template<typename T, int N, int k>
87 struct gfsr_rng
88 {
89 int i;
90 T x[N];
91
92 // rng must have same bitwidth as T
93 template<typename RNG>
94 void seed_rng (RNG rng)
95 {
96 i = N;
97
98 do
99 x [--i] = rng.next ();
100 while (i > sizeof (T) * 8);
101
102 T m = 1;
103
104 do
105 {
106 x [--i] = (rng.next () | m) & ~(m - 1);
107 m <<= 1;
108 }
109 while (i);
110 }
111
112 // actually should subclass to gfsr32... :)
113 void seed (seed_t seed)
114 {
115 xorshift_rng rng;
116
117 rng.seed (seed);
118 this->seed_rng (rng);
119 }
120
121 T next ()
122 {
123 int j = i + (k - N);
124
125 if (j < 0)
126 j += N;
127
128 T v = (x [i] ^= x [j]);
129
130 i = (i ? i : N) - 1;
131
132 return v;
133 }
134 };
135
136 // these are about 2-3 times faster than tausworthe, non-inlined,
137 // and likely of higher quality.
138 typedef gfsr_rng<uint32_t, 250, 103> r250_rng;
139 typedef gfsr_rng<uint32_t, 521, 168> r521_rng;
140
141 // freeciv uses this one, so it's good enough for us :)
142 // (also known as mitchell moore generator
143 typedef gfsr_rng<uint32_t, 55, 24> freeciv_rng;
144
145 // this one should be high quality, but is slightly slower than tausworthe
146 struct r250521_rng
147 {
148 r250_rng r250;
149 r521_rng r521;
150
151 void seed (uint32_t seed);
152 uint32_t next ();
153 };
154
155 /////////////////////////////////////////////////////////////////////////////
156
157 // this is actually an adaptor that provides different
158 // distributions of random numbers.
159 template<class generator>
160 struct random_number_generator : generator
161 {
162 random_number_generator ()
163 {
164 }
165
166 random_number_generator (seed_t seed)
167 {
168 this->seed (seed);
169 }
170
171 // uniform distribution, [0 .. num - 1]
172 uint32_t operator ()(uint32_t num)
173 {
174 return !is_constant (num) ? get_range (num) // non-constant
175 : num & (num - 1) ? (this->next () * (uint64_t)num) >> 32U // constant, non-power-of-two
176 : this->next () & (num - 1); // constant, power-of-two
177 }
178
179 // return a number within the closed interval [min .. max], max can be >, < or == min.
180 int operator () (int r_min, int r_max)
181 {
182 return is_constant (r_min <= r_max) && r_min <= r_max
183 ? r_min + operator ()(r_max - r_min + 1)
184 : get_range (r_min, r_max);
185 }
186
187 uint32_t get_u32 ();
188 uint64_t get_u64 ();
189 float get_float ();
190 double get_double ();
191
192 // return a number within the half-open interval [0..1[
193 double operator () ()
194 {
195 return get_double ();
196 }
197
198 uint32_t poisson (double mean);
199
200 protected:
201 uint32_t get_range (uint32_t r_max);
202 int get_range (int r_min, int r_max);
203 };
204
205 // the default rng used in the game
206 typedef random_number_generator<freeciv_rng> rand_gen;
207
208 // used when we often seed
209 typedef random_number_generator<tausworthe_rng> seedable_rand_gen;
210
211 extern rand_gen rndm, rmg_rndm;
212
213 #endif
214