use num::arithmetic::traits::Parity;
use num::random::geometric::SimpleRational;
use num::random::{random_unsigneds_less_than, RandomUnsignedsLessThan};
use rand::Rng;
use rand_chacha::ChaCha20Rng;
use random::Seed;
#[derive(Clone, Debug)]
pub struct RandomBools {
rng: ChaCha20Rng,
x: u32,
bits_left: u8,
}
impl Iterator for RandomBools {
type Item = bool;
#[inline]
fn next(&mut self) -> Option<bool> {
if self.bits_left == 0 {
self.x = self.rng.gen();
self.bits_left = 31;
} else {
self.x >>= 1;
self.bits_left -= 1;
}
Some(self.x.odd())
}
}
#[inline]
pub fn random_bools(seed: Seed) -> RandomBools {
RandomBools {
rng: seed.get_rng(),
x: 0,
bits_left: 0,
}
}
#[derive(Clone, Debug)]
pub struct WeightedRandomBools {
numerator: u64,
xs: RandomUnsignedsLessThan<u64>,
}
impl Iterator for WeightedRandomBools {
type Item = bool;
#[inline]
fn next(&mut self) -> Option<bool> {
Some(self.xs.next().unwrap() < self.numerator)
}
}
pub fn weighted_random_bools(
seed: Seed,
p_numerator: u64,
p_denominator: u64,
) -> WeightedRandomBools {
assert!(p_numerator <= p_denominator);
let p = SimpleRational::new(p_numerator, p_denominator);
WeightedRandomBools {
numerator: p.n,
xs: random_unsigneds_less_than(seed, p.d),
}
}