wybr 0.0.6

Collection of preferential voting methods
Documentation
pub struct Prng {
    state: u64,
    sealed: bool,
    states: Vec<(u64, bool)>,
}

//PCG 32 with inc=1, that is stream #0
//Based on Melissa E. O'Neill. PCG: A Family of Simple Fast Space-Efficient Statistically Good
//Algorithms for Random Number Generation. Harvey Mudd College, 2014.
impl Prng {
    pub fn new(seed: u32) -> Prng {
        let mut ans = Prng {
            state: 0,
            sealed: true,
            states: Vec::new(),
        };
        ans.next();
        ans.state = ans.state.wrapping_add(seed as u64);
        ans.next();
        ans.sealed = true;
        ans
    }
    pub fn sealed(&self) -> bool {
        self.sealed
    }
    pub fn next(&mut self) -> u32 {
        let prv = self.state;
        //Push generator
        self.state = (prv.wrapping_mul(6_364_136_223_846_793_005)).wrapping_add(1);
        self.sealed = false;
        //Make output
        let xorshifted = (((prv >> 18) ^ prv) >> 27) as u32;
        let rot = (prv >> 59) as u32;
        (xorshifted >> rot) | (xorshifted << ((rot.wrapping_neg()) & 31))
    }
    pub fn push(&mut self) {
        self.states.push((self.state, self.sealed));
    }
    pub fn pop(&mut self) -> Option<()> {
        if let Some(old) = self.states.pop() {
            self.state = old.0;
            self.sealed = old.1;
            Some(())
        } else {
            None
        }
    }
    pub fn random_usindex(&mut self, up_to: usize) -> usize {
        //This assumes usize is u64 or less
        assert!(std::mem::size_of::<usize>() <= 64);
        assert!(up_to > 0);
        if up_to == 1 {
            0
        } else {
            let thresh = up_to.wrapping_neg() % up_to;
            loop {
                let mut p = self.next() as usize;
                //TODO: This is super dumb, separate streams shell be used
                if up_to > 4_294_967_296 {
                    p <<= 32;
                    p += self.next() as usize;
                }
                //rejection method:
                if p >= thresh {
                    break p % up_to;
                }
            }
        }
    }
    pub fn only_or_random<T: Copy>(&mut self, from: &[T]) -> Option<T> {
        if from.is_empty() {
            None
        } else {
            Some(from[self.random_usindex(from.len())])
        }
    }
    pub fn shuffle<T>(&mut self, x: &mut [T]) {
        if !x.is_empty() {
            for e in 0..(x.len() - 1) {
                let ee = e + self.random_usindex(x.len() - e);
                x.swap(e, ee);
            }
        }
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    #[test]
    fn cmp_with_c() {
        let mut x = Prng::new(21);
        let x_out: Vec<u32> = (0..6).map(|_| x.next()).collect();
        //For seed=21 & stream "0" (streams are *2+1 because stream number must be odd)
        let pcg32_c_out = vec![
            4046551126, 3645130801, 1491492233, 2234036793, 669229171, 981735442,
        ];
        assert_eq!(x_out, pcg32_c_out);

        let mut x = Prng::new(33198495);
        let x_out: Vec<u32> = (0..6).map(|_| x.next()).collect();
        //For seed=33198495 & stream "0" (streams are *2+1 because stream number must be odd)
        let pcg32_c_out = vec![
            3221354117, 560577576, 1464394025, 77867303, 6303390, 439113613,
        ];
        assert_eq!(x_out, pcg32_c_out);
    }
    #[test]
    fn upto() {
        let mut x = Prng::new(912);
        let n = 3;
        let mut cc: Vec<u64> = std::iter::repeat(0).take(n).collect();
        for _ in 0..100 {
            cc[x.random_usindex(n)] += 1;
        }
        assert_eq!(cc[1], 35); //Will change with seed
        assert_eq!(x.sealed(), false);
    }
    #[test]
    fn random_element() {
        let mut x = Prng::new(71);
        let vv = vec!["Hello", "or", "something"];
        assert_eq!(x.only_or_random(&vv).unwrap(), "or");
        let ev: Vec<i64> = vec![];
        assert_eq!(x.only_or_random(&ev), None);
        assert_eq!(x.sealed(), false);
    }
    #[test]
    fn only_element() {
        let mut y = Prng::new(99);
        let eo = vec!["only"];
        assert_eq!(y.only_or_random(&eo), Some("only"));
        assert_eq!(y.sealed(), true);
    }
    #[test]
    fn shuffle() {
        let mut x = Prng::new(81);
        let mut v: Vec<u32> = vec![];
        x.shuffle(&mut v);
        assert!(x.sealed());

        v.push(1);
        x.shuffle(&mut v);
        assert!(x.sealed());

        v.push(2);
        x.shuffle(&mut v);
        assert!(!x.sealed());
        assert_eq!(v, vec![2, 1]);
    }
    #[test]
    fn state_stack() {
        let mut x = Prng::new(99);
        x.push();
        let a = x.next();
        for _ in 0..100 {
            x.next();
        }
        x.push();
        let b = x.next();
        for _ in 0..100 {
            x.next();
        }
        x.pop().unwrap();
        assert!(!x.sealed());
        assert_eq!(b, x.next());
        x.pop().unwrap();
        assert!(x.sealed());
        assert_eq!(a, x.next());
        assert!(x.pop().is_none());
    }
}