oxedyne/ore/oracle/src/random.rs
1.1 KiB, 1 run
created by r2848102244:91, which is this file's identity for as long as the history lasts, whatever it is later renamed to
download · who wrote it · its history
| 1 | //! A tiny deterministic generator, so that a failing seed can be replayed. |
| 2 | |
| 3 | /// SplitMix64. |
| 4 | pub struct Rng { |
| 5 | state: u64, |
| 6 | } |
| 7 | |
| 8 | impl Rng { |
| 9 | /// Creates a generator from a seed. |
| 10 | pub fn new(seed: u64) -> Self { |
| 11 | Self { state: seed.wrapping_add(0x9E3779B97F4A7C15) } |
| 12 | } |
| 13 | |
| 14 | /// The next 64 bits. |
| 15 | pub fn next(&mut self) -> u64 { |
| 16 | self.state = self.state.wrapping_add(0x9E3779B97F4A7C15); |
| 17 | let mut z = self.state; |
| 18 | z = (z ^ (z >> 30)).wrapping_mul(0xBF58476D1CE4E5B9); |
| 19 | z = (z ^ (z >> 27)).wrapping_mul(0x94D049BB133111EB); |
| 20 | z ^ (z >> 31) |
| 21 | } |
| 22 | |
| 23 | /// A number below `n`, or zero when `n` is zero. |
| 24 | pub fn below(&mut self, n: usize) -> usize { |
| 25 | if n == 0 { |
| 26 | 0 |
| 27 | } else { |
| 28 | (self.next() % n as u64) as usize |
| 29 | } |
| 30 | } |
| 31 | |
| 32 | /// A number in `lo..=hi`. |
| 33 | pub fn between(&mut self, lo: usize, hi: usize) -> usize { |
| 34 | if hi <= lo { |
| 35 | lo |
| 36 | } else { |
| 37 | lo + self.below(hi - lo + 1) |
| 38 | } |
| 39 | } |
| 40 | |
| 41 | /// True with probability `num/den`. |
| 42 | pub fn chance(&mut self, num: u64, den: u64) -> bool { |
| 43 | self.next() % den < num |
| 44 | } |
| 45 | |
| 46 | /// Shuffles a slice in place. |
| 47 | pub fn shuffle<T>(&mut self, v: &mut [T]) { |
| 48 | for i in (1..v.len()).rev() { |
| 49 | let j = self.below(i + 1); |
| 50 | v.swap(i, j); |
| 51 | } |
| 52 | } |
| 53 | } |