1use std::num::Wrapping;
2
3pub struct Random {
5 seed: Wrapping<u64>,
6}
7
8const DEECE: Wrapping<u64> = Wrapping(0x0005_DEEC_E66D);
9const BL: Wrapping<u64> = Wrapping(0xB);
10
11impl Random {
12 pub fn new(seed: u64) -> Self {
14 Self {
15 seed: Wrapping((seed ^ 0x0005_DEEC_E66D) & ((1 << 48) - 1)),
16 }
17 }
18 pub fn next(&mut self, bits: u32) -> u32 {
20 self.seed = Wrapping((self.seed * DEECE + BL).0 & ((1 << 48) - 1));
21
22 (self.seed.0 >> (48 - bits)) as u32
23 }
24 #[allow(clippy::cast_lossless)]
25 pub fn next_int(&mut self, bound: u32) -> u32 {
27 assert!(bound > 0, "bound must be positive");
28 if bound.count_ones() == 1 {
29 ((bound as u64 * self.next(31) as u64) >> 31) as u32
30 } else {
31 let mut bits = self.next(31);
32 let mut val = bits % bound;
33 while bits + bound < val + 1 {
34 bits = self.next(31);
35 val = bits % bound;
36 }
37 val
38 }
39 }
40}