Skip to main content

trueno_gpu/testing/stress/
rng.rs

1//! Simple PCG32 RNG for stress testing.
2//!
3//! Used when the `simular` feature is not enabled.
4
5/// Simple PCG32 RNG for stress testing (no external deps in core)
6/// Used when simular feature is not enabled
7#[derive(Debug, Clone)]
8pub struct StressRng {
9    state: u64,
10    inc: u64,
11}
12
13impl StressRng {
14    /// Create new RNG with seed
15    #[must_use]
16    pub fn new(seed: u64) -> Self {
17        let mut rng = Self {
18            state: 0,
19            inc: (seed << 1) | 1,
20        };
21        rng.next_u32();
22        rng.state = rng.state.wrapping_add(seed);
23        rng.next_u32();
24        rng
25    }
26
27    /// Generate next u32
28    pub fn next_u32(&mut self) -> u32 {
29        let old_state = self.state;
30        self.state = old_state
31            .wrapping_mul(6_364_136_223_846_793_005)
32            .wrapping_add(self.inc);
33        let xorshifted = (((old_state >> 18) ^ old_state) >> 27) as u32;
34        let rot = (old_state >> 59) as u32;
35        (xorshifted >> rot) | (xorshifted << ((!rot).wrapping_add(1) & 31))
36    }
37
38    /// Generate next u64
39    pub fn next_u64(&mut self) -> u64 {
40        let high = self.next_u32() as u64;
41        let low = self.next_u32() as u64;
42        (high << 32) | low
43    }
44
45    /// Generate f32 in [0, 1)
46    pub fn gen_f32(&mut self) -> f32 {
47        (self.next_u32() as f64 / u32::MAX as f64) as f32
48    }
49
50    /// Generate u32 in range [min, max)
51    pub fn gen_range_u32(&mut self, min: u32, max: u32) -> u32 {
52        if max <= min {
53            return min;
54        }
55        let range = max - min;
56        min + (self.next_u32() % range)
57    }
58}