criterion/stats/univariate/
mixed.rs

1//! Mixed bootstrap
2
3use rayon::prelude::*;
4use stats::float::Float;
5
6use stats::tuple::{Tuple, TupledDistributionsBuilder};
7use stats::univariate::Resamples;
8use stats::univariate::Sample;
9
10/// Performs a *mixed* two-sample bootstrap
11pub fn bootstrap<A, T, S>(
12    a: &Sample<A>,
13    b: &Sample<A>,
14    nresamples: usize,
15    statistic: S,
16) -> T::Distributions
17where
18    A: Float,
19    S: Fn(&Sample<A>, &Sample<A>) -> T + Sync,
20    T: Tuple + Send,
21    T::Distributions: Send,
22    T::Builder: Send,
23{
24    let n_a = a.len();
25    let n_b = b.len();
26    let mut c = Vec::with_capacity(n_a + n_b);
27    c.extend_from_slice(a);
28    c.extend_from_slice(b);
29    let c = Sample::new(&c);
30
31    (0..nresamples)
32        .into_par_iter()
33        .map_init(
34            || Resamples::new(c),
35            |resamples, _| {
36                let resample = resamples.next();
37                let a: &Sample<A> = Sample::new(&resample[..n_a]);
38                let b: &Sample<A> = Sample::new(&resample[n_a..]);
39
40                statistic(a, b)
41            },
42        )
43        .fold(
44            || T::Builder::new(0),
45            |mut sub_distributions, sample| {
46                sub_distributions.push(sample);
47                sub_distributions
48            },
49        )
50        .reduce(
51            || T::Builder::new(0),
52            |mut a, mut b| {
53                a.extend(&mut b);
54                a
55            },
56        )
57        .complete()
58}