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

# User Rev Content
1 root 1.1 /*
2     * This file is part of Deliantra, the Roguelike Realtime MMORPG.
3     *
4 root 1.6 * Copyright (©) 2010,2011 Marc Alexander Lehmann / Robin Redeker / the Deliantra team
5 root 1.1 *
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 root 1.7 typedef uint32_t seed_t; // overkill
29    
30 root 1.1 // 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 root 1.3 struct tausworthe_rng
34 root 1.1 {
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 root 1.3 struct xorshift_rng
47 root 1.1 {
48     uint32_t x, y;
49    
50     void seed (uint32_t seed)
51     {
52 root 1.4 x = seed ? seed : 0xdeadbeef;
53 root 1.1 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 root 1.3 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 root 1.8 typedef lc_rng<3039177861U, 0U> borosh_niederreiter_rng;
83 root 1.3 typedef lc_rng<2147001325U, 715136305U> bcpl_rng;
84 root 1.8 typedef lc_rng< 1664525U, 1U> lavaux_janssens_rng;
85 root 1.3
86 root 1.1 template<typename T, int N, int k>
87 root 1.3 struct gfsr_rng
88 root 1.1 {
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 root 1.7 void seed (seed_t seed)
114 root 1.1 {
115 root 1.3 xorshift_rng rng;
116 root 1.1
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 root 1.3 typedef gfsr_rng<uint32_t, 250, 103> r250_rng;
139     typedef gfsr_rng<uint32_t, 521, 168> r521_rng;
140 root 1.1
141     // freeciv uses this one, so it's good enough for us :)
142 root 1.8 // (also known as mitchell moore generator
143 root 1.3 typedef gfsr_rng<uint32_t, 55, 24> freeciv_rng;
144 root 1.1
145     // this one should be high quality, but is slightly slower than tausworthe
146 root 1.3 struct r250521_rng
147 root 1.1 {
148 root 1.3 r250_rng r250;
149     r521_rng r521;
150 root 1.1
151     void seed (uint32_t seed);
152     uint32_t next ();
153     };
154    
155 root 1.8 /////////////////////////////////////////////////////////////////////////////
156    
157 root 1.5 // this is actually an adaptor that provides different
158     // distributions of random numbers.
159 root 1.1 template<class generator>
160     struct random_number_generator : generator
161     {
162 root 1.2 random_number_generator ()
163     {
164     }
165    
166 root 1.7 random_number_generator (seed_t seed)
167 root 1.2 {
168     this->seed (seed);
169     }
170    
171 root 1.1 // 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 root 1.3 uint32_t get_u32 ();
188     uint64_t get_u64 ();
189     float get_float ();
190     double get_double ();
191    
192 root 1.1 // return a number within the half-open interval [0..1[
193 root 1.3 double operator () ()
194 root 1.1 {
195 root 1.3 return get_double ();
196 root 1.1 }
197    
198 root 1.3 uint32_t poisson (double mean);
199 root 1.1
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 root 1.3 typedef random_number_generator<freeciv_rng> rand_gen;
207 root 1.1
208 root 1.2 // used when we often seed
209 root 1.3 typedef random_number_generator<tausworthe_rng> seedable_rand_gen;
210 root 1.2
211 root 1.1 extern rand_gen rndm, rmg_rndm;
212    
213     #endif
214