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