Skip to main content

common_traits/
rnd.rs

1/// A generic Random number generator
2///
3/// # Example
4///
5/// ```rust
6/// use common_traits::{Rng, RngNext};
7///
8/// pub struct Xorshift64(u64);
9///
10/// impl Rng for Xorshift64 {
11///     type Seed = u64;
12///
13///     fn new(seed: u64) -> Self {
14///         Self(seed.saturating_add(1))
15///     }
16/// }
17///
18/// impl RngNext<u64> for Xorshift64 {
19///     fn next_inner(&mut self) -> u64 {
20///         self.0 ^= self.0 << 13;
21///         self.0 ^= self.0 >> 7;
22///         self.0 ^= self.0 << 17;
23///         self.0
24///     }
25/// }
26///
27/// impl RngNext<f64> for Xorshift64 {
28///     fn next_inner(&mut self) -> f64 {
29///         let v: u64 = (self.next::<u64>() >> 11) | (1023 << 52);
30///         let r: f64 = f64::from_le_bytes(v.to_le_bytes());
31///         r - 1f64
32///     }
33/// }
34/// ```
35pub trait Rng {
36    type Seed;
37
38    /// Instantiate a new Rng making no assumptions on its seed.
39    fn new(seed: Self::Seed) -> Self;
40
41    /// automatic dispatching of the implementation, no need to re-implement
42    #[inline(always)]
43    fn next<T>(&mut self) -> T
44    where
45        Self: RngNext<T>,
46    {
47        <Self as RngNext<T>>::next_inner(self)
48    }
49}
50
51/// Implementation of a specific type generation for a Rng
52///
53/// # Example
54///
55/// ```rust
56/// use common_traits::{Rng, RngNext};
57///
58/// pub struct Xorshift64(u64);
59///
60/// impl Rng for Xorshift64 {
61///     type Seed = u64;
62///     fn new(seed: u64) -> Self {
63///         Self(seed.saturating_add(1))
64///     }
65/// }
66///
67/// impl RngNext<u64> for Xorshift64 {
68///     fn next_inner(&mut self) -> u64 {
69///         self.0 ^= self.0 << 13;
70///         self.0 ^= self.0 >> 7;
71///         self.0 ^= self.0 << 17;
72///         self.0
73///     }
74/// }
75///
76/// impl RngNext<f64> for Xorshift64 {
77///     fn next_inner(&mut self) -> f64 {
78///         let v: u64 = (self.next::<u64>() >> 11) | (1023 << 52);
79///         let r: f64 = f64::from_le_bytes(v.to_le_bytes());
80///         r - 1f64
81///     }
82/// }
83/// ```
84pub trait RngNext<T> {
85    fn next_inner(&mut self) -> T;
86}