use rand::Rng;
use crate::Sample;
use super::Re;
#[derive(Clone, Copy, Default)]
pub struct Shuffle<R: Rng> {
pub rng: R,
}
impl<R: Rng> Shuffle<R> {
pub fn new(rng: R) -> Self {
Self { rng }
}
}
impl<T: Copy, R: Rng + Clone> Re<Sample<T>> for Shuffle<R> {
type Item = Sample<T>;
fn re(&self, sample: &Sample<T>) -> impl Iterator<Item = Self::Item> {
Box::new(ShuffleIter::new(&sample.data, self.rng.clone()))
}
}
pub struct ShuffleIter<'a, T, R: Rng> {
data: &'a [T],
rng: R,
buffer: Vec<T>,
}
impl<'a, T: Copy, R: Rng> ShuffleIter<'a, T, R> {
fn new(data: &'a [T], rng: R) -> Self {
Self {
buffer: Vec::with_capacity(data.len()),
data,
rng,
}
}
}
impl<'a, T: Copy, R: Rng> Iterator for ShuffleIter<'a, T, R> {
type Item = Sample<T>;
fn next(&mut self) -> Option<Self::Item> {
let n = self.data.len();
unsafe {
if self.buffer.capacity() < n {
self.buffer.reserve_exact(n);
}
self.buffer.set_len(n);
std::ptr::copy_nonoverlapping(self.data.as_ptr(), self.buffer.as_mut_ptr(), n);
}
if n > 1 {
let ptr = self.buffer.as_mut_ptr();
for i in (1..n).rev() {
let j = self.rng.gen_range(0..=i);
unsafe {
let tmp = *ptr.add(i);
*ptr.add(i) = *ptr.add(j);
*ptr.add(j) = tmp;
}
}
}
Some(Sample::new(std::mem::take(&mut self.buffer)))
}
}