Oregami
Repositories/oxedyne/ore

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.
4pub struct Rng {
5 state: u64,
6}
7
8impl 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}