criterion/stats/bivariate/
mod.rs
1mod bootstrap;
4mod resamples;
5
6pub mod regression;
7
8use rayon::prelude::*;
9use stats::float::Float;
10
11use stats::bivariate::resamples::Resamples;
12use stats::tuple::{Tuple, TupledDistributionsBuilder};
13use stats::univariate::Sample;
14
15pub struct Data<'a, X, Y>(&'a [X], &'a [Y])
22where
23 X: 'a,
24 Y: 'a;
25
26impl<'a, X, Y> Copy for Data<'a, X, Y> {}
27
28#[cfg_attr(feature = "cargo-clippy", allow(clippy::expl_impl_clone_on_copy))]
29impl<'a, X, Y> Clone for Data<'a, X, Y> {
30 fn clone(&self) -> Data<'a, X, Y> {
31 *self
32 }
33}
34
35impl<'a, X, Y> Data<'a, X, Y> {
36 pub fn len(&self) -> usize {
38 self.0.len()
39 }
40
41 pub fn iter(&self) -> Pairs<'a, X, Y> {
43 Pairs {
44 data: *self,
45 state: 0,
46 }
47 }
48}
49
50impl<'a, X, Y> Data<'a, X, Y>
51where
52 X: Float,
53 Y: Float,
54{
55 pub fn new(xs: &'a [X], ys: &'a [Y]) -> Data<'a, X, Y> {
57 assert!(
58 xs.len() == ys.len()
59 && xs.len() > 1
60 && xs.iter().all(|x| !x.is_nan())
61 && ys.iter().all(|y| !y.is_nan())
62 );
63
64 Data(xs, ys)
65 }
66
67 pub fn bootstrap<T, S>(&self, nresamples: usize, statistic: S) -> T::Distributions
74 where
75 S: Fn(Data<X, Y>) -> T,
76 S: Sync,
77 T: Tuple + Send,
78 T::Distributions: Send,
79 T::Builder: Send,
80 {
81 (0..nresamples)
82 .into_par_iter()
83 .map_init(
84 || Resamples::new(*self),
85 |resamples, _| statistic(resamples.next()),
86 )
87 .fold(
88 || T::Builder::new(0),
89 |mut sub_distributions, sample| {
90 sub_distributions.push(sample);
91 sub_distributions
92 },
93 )
94 .reduce(
95 || T::Builder::new(0),
96 |mut a, mut b| {
97 a.extend(&mut b);
98 a
99 },
100 )
101 .complete()
102 }
103
104 pub fn x(&self) -> &'a Sample<X> {
106 Sample::new(&self.0)
107 }
108
109 pub fn y(&self) -> &'a Sample<Y> {
111 Sample::new(&self.1)
112 }
113}
114
115pub struct Pairs<'a, X: 'a, Y: 'a> {
117 data: Data<'a, X, Y>,
118 state: usize,
119}
120
121impl<'a, X, Y> Iterator for Pairs<'a, X, Y> {
122 type Item = (&'a X, &'a Y);
123
124 fn next(&mut self) -> Option<(&'a X, &'a Y)> {
125 if self.state < self.data.len() {
126 let i = self.state;
127 self.state += 1;
128
129 debug_assert!(i < self.data.0.len());
131 debug_assert!(i < self.data.1.len());
132 unsafe { Some((self.data.0.get_unchecked(i), self.data.1.get_unchecked(i))) }
133 } else {
134 None
135 }
136 }
137}