rand_python/mersenne_twister.rs
1/*
2 Rust port of the original mt19937ar Mersenne Twister.
3
4 Porting, additional comments and documentation by Ronald Volgers.
5
6 The original copyright notice and BSD 3-clause license is reproduced below.
7
8 ---
9
10 Copyright (C) 1997 - 2002, Makoto Matsumoto and Takuji Nishimura,
11 All rights reserved.
12
13 Redistribution and use in source and binary forms, with or without
14 modification, are permitted provided that the following conditions
15 are met:
16
17 1. Redistributions of source code must retain the above copyright
18 notice, this list of conditions and the following disclaimer.
19
20 2. Redistributions in binary form must reproduce the above copyright
21 notice, this list of conditions and the following disclaimer in the
22 documentation and/or other materials provided with the distribution.
23
24 3. The names of its contributors may not be used to endorse or promote
25 products derived from this software without specific prior written
26 permission.
27
28 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
29 "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
30 LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
31 A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
32 CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
33 EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
34 PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
35 PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
36 LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
37 NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
38 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
39 */
40
41use std::cmp::max;
42use std::fmt;
43
44const N: usize = 624;
45const M: usize = 397;
46const MATRIX_A: u32 = 0x9908b0df;
47const UPPER_MASK: u32 = 0x80000000;
48const LOWER_MASK: u32 = 0x7fffffff;
49
50/// `self.index` is set to this value after seeding. It is also encountered during normal
51/// operation, when a block of random numbers has been consumed and `genrand_int32` needs
52/// to generate a new one before returning the next random number.
53const INITIAL_INDEX: usize = N;
54
55/// `self.index` is set to this value at creation time. It indicates the random number
56/// generator has not been seeded. If this value is encountered when trying to generate
57/// a random number, the implementation will panic.
58const UNSEEDED_INDEX: usize = N + 1;
59
60/// Implementation of [Mersenne Twister] (`mt19937ar`).
61///
62/// This is a direct Rust port of the C implementation known as [`mt19937ar.c`].
63///
64/// It tries to stay as close as possible to the original in terms of function naming
65/// and overall interface. This makes it easier to port libraries that use the Mersenne
66/// Twister internally.
67///
68/// The code remains functionally the same but has been cleaned up and re-commented
69/// to reflect my own understanding of the original code and algorithm. Some comments from
70/// the original have been omitted. Errors are mine.
71///
72/// [Mersenne Twister]: http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/emt.html
73/// [`mt19937ar.c`]: http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/MT2002/CODES/mt19937ar.c
74#[derive(Clone)]
75pub struct MersenneTwister {
76 index: usize,
77 state: [u32; N],
78}
79
80impl fmt::Debug for MersenneTwister {
81 fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
82 fmt.debug_struct("MersenneTwister")
83 .field("index", &self.index)
84 .field("state", &&self.state[..])
85 .finish()
86 }
87}
88
89impl MersenneTwister {
90 /// Creates a new, unseeded random number generator.
91 ///
92 /// Seed it using [`init_by_array`], [`init_genrand`], or the deprecated and buggy
93 /// [`sgenrand`].
94 ///
95 /// Trying to generate random numbers without seeding will cause a panic.
96 /// The upstream implementation automatically seeds the generator using a hardcoded
97 /// seed instead. To use that seed, you can manually call `init_genrand(5489)`.
98 ///
99 /// [`init_by_array`]: #method.init_by_array
100 /// [`init_genrand`]: #method.init_genrand
101 /// [`sgenrand`]: #method.sgenrand
102 pub fn new() -> MersenneTwister {
103 MersenneTwister {
104 index: UNSEEDED_INDEX,
105 state: [0; N],
106 }
107 }
108
109 /// This is the core random number generation function that all the others are
110 /// based on.
111 ///
112 /// It generates a random `u32` value.
113 pub fn genrand_int32(&mut self) -> u32 {
114
115 let mt = &mut self.state;
116
117 if self.index >= N {
118
119 // This deviates from the original implementation, which will simply call
120 // init_genrand(5489) in this situation instead.
121 assert!(self.index != UNSEEDED_INDEX,
122 "random number generator must be seeded before use");
123
124 #[cfg(feature = "prefetch")]
125 #[cfg(target_feature = "sse")]
126 unsafe {
127 // 64 is min possible cache line size
128 for i in (0..N).step_by(64) {
129 core::arch::x86_64::_mm_prefetch((mt as *const _ as *const i8).add(i), core::arch::x86_64::_MM_HINT_T2);
130 }
131 }
132
133 // Produce an entire block of outputs at once.
134 // The calculation for each entry is the same, but the loop is split into
135 // three separate parts according to which indexing calculations will wrap,
136 // to avoid needing modulo operations or conditionals in the loop itself.
137
138 // Process initial items, where kk+M and kk+1 both don't wrap
139 for kk in 0..(N - M) {
140 let y = (mt[kk] & UPPER_MASK) | (mt[kk + 1] & LOWER_MASK);
141 mt[kk] = mt[kk + M] ^ (y >> 1) ^ ((y & 1) * MATRIX_A);
142 }
143
144 // Process next items, where kk+M wraps but kk+1 doesn't
145 for kk in (N - M)..(N - 1) {
146 let y = (mt[kk] & UPPER_MASK) | (mt[kk + 1] & LOWER_MASK);
147 mt[kk] = mt[kk + M - N] ^ (y >> 1) ^ ((y & 1) * MATRIX_A);
148 }
149
150 // Process final item, where both kk+M and kk+1 wrap
151 let kk = N - 1;
152 let y = (mt[kk] & UPPER_MASK) | (mt[kk + 1 - N] & LOWER_MASK);
153 mt[kk] = mt[kk + M - N] ^ (y >> 1) ^ ((y & 1) * MATRIX_A);
154
155 self.index = 0;
156 }
157
158 let y = mt[self.index];
159 self.index += 1;
160
161 // This is the "tempering" operation to improve the distribution of bits in
162 // the output. This transformation is *not* intended to prevent recovery of
163 // the state from the output; in fact this transformation is fully invertible
164 // so it does nothing to prevent that.
165 let mut y = y;
166 y ^= y >> 11;
167 y ^= (y << 7) & 0x9d2c5680;
168 y ^= (y << 15) & 0xefc60000;
169 y ^= y >> 18;
170 y
171 }
172
173 /// Reset the random number generator with a seed of arbitary length.
174 ///
175 /// The seed is specified as a slice of `u32` values. It cannot be specified as an
176 /// iterator because if the seed is shorter than 624 values each value may
177 /// be accessed more than once.
178 pub fn init_by_array(&mut self, init_key: &[u32]) {
179
180 // Reset self.state to some decently varied constant data.
181 // This also sets self.index = N, which ensures that genrand_int32 will run
182 // its random number generation loop when it is called for the first time
183 // after seeding.
184 self.init_genrand(19650218);
185
186 let mt = &mut self.state;
187
188 // Cycles through 1..N, which has length N-1, not N.
189 // The zero index is "skipped over" and handled specially.
190 let mut i: usize = 1;
191
192 // Cycles through the valid indices of init_key.
193 let mut j: usize = 0;
194
195 for _ in 0..max(N, init_key.len()) {
196 let prev = mt[i - 1] ^ (mt[i - 1] >> 30);
197 mt[i] = (mt[i] ^ prev.wrapping_mul(1664525))
198 .wrapping_add(init_key[j])
199 .wrapping_add(j as u32);
200
201 i += 1;
202 if i >= N {
203 mt[0] = mt[N - 1];
204 i = 1;
205 }
206
207 j += 1;
208 if j >= init_key.len() {
209 j = 0;
210 }
211 }
212
213 for _ in 0..(N - 1) {
214 let prev = mt[i - 1] ^ (mt[i - 1] >> 30);
215 mt[i] = (mt[i] ^ prev.wrapping_mul(1566083941))
216 .wrapping_sub(i as u32);
217
218 i += 1;
219 if i >= N {
220 mt[0] = mt[N - 1];
221 i = 1;
222 }
223 }
224
225 mt[0] = 0x80000000;
226 }
227
228 /// Reset the random number generator using a single 32 bit seed.
229 ///
230 /// This is generally not recommended since it means all future output
231 /// of the random number generator can be reproduced by knowing, guessing,
232 /// or accidentally picking the same 32 bit seed value.
233 ///
234 /// If you want to seed the random number generator with more than 32 bits
235 /// of data, see [`init_by_array`].
236 ///
237 /// [`init_by_array`]: #method.init_by_array
238 pub fn init_genrand(&mut self, s: u32) {
239
240 let mt = &mut self.state;
241
242 mt[0] = s;
243
244 for i in 1..N {
245 let prev = mt[i - 1] ^ (mt[i - 1] >> 30);
246 mt[i] = prev.wrapping_mul(1812433253)
247 .wrapping_add(i as u32);
248 }
249
250 self.index = INITIAL_INDEX; // == N
251 }
252
253 /// Generates a random `value: f64` such that `0. <= value && value < 1.`,
254 /// using 53 bits of randomness (the maximum possible for a `f64` value).
255 pub fn genrand_res53(&mut self) -> f64 {
256
257 let a = self.genrand_int32() >> 5; // 32 - 5 = 27 bits
258 let b = self.genrand_int32() >> 6; // 32 - 6 = 26 bits
259
260 // This is essentially doing ((a << 26) + b) / 2**53, but combining
261 // a and b is done in floating point because on 32 bits systems the
262 // CPU often has native support for f64 but not u64.
263
264 // Combining a and b in a u64 instead of a f64 is about 25% faster in
265 // my testing, but changing anything about the generation of floating
266 // point numbers is extremely risky since even the smallest change
267 // can cause a number to be rounded up instead of down or vice versa
268 // in downstream calculations. So, let's just do it the way the original
269 // implementation does.
270
271 // Likewise, the multiplication-by-reciprocal instead of division is
272 // how it's done in the original code.
273
274 // 2**26 == 67108864
275 // 2**53 == 9007199254740992
276 (a as f64 * 67108864.0 + b as f64) * (1.0 / 9007199254740992.0)
277 }
278
279 /// Generates a random `value: i32` such that `0 <= value && value <= 0x7fffffff`.
280 ///
281 /// If you want a `u32`, see [`genrand_int32`].
282 ///
283 /// [`genrand_int32`]: #method.genrand_int32
284 pub fn genrand_int31(&mut self) -> i32 {
285 (self.genrand_int32() >> 1) as i32
286 }
287
288 /// Generates a random `value: f64` such that `0. <= value && value <= 1.`,
289 /// using 32 bits worth of randomness.
290 ///
291 /// If you want `value < 1` instead of `value <= 1`, see [`genrand_real2`]
292 /// (or [`genrand_res53`] if you also want the maximum amount of randomness).
293 ///
294 /// [`genrand_real2`]: #method.genrand_real2
295 /// [`genrand_res53`]: #method.genrand_res53
296 pub fn genrand_real1(&mut self) -> f64 {
297 // 4294967295 == 2**32 - 1
298 self.genrand_int32() as f64 / 4294967295.0
299 }
300
301 /// Generates a random `value: f64` such that `0. <= value && value < 1.`,
302 /// using 32 bits of randomness.
303 ///
304 /// If you want the maximum amount of randomness, see [`genrand_res53`].
305 ///
306 /// [`genrand_res53`]: #method.genrand_res53
307 pub fn genrand_real2(&mut self) -> f64 {
308 // 4294967296 == 2**32
309 self.genrand_int32() as f64 / 4294967296.0
310 }
311
312 /// Generates a random `value: f64` such that `0. < value && value < 1.`,
313 /// using 32 bits of randomness.
314 ///
315 /// If you want `0 <= value` instead of `0 < value`, see [`genrand_real2`]
316 /// (or [`genrand_res53`] if you also want the maximum amount of randomness).
317 ///
318 /// [`genrand_real2`]: #method.genrand_real2
319 /// [`genrand_res53`]: #method.genrand_res53
320 pub fn genrand_real3(&mut self) -> f64 {
321 // 4294967296 == 2**32
322 (self.genrand_int32() as f64 + 0.5) / 4294967296.0
323 }
324
325 /// Reset the random number generator using a single 32 bit seed.
326 ///
327 /// This old seed function can cause very poor quality random numbers and
328 /// is mainly included for historical purposes. It is only present in older
329 /// versions of the Mersenne Twister code base, not the `mt19937ar` version
330 /// this module is based on.
331 ///
332 /// Most software uses [`init_by_array`] or [`init_genrand`] instead, which were
333 /// introduced in the `mt19937ar` version.
334 ///
335 /// [`init_by_array`]: #method.init_by_array
336 /// [`init_genrand`]: #method.init_getrand
337 #[deprecated = "Can lead to very poor quality random numbers. \
338 Use `init_by_array` or `init_genrand` instead."]
339 pub fn sgenrand(&mut self, seed: u32) {
340
341 let mt = &mut self.state;
342
343 mt[0] = seed;
344
345 for i in 1..N {
346 mt[i] = mt[i - 1].wrapping_mul(69069);
347 }
348
349 }
350
351}