zima 0.1.0-alpha.2

An attempt to create a modern package for the needs of applied statistics
Documentation
use rand::Rng;
use crate::Sample;
use super::Re;

#[derive(Clone, Copy, Default)]
pub struct Bootstrap<R: Rng> {
    pub rng: R,
}

impl<R: Rng> Bootstrap<R> {
    pub fn new(rng: R) -> Self {
        Self { rng }
    }
}

impl<T: Copy, R: Rng + Clone> Re<Sample<T>> for Bootstrap<R> {
    type Item = Sample<T>;

    fn re(&self, sample: &Sample<T>) -> impl Iterator<Item = Self::Item> {
        Box::new(BootstrapIter::new(&sample.data, self.rng.clone()))
    }
}

pub struct BootstrapIter<'a, T, R: Rng> {
    data: &'a [T],
    rng: R,
    buffer: Vec<T>,
}

impl<'a, T: Copy, R: Rng> BootstrapIter<'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 BootstrapIter<'a, T, R> {
    type Item = Sample<T>;

    fn next(&mut self) -> Option<Self::Item> {
        let n = self.data.len();
        self.buffer.clear();
        self.buffer.reserve_exact(n);

        unsafe {
            self.buffer.set_len(n);
            for i in 0..n {
                let idx = self.rng.gen_range(0..n);
                *self.buffer.get_unchecked_mut(i) = *self.data.get_unchecked(idx);
            }
        }

        Some(Sample::new(std::mem::take(&mut self.buffer)))
    }
}