aboutsummaryrefslogtreecommitdiff
path: root/src/stats/univariate/mixed.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/stats/univariate/mixed.rs')
-rwxr-xr-xsrc/stats/univariate/mixed.rs57
1 files changed, 57 insertions, 0 deletions
diff --git a/src/stats/univariate/mixed.rs b/src/stats/univariate/mixed.rs
new file mode 100755
index 0000000..5c0a59f
--- /dev/null
+++ b/src/stats/univariate/mixed.rs
@@ -0,0 +1,57 @@
+//! 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, 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);
+
+ (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()
+}