2020-08-21 05:27:26 +00:00
|
|
|
use std::cell::Cell;
|
|
|
|
|
2020-11-28 19:25:51 +00:00
|
|
|
/// Deterministic XorShift-based random number generator
|
2020-09-05 01:03:43 +00:00
|
|
|
pub struct RNG(Cell<(u64, u64, u64, u64)>);
|
|
|
|
|
2020-08-20 18:31:47 +00:00
|
|
|
impl RNG {
|
2020-08-21 05:27:26 +00:00
|
|
|
pub fn new(seed: i32) -> Self {
|
2020-09-05 01:03:43 +00:00
|
|
|
Self(Cell::new((seed as u64,
|
|
|
|
(seed as u64).wrapping_add(0x9e3779b97f4a7c15),
|
|
|
|
(seed as u64).wrapping_add(0xbdd3944475a73cf0),
|
|
|
|
0
|
|
|
|
)))
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn next_u64(&self) -> i32 {
|
|
|
|
let mut state = self.0.get();
|
2020-12-06 20:20:26 +00:00
|
|
|
let result = state.1.wrapping_mul(5).rotate_left(5).wrapping_mul(9);
|
2020-09-05 01:03:43 +00:00
|
|
|
let t = state.1 << 17;
|
|
|
|
|
|
|
|
state.2 ^= state.0;
|
|
|
|
state.3 ^= state.1;
|
|
|
|
state.1 ^= state.2;
|
|
|
|
state.0 ^= state.3;
|
|
|
|
|
|
|
|
state.2 ^= t;
|
2020-12-06 20:20:26 +00:00
|
|
|
state.3 = state.3.rotate_left(45);
|
2020-09-05 01:03:43 +00:00
|
|
|
|
|
|
|
self.0.replace(state);
|
|
|
|
result as i32
|
2020-08-20 18:31:47 +00:00
|
|
|
}
|
|
|
|
|
2020-09-05 04:26:01 +00:00
|
|
|
#[inline]
|
2020-08-21 05:27:26 +00:00
|
|
|
pub fn next(&self) -> i32 {
|
2020-09-05 01:03:43 +00:00
|
|
|
self.next_u64() as i32
|
2020-08-21 05:27:26 +00:00
|
|
|
}
|
|
|
|
|
2020-09-05 04:26:01 +00:00
|
|
|
#[inline]
|
2020-08-21 05:27:26 +00:00
|
|
|
pub fn next_u32(&self) -> u32 {
|
2020-09-05 01:03:43 +00:00
|
|
|
self.next_u64() as u32
|
2020-08-20 18:31:47 +00:00
|
|
|
}
|
|
|
|
|
2020-11-28 19:25:51 +00:00
|
|
|
pub fn dump_state(&self) -> (u64, u64, u64, u64) {
|
|
|
|
self.0.get()
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn load_state(&mut self, saved_state: (u64, u64, u64, u64)) {
|
|
|
|
self.0.replace(saved_state);
|
|
|
|
}
|
|
|
|
|
2020-08-21 05:27:26 +00:00
|
|
|
pub fn range(&self, range: std::ops::Range<i32>) -> i32 {
|
2020-09-05 01:03:43 +00:00
|
|
|
range.start.wrapping_add((self.next_u32() >> 2) as i32 % (range.end.wrapping_sub(range.start).wrapping_add(1)))
|
2020-08-20 18:31:47 +00:00
|
|
|
}
|
|
|
|
}
|
2020-12-06 20:20:26 +00:00
|
|
|
|
|
|
|
#[derive(Debug, Copy, Clone)]
|
|
|
|
pub struct Xoroshiro32PlusPlus(u16, u16);
|
|
|
|
|
|
|
|
impl Xoroshiro32PlusPlus {
|
|
|
|
pub fn new(seed: u32) -> Xoroshiro32PlusPlus {
|
|
|
|
Xoroshiro32PlusPlus(
|
|
|
|
(seed & 0xffff) as u16,
|
|
|
|
(seed >> 16 & 0xffff) as u16
|
|
|
|
)
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn next_u16(&mut self) -> u16 {
|
|
|
|
let mut result = (self.0.wrapping_add(self.1)).rotate_left(9).wrapping_add(self.0);
|
|
|
|
|
|
|
|
self.1 ^= self.0;
|
|
|
|
self.0 = self.0.rotate_left(13) ^ self.1 ^ (self.1 << 5);
|
|
|
|
self.1 = self.1.rotate_left(10);
|
|
|
|
|
|
|
|
result
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn dump_state(&self) -> u32 {
|
|
|
|
(self.0 as u32) | (self.1 as u32) << 16
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn load_state(&mut self, state: u32) {
|
|
|
|
self.0 = (state & 0xffff) as u16;
|
|
|
|
self.1 = ((state >> 16) & 0xffff) as u16;
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn range(&mut self, range: std::ops::Range<i32>) -> i32 {
|
|
|
|
let num = ((self.next_u16() as u32) << 16 | self.next_u16() as u32) >> 2;
|
|
|
|
range.start.wrapping_add(num as i32 % (range.end.wrapping_sub(range.start).wrapping_add(1)))
|
|
|
|
}
|
|
|
|
}
|