1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
|
//! Mixed bootstrap
use crate::stats::float::Float;
use crate::stats::tuple::{Tuple, TupledDistributionsBuilder};
use crate::stats::univariate::Resamples;
use crate::stats::univariate::Sample;
#[cfg(feature = "rayon")]
use rayon::prelude::*;
/// Performs a *mixed* two-sample bootstrap
pub fn bootstrap<A, T, S>(
a: &Sample<A>,
b: &Sample<A>,
nresamples: usize,
statistic: S,
) -> T::Distributions
where
A: Float,
S: Fn(&Sample<A>, &Sample<A>) -> 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);
#[cfg(feature = "rayon")]
{
(0..nresamples)
.into_par_iter()
.map_init(
|| Resamples::new(c),
|resamples, _| {
let resample = resamples.next();
let a: &Sample<A> = Sample::new(&resample[..n_a]);
let b: &Sample<A> = 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()
}
#[cfg(not(feature = "rayon"))]
{
let mut resamples = Resamples::new(c);
(0..nresamples)
.map(|_| {
let resample = resamples.next();
let a: &Sample<A> = Sample::new(&resample[..n_a]);
let b: &Sample<A> = Sample::new(&resample[n_a..]);
statistic(a, b)
})
.fold(T::Builder::new(0), |mut sub_distributions, sample| {
sub_distributions.push(sample);
sub_distributions
})
.complete()
}
}
|