#[cfg(test)] extern crate bit_vec;
extern crate rand;
pub use iter::ShuffledIterGen;
use std::num::Wrapping;
use rand::Rng;
mod iter;
#[allow(non_camel_case_types)]
type w32 = Wrapping<u32>;
#[inline(always)]
fn w32(u: u32) -> w32 {
Wrapping(u)
}
#[inline(always)]
fn shl_ignore(slf: u32, rhs: u32) -> u32 {
if rhs >= 32 { 0 } else { slf << rhs }
}
#[inline(always)]
fn gen_factor<R: Rng>(rng: &mut R) -> w32 {
w32((rng.next_u32() << 1) | 1)
}
#[inline(always)]
fn gen_xor_op<R: Rng>(rng: &mut R) -> w32 {
w32(rng.next_u32())
}
#[derive(Copy, Clone, Debug)]
pub struct ShuffledIter {
max: w32,
mask: w32,
index: w32,
count: w32,
f1: w32,
f2: w32,
x1: w32,
x2: w32,
done: bool,
}
impl ShuffledIter {
fn new<R: Rng>(max: u32, rng: &mut R) -> ShuffledIter {
let bits = 32 - max.leading_zeros();
let max = w32(max);
let mask = w32(shl_ignore(1, bits)) - w32(1);
ShuffledIter {
max: max,
mask: mask,
index: w32(rng.next_u32()),
count: w32(0),
f1: gen_factor(rng),
f2: gen_factor(rng),
x1: gen_xor_op(rng),
x2: gen_xor_op(rng),
done: false,
}
}
#[inline(always)]
fn next_value(&mut self) -> u32 {
self.index = self.index + w32(1);
self.count = self.count + w32(1);
let mut val = self.calc(self.index);
while val > self.max {
self.index = self.index + w32(1);
val = self.calc(self.index);
}
val.0
}
#[inline(always)]
fn calc(&self, val: w32) -> w32 {
((((val * self.f1) ^ self.x1) * self.f2) ^ self.x2) & self.mask
}
}
impl Iterator for ShuffledIter {
type Item = u32;
#[inline]
fn next(&mut self) -> Option<u32> {
if self.count < self.max {
Some(self.next_value())
} else if self.done {
None
} else {
self.done = true;
self.count = self.count - w32(1);
Some(self.next_value())
}
}
}
#[test]
fn gen_1_1024() {
use bit_vec::BitVec;
use rand::XorShiftRng;
let mut rng = XorShiftRng::new_unseeded();
for i in 0u32 .. 1025 {
let mut bv = BitVec::from_elem(i as usize + 1, false);
let it = ShuffledIter::new(i, &mut rng);
for j in it {
assert!(bv.get(j as usize) == Some(false));
bv.set(j as usize, true);
}
assert!(bv.all());
}
}
#[test]
fn max_u32_max() {
use std::u32;
use rand::XorShiftRng;
let mut rng = XorShiftRng::new_unseeded();
let mut it = ShuffledIter::new(u32::MAX, &mut rng);
for _ in 0 .. 10 {
assert!(it.next().is_some());
}
it.count = w32(u32::MAX - 9);
for _ in 0 .. 10 {
assert!(it.next().is_some());
}
println!("{}", it.count.0);
assert!(it.next().is_none());
}