1 //! Univariate analysis
2 
3 mod bootstrap;
4 mod percentiles;
5 mod resamples;
6 mod sample;
7 
8 pub mod kde;
9 pub mod mixed;
10 pub mod outliers;
11 
12 use crate::stats::float::Float;
13 use crate::stats::tuple::{Tuple, TupledDistributionsBuilder};
14 use rayon::prelude::*;
15 use std::cmp;
16 
17 use self::resamples::Resamples;
18 
19 pub use self::percentiles::Percentiles;
20 pub use self::sample::Sample;
21 
22 /// Performs a two-sample bootstrap
23 ///
24 /// - Multithreaded
25 /// - Time: `O(nresamples)`
26 /// - Memory: `O(nresamples)`
27 #[cfg_attr(feature = "cargo-clippy", allow(clippy::cast_lossless))]
bootstrap<A, B, T, S>( a: &Sample<A>, b: &Sample<B>, nresamples: usize, statistic: S, ) -> T::Distributions where A: Float, B: Float, S: Fn(&Sample<A>, &Sample<B>) -> T + Sync, T: Tuple + Send, T::Distributions: Send, T::Builder: Send,28 pub fn bootstrap<A, B, T, S>(
29     a: &Sample<A>,
30     b: &Sample<B>,
31     nresamples: usize,
32     statistic: S,
33 ) -> T::Distributions
34 where
35     A: Float,
36     B: Float,
37     S: Fn(&Sample<A>, &Sample<B>) -> T + Sync,
38     T: Tuple + Send,
39     T::Distributions: Send,
40     T::Builder: Send,
41 {
42     let nresamples_sqrt = (nresamples as f64).sqrt().ceil() as usize;
43     let per_chunk = (nresamples + nresamples_sqrt - 1) / nresamples_sqrt;
44 
45     (0..nresamples_sqrt)
46         .into_par_iter()
47         .map_init(
48             || (Resamples::new(a), Resamples::new(b)),
49             |(a_resamples, b_resamples), i| {
50                 let start = i * per_chunk;
51                 let end = cmp::min((i + 1) * per_chunk, nresamples);
52                 let a_resample = a_resamples.next();
53 
54                 let mut sub_distributions: T::Builder =
55                     TupledDistributionsBuilder::new(end - start);
56 
57                 for _ in start..end {
58                     let b_resample = b_resamples.next();
59                     sub_distributions.push(statistic(a_resample, b_resample));
60                 }
61                 sub_distributions
62             },
63         )
64         .reduce(
65             || T::Builder::new(0),
66             |mut a, mut b| {
67                 a.extend(&mut b);
68                 a
69             },
70         )
71         .complete()
72 }
73