//! Mixed bootstrap use crate::stats::float::Float; use crate::stats::tuple::{Tuple, TupledDistributionsBuilder}; use crate::stats::univariate::Resamples; use crate::stats::univariate::Sample; use rayon::prelude::*; /// Performs a *mixed* two-sample bootstrap pub fn bootstrap( a: &Sample, b: &Sample, nresamples: usize, statistic: S, ) -> T::Distributions where A: Float, S: Fn(&Sample, &Sample) -> T + Sync, T: Tuple + Send, T::Distributions: Send, T::Builder: Send, { let n_a = a.len(); let n_b = b.len(); let mut c = Vec::with_capacity(n_a + n_b); c.extend_from_slice(a); c.extend_from_slice(b); let c = Sample::new(&c); (0..nresamples) .into_par_iter() .map_init( || Resamples::new(c), |resamples, _| { let resample = resamples.next(); let a: &Sample = Sample::new(&resample[..n_a]); let b: &Sample = Sample::new(&resample[n_a..]); statistic(a, b) }, ) .fold( || T::Builder::new(0), |mut sub_distributions, sample| { sub_distributions.push(sample); sub_distributions }, ) .reduce( || T::Builder::new(0), |mut a, mut b| { a.extend(&mut b); a }, ) .complete() }