infinity_sampler/
rate.rs

1use core::hint::unreachable_unchecked;
2
3/// A simple sampler.
4///
5/// ```
6/// use infinity_sampler::SamplingRate;
7///
8/// let mut sampler = SamplingRate::new(2);
9/// assert_eq!(sampler.step(), false);
10/// assert_eq!(sampler.step(), true);
11/// assert_eq!(sampler.step(), false);
12/// assert_eq!(sampler.step(), true);
13///
14/// sampler.div(2);
15/// assert_eq!(sampler.step(), false);
16/// assert_eq!(sampler.step(), false);
17/// assert_eq!(sampler.step(), false);
18/// assert_eq!(sampler.step(), true);
19/// assert_eq!(sampler.step(), false);
20/// assert_eq!(sampler.step(), false);
21/// assert_eq!(sampler.step(), false);
22/// assert_eq!(sampler.step(), true);
23///
24#[derive(Copy, Clone)]
25pub struct SamplingRate {
26    divisor: u32,
27    counter: u32,
28}
29
30impl SamplingRate {
31    pub const fn new(divisor: u32) -> Self {
32        assert!(divisor > 0);
33        Self {
34            divisor,
35            counter: 0,
36        }
37    }
38
39    /// Returns true if the sampler should sample.
40    pub fn step(&mut self) -> bool {
41        if self.divisor == 0 {
42            unsafe { unreachable_unchecked() };
43        }
44        self.counter += 1;
45        self.counter %= self.divisor;
46        self.counter == 0
47    }
48
49    /// Reduce the sampling rate by a ratio.
50    pub fn div(&mut self, ratio: u32) {
51        assert!(ratio > 0);
52        self.divisor *= ratio;
53    }
54
55    pub fn divisor(&self) -> u32 {
56        self.divisor
57    }
58}