criterion_stats/univariate/
mod.rs1mod bootstrap;
4mod percentiles;
5mod resamples;
6mod sample;
7
8pub mod kde;
9pub mod mixed;
10pub mod outliers;
11
12use float::Float;
13use num_cpus;
14use std::cmp;
15use thread_scoped as thread;
16
17use tuple::{Tuple, TupledDistributionsBuilder};
18
19use self::resamples::Resamples;
20
21pub use self::percentiles::Percentiles;
22pub use self::sample::Sample;
23
24#[cfg_attr(feature = "cargo-clippy", allow(clippy::cast_lossless))]
30pub fn bootstrap<A, B, T, S>(
31 a: &Sample<A>,
32 b: &Sample<B>,
33 nresamples: usize,
34 statistic: S,
35) -> T::Distributions
36where
37 A: Float,
38 B: Float,
39 S: Fn(&Sample<A>, &Sample<B>) -> T,
40 S: Sync,
41 T: Tuple,
42 T::Distributions: Send,
43 T::Builder: Send,
44{
45 let ncpus = num_cpus::get();
46
47 unsafe {
48 if true {
50 let granularity = nresamples / ncpus + 1;
52 let granularity_sqrt = (granularity as f64).sqrt().ceil() as usize;
53 let statistic = &statistic;
54 let mut cutoff = 0;
55
56 let chunks = (0..ncpus)
57 .map(|_| {
58 let mut sub_distributions: T::Builder =
59 TupledDistributionsBuilder::new(granularity);
60 let start = cutoff;
61 let end = cmp::min(start + granularity, nresamples);
62 cutoff = end;
63
64 thread::scoped(move || {
65 let mut a_resamples = Resamples::new(a);
66 let mut b_resamples = Resamples::new(b);
67 let mut i = start;
68
69 for _ in 0..granularity_sqrt {
70 let a_resample = a_resamples.next();
71
72 for _ in 0..granularity_sqrt {
73 if i == end {
74 return sub_distributions;
75 }
76
77 let b_resample = b_resamples.next();
78
79 sub_distributions.push(statistic(a_resample, b_resample));
80
81 i += 1;
82 }
83 }
84 sub_distributions
85 })
86 })
87 .collect::<Vec<_>>();
88
89 let mut builder: T::Builder = TupledDistributionsBuilder::new(nresamples);
90 for chunk in chunks {
91 builder.extend(&mut (chunk.join()));
92 }
93 builder.complete()
94 } else {
95 let nresamples_sqrt = (nresamples as f64).sqrt().ceil() as usize;
96 let mut a_resamples = Resamples::new(a);
97 let mut b_resamples = Resamples::new(b);
98 let mut distributions: T::Builder = TupledDistributionsBuilder::new(nresamples);
99
100 let mut i = 0;
101 'outer: for _ in 0..nresamples_sqrt {
102 let a_resample = a_resamples.next();
103
104 for _ in 0..nresamples_sqrt {
105 if i == nresamples {
106 break 'outer;
107 }
108
109 let b_resample = b_resamples.next();
110
111 distributions.push(statistic(a_resample, b_resample));
112
113 i += 1;
114 }
115 }
116
117 distributions.complete()
118 }
119 }
120}