ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/include/rng.h
Revision: 1.13
Committed: Wed Nov 16 23:42:01 2016 UTC (7 years, 6 months ago) by root
Content type: text/plain
Branch: MAIN
Changes since 1.12: +1 -1 lines
Log Message:
copyright update 2016

File Contents

# Content
1 /*
2 * This file is part of Deliantra, the Roguelike Realtime MMORPG.
3 *
4 * Copyright (©) 2010,2011,2012,2013,2014,2015,2016 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 typedef lc_rng< 1664525U, 1013904223U> numerical_recipes_rng;
86
87 template<typename T, int N, int k>
88 struct gfsr_rng
89 {
90 int i;
91 T x[N];
92
93 // rng must have same bitwidth as T
94 template<typename RNG>
95 void seed_rng (RNG rng)
96 {
97 i = N;
98
99 do
100 x [--i] = rng.next ();
101 while (i > sizeof (T) * 8);
102
103 T m = 1;
104
105 do
106 {
107 x [--i] = (rng.next () | m) & ~(m - 1);
108 m <<= 1;
109 }
110 while (i);
111 }
112
113 // actually should subclass to gfsr32... :)
114 void seed (seed_t seed)
115 {
116 xorshift_rng rng;
117
118 rng.seed (seed);
119 this->seed_rng (rng);
120 }
121
122 T next ()
123 {
124 int j = i + (k - N);
125
126 if (j < 0)
127 j += N;
128
129 T v = (x [i] ^= x [j]);
130
131 i = (i ? i : N) - 1;
132
133 return v;
134 }
135 };
136
137 // these are about 2-3 times faster than tausworthe, non-inlined,
138 // and likely of higher quality.
139 typedef gfsr_rng<uint32_t, 250, 103> r250_rng;
140 typedef gfsr_rng<uint32_t, 521, 168> r521_rng;
141
142 // freeciv uses this one, so it's good enough for us :)
143 // (also known as mitchell moore generator)
144 typedef gfsr_rng<uint32_t, 55, 24> freeciv_rng;
145
146 // this one should be high quality, but is slightly slower than tausworthe
147 struct r250521_rng
148 {
149 r250_rng r250;
150 r521_rng r521;
151
152 void seed (uint32_t seed);
153 uint32_t next ();
154 };
155
156 /////////////////////////////////////////////////////////////////////////////
157
158 // this is actually an adaptor that provides different
159 // distributions of random numbers.
160 template<class generator>
161 struct random_number_generator : generator
162 {
163 random_number_generator ()
164 {
165 }
166
167 random_number_generator (seed_t seed)
168 {
169 this->seed (seed);
170 }
171
172 // uniform distribution, [0 .. num - 1]
173 uint32_t operator ()(uint32_t num)
174 {
175 return !is_constant (num) ? get_range (num) // non-constant
176 : num & (num - 1) ? (this->next () * (uint64_t)num) >> 32U // constant, non-power-of-two
177 : this->next () & (num - 1); // constant, power-of-two
178 }
179
180 // return a number within the closed interval [min .. max], max can be >, < or == min.
181 int operator () (int r_min, int r_max)
182 {
183 return is_constant (r_min <= r_max) && r_min <= r_max
184 ? r_min + operator ()(r_max - r_min + 1)
185 : get_range (r_min, r_max);
186 }
187
188 uint32_t get_u32 ();
189 uint64_t get_u64 ();
190 float get_float ();
191 double get_double ();
192
193 // return a number within the half-open interval [0..1[
194 double operator () ()
195 {
196 return get_double ();
197 }
198
199 uint32_t poisson (double mean);
200
201 protected:
202 uint32_t get_range (uint32_t r_max);
203 int get_range (int r_min, int r_max);
204 };
205
206 // the default rng used in the game
207 typedef random_number_generator<freeciv_rng> rand_gen;
208
209 // used when we often seed
210 typedef random_number_generator<tausworthe_rng> seedable_rand_gen;
211
212 extern rand_gen rndm, rmg_rndm;
213
214 #endif
215