simu

Ice hockey final standings simulator
git clone https://git.inz.fi/simu
Log | Files | Refs

rand.rs (1698B)


      1 pub trait RandOutput:
      2     Copy + Ord + std::ops::Sub<Output = Self> + std::fmt::Debug + Default
      3 {
      4 }
      5 impl<T: Copy + Ord + std::ops::Sub<Output = Self> + std::fmt::Debug + Default> RandOutput for T {}
      6 
      7 pub trait Rand: Copy {
      8     type Output: RandOutput;
      9     const MAX: Self::Output;
     10 
     11     fn rand(&mut self) -> Self::Output;
     12 }
     13 
     14 pub trait YesNo<T: RandOutput>: Rand<Output = T> {
     15     fn yesno(&mut self, limit: T) -> (bool, bool) {
     16         let r = self.rand();
     17         (r < limit, Self::MAX - r < limit)
     18     }
     19 }
     20 
     21 impl<T, R> YesNo<T> for R
     22 where
     23     T: RandOutput,
     24     R: Rand<Output = T>,
     25 {
     26 }
     27 
     28 #[derive(Clone, Copy)]
     29 pub struct Lehmer {
     30     state: std::num::Wrapping<u128>,
     31 }
     32 
     33 impl Default for Lehmer {
     34     fn default() -> Self {
     35         let now = std::time::SystemTime::now()
     36             .duration_since(std::time::SystemTime::UNIX_EPOCH)
     37             .expect("Failed to initialize random");
     38         Self::new(u128::from(now.subsec_nanos()) << 64 | u128::from(now.as_secs()) | 1)
     39     }
     40 }
     41 
     42 impl Lehmer {
     43     pub fn new(seed: u128) -> Self {
     44         Self {
     45             state: std::num::Wrapping(seed),
     46         }
     47     }
     48 
     49     pub fn new_with<T: Into<u128>>(other: &mut impl Rand<Output = T>) -> Self {
     50         Self::new(
     51             other.rand().into() << 96
     52                 ^ other.rand().into() << 64
     53                 ^ other.rand().into() << 32
     54                 ^ other.rand().into()
     55                 | 1,
     56         )
     57     }
     58 }
     59 
     60 impl Rand for Lehmer {
     61     type Output = u32;
     62     const MAX: Self::Output = Self::Output::MAX;
     63 
     64     #[allow(clippy::cast_possible_truncation)]
     65     fn rand(&mut self) -> Self::Output {
     66         self.state *= 0xda94_2042_e4dd_58b5;
     67         (self.state >> 64).0 as Self::Output
     68     }
     69 }