1
0
Fork 0
mirror of https://github.com/doukutsu-rs/doukutsu-rs synced 2024-11-09 15:54:24 +00:00
doukutsu-rs/src/rng.rs

64 lines
1.5 KiB
Rust
Raw Normal View History

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-09-05 04:26:01 +00:00
#[inline]
2020-09-05 01:03:43 +00:00
fn rol64(x: u64, shift: u64) -> u64
{
if shift == 0 || shift == 64 {
x
} else {
(x << shift) | (x >> (64 - shift))
}
}
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();
let result = rol64(state.1.wrapping_mul(5), 7).wrapping_mul(9);
let t = state.1 << 17;
state.2 ^= state.0;
state.3 ^= state.1;
state.1 ^= state.2;
state.0 ^= state.3;
state.2 ^= t;
state.3 = rol64(state.3, 45);
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
}
}