ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/include/rng.h
Revision: 1.5
Committed: Mon Oct 25 11:35:14 2010 UTC (13 years, 7 months ago) by root
Content type: text/plain
Branch: MAIN
Changes since 1.4: +2 -2 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     * Copyright (©) 2010 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     // P. L'Ecuyer, “Maximally Equidistributed Combined Tausworthe Generators”, Mathematics of Computation, 65, 213 (1996), 203–213.
29     // http://www.iro.umontreal.ca/~lecuyer/myftp/papers/tausme.ps
30     // http://www.iro.umontreal.ca/~lecuyer/myftp/papers/tausme2.ps
31 root 1.3 struct tausworthe_rng
32 root 1.1 {
33     uint32_t state [4];
34    
35     void seed (uint32_t seed);
36     uint32_t next ();
37     };
38    
39     // Xorshift RNGs, George Marsaglia
40     // http://www.jstatsoft.org/v08/i14/paper
41     // this one is about 40% faster than the tausworthe one above (i.e. not much),
42     // despite the inlining, and has the issue of only creating 2**32-1 numbers.
43     // see also http://www.iro.umontreal.ca/~lecuyer/myftp/papers/xorshift.pdf
44 root 1.3 struct xorshift_rng
45 root 1.1 {
46     uint32_t x, y;
47    
48     void seed (uint32_t seed)
49     {
50 root 1.4 x = seed ? seed : 0xdeadbeef;
51 root 1.1 y = x * 69069U;
52     }
53    
54     uint32_t next ()
55     {
56     uint32_t t = x ^ (x << 10);
57     x = y;
58     y = y ^ (y >> 13) ^ t ^ (t >> 10);
59     return y;
60     }
61     };
62    
63 root 1.3 template<uint32_t A, uint32_t B>
64     struct lc_rng
65     {
66     uint32_t x;
67    
68     void seed (uint32_t seed)
69     {
70     x = seed;
71     }
72    
73     uint32_t next ()
74     {
75     x = x * A + B;
76     return x;
77     }
78     };
79    
80     typedef lc_rng<3039177861U, 0> borosh_niederreiter_rng;
81     typedef lc_rng<2147001325U, 715136305U> bcpl_rng;
82    
83 root 1.1 template<typename T, int N, int k>
84 root 1.3 struct gfsr_rng
85 root 1.1 {
86     int i;
87     T x[N];
88    
89     // rng must have same bitwidth as T
90     template<typename RNG>
91     void seed_rng (RNG rng)
92     {
93     i = N;
94    
95     do
96     x [--i] = rng.next ();
97     while (i > sizeof (T) * 8);
98    
99     T m = 1;
100    
101     do
102     {
103     x [--i] = (rng.next () | m) & ~(m - 1);
104     m <<= 1;
105     }
106     while (i);
107     }
108    
109     // actually should subclass to gfsr32... :)
110     void seed (uint32_t seed)
111     {
112 root 1.3 xorshift_rng rng;
113 root 1.1
114     rng.seed (seed);
115     this->seed_rng (rng);
116     }
117    
118     T next ()
119     {
120     int j = i + (k - N);
121    
122     if (j < 0)
123     j += N;
124    
125     T v = (x [i] ^= x [j]);
126    
127     i = (i ? i : N) - 1;
128    
129     return v;
130     }
131     };
132    
133     // these are about 2-3 times faster than tausworthe, non-inlined,
134     // and likely of higher quality.
135 root 1.3 typedef gfsr_rng<uint32_t, 250, 103> r250_rng;
136     typedef gfsr_rng<uint32_t, 521, 168> r521_rng;
137 root 1.1
138     // freeciv uses this one, so it's good enough for us :)
139 root 1.3 typedef gfsr_rng<uint32_t, 55, 24> freeciv_rng;
140 root 1.1
141     // this one should be high quality, but is slightly slower than tausworthe
142 root 1.3 struct r250521_rng
143 root 1.1 {
144 root 1.3 r250_rng r250;
145     r521_rng r521;
146 root 1.1
147     void seed (uint32_t seed);
148     uint32_t next ();
149     };
150    
151 root 1.5 // this is actually an adaptor that provides different
152     // distributions of random numbers.
153 root 1.1 template<class generator>
154     struct random_number_generator : generator
155     {
156 root 1.2 random_number_generator ()
157     {
158     }
159    
160     random_number_generator (uint32_t seed)
161     {
162     this->seed (seed);
163     }
164    
165 root 1.1 // uniform distribution, [0 .. num - 1]
166     uint32_t operator ()(uint32_t num)
167     {
168     return !is_constant (num) ? get_range (num) // non-constant
169     : num & (num - 1) ? (this->next () * (uint64_t)num) >> 32U // constant, non-power-of-two
170     : this->next () & (num - 1); // constant, power-of-two
171     }
172    
173     // return a number within the closed interval [min .. max], max can be >, < or == min.
174     int operator () (int r_min, int r_max)
175     {
176     return is_constant (r_min <= r_max) && r_min <= r_max
177     ? r_min + operator ()(r_max - r_min + 1)
178     : get_range (r_min, r_max);
179     }
180    
181 root 1.3 uint32_t get_u32 ();
182     uint64_t get_u64 ();
183     float get_float ();
184     double get_double ();
185    
186 root 1.1 // return a number within the half-open interval [0..1[
187 root 1.3 double operator () ()
188 root 1.1 {
189 root 1.3 return get_double ();
190 root 1.1 }
191    
192 root 1.3 uint32_t poisson (double mean);
193 root 1.1
194     protected:
195     uint32_t get_range (uint32_t r_max);
196     int get_range (int r_min, int r_max);
197     };
198    
199     // the default rng used in the game
200 root 1.3 typedef random_number_generator<freeciv_rng> rand_gen;
201 root 1.1
202 root 1.2 // used when we often seed
203 root 1.3 typedef random_number_generator<tausworthe_rng> seedable_rand_gen;
204 root 1.2
205 root 1.1 extern rand_gen rndm, rmg_rndm;
206    
207     #endif
208