java_utils/
util.rs

1use std::num::Wrapping;
2
3/// A `java.util.Random` implementation that implements the logic from Java in pure Rust.
4pub 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    /// Create a new `Random` object from the given seed
13    pub fn new(seed: u64) -> Self {
14        Self {
15            seed: Wrapping((seed ^ 0x0005_DEEC_E66D) & ((1 << 48) - 1)),
16        }
17    }
18    /// Return a new number with the given amount of bits
19    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    /// Return a new int
26    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}