criterion/stats/univariate/
bootstrap.rs

1#[cfg(test)]
2macro_rules! test {
3    ($ty:ident) => {
4        mod $ty {
5            use approx::relative_eq;
6            use quickcheck::quickcheck;
7            use quickcheck::TestResult;
8
9            use crate::stats::univariate::{Sample, mixed, self};
10
11            quickcheck!{
12                fn mean(size: u8, start: u8, nresamples: u8) -> TestResult {
13                    let size = size as usize;
14                    let start = start as usize;
15                    let nresamples = nresamples as usize;
16                    if let Some(v) = crate::stats::test::vec::<$ty>(size, start) {
17                        let sample = Sample::new(&v[start..]);
18
19                        let means = if nresamples > 0 {
20                            sample.bootstrap(nresamples, |s| (s.mean(),)).0
21                        } else {
22                            return TestResult::discard();
23                        };
24
25                        let min = sample.min();
26                        let max = sample.max();
27
28                        TestResult::from_bool(
29                            // Computed the correct number of resamples
30                            means.len() == nresamples &&
31                            // No uninitialized values
32                            means.iter().all(|&x| {
33                                (x > min || relative_eq!(x, min)) &&
34                                (x < max || relative_eq!(x, max))
35                            })
36                        )
37                    } else {
38                        TestResult::discard()
39                    }
40                }
41            }
42
43            quickcheck!{
44                fn mean_median(size: u8, start: u8, nresamples: u8) -> TestResult {
45                    let size = size as usize;
46                    let start = start as usize;
47                    let nresamples = nresamples as usize;
48                    if let Some(v) = crate::stats::test::vec::<$ty>(size, start) {
49                        let sample = Sample::new(&v[start..]);
50
51                        let (means, medians) = if nresamples > 0 {
52                            sample.bootstrap(nresamples, |s| (s.mean(), s.median()))
53                        } else {
54                            return TestResult::discard();
55                        };
56
57                        let min = sample.min();
58                        let max = sample.max();
59
60                        TestResult::from_bool(
61                            // Computed the correct number of resamples
62                            means.len() == nresamples &&
63                            medians.len() == nresamples &&
64                            // No uninitialized values
65                            means.iter().all(|&x| {
66                                (x > min || relative_eq!(x, min)) &&
67                                (x < max || relative_eq!(x, max))
68                            }) &&
69                            medians.iter().all(|&x| {
70                                (x > min || relative_eq!(x, min)) &&
71                                (x < max || relative_eq!(x, max))
72                            })
73                        )
74                    } else {
75                        TestResult::discard()
76                    }
77                }
78            }
79
80            quickcheck!{
81                fn mixed_two_sample(
82                    a_size: u8, a_start: u8,
83                    b_size: u8, b_start: u8,
84                    nresamples: u8
85                ) -> TestResult {
86                    let a_size = a_size as usize;
87                    let b_size = b_size as usize;
88                    let a_start = a_start as usize;
89                    let b_start = b_start as usize;
90                    let nresamples = nresamples as usize;
91                    if let (Some(a), Some(b)) =
92                        (crate::stats::test::vec::<$ty>(a_size, a_start), crate::stats::test::vec::<$ty>(b_size, b_start))
93                    {
94                        let a = Sample::new(&a);
95                        let b = Sample::new(&b);
96
97                        let distribution = if nresamples > 0 {
98                            mixed::bootstrap(a, b, nresamples, |a, b| (a.mean() - b.mean(),)).0
99                        } else {
100                            return TestResult::discard();
101                        };
102
103                        let min = <$ty>::min(a.min() - b.max(), b.min() - a.max());
104                        let max = <$ty>::max(a.max() - b.min(), b.max() - a.min());
105
106                        TestResult::from_bool(
107                            // Computed the correct number of resamples
108                            distribution.len() == nresamples &&
109                            // No uninitialized values
110                            distribution.iter().all(|&x| {
111                                (x > min || relative_eq!(x, min)) &&
112                                (x < max || relative_eq!(x, max))
113                            })
114                        )
115                    } else {
116                        TestResult::discard()
117                    }
118                }
119            }
120
121            quickcheck!{
122                fn two_sample(
123                    a_size: u8, a_start: u8,
124                    b_size: u8, b_start: u8,
125                    nresamples: u8
126                ) -> TestResult {
127                    let a_size = a_size as usize;
128                    let b_size = b_size as usize;
129                    let a_start = a_start as usize;
130                    let b_start = b_start as usize;
131                    let nresamples = nresamples as usize;
132                    if let (Some(a), Some(b)) =
133                        (crate::stats::test::vec::<$ty>(a_size, a_start), crate::stats::test::vec::<$ty>(b_size, b_start))
134                    {
135                        let a = Sample::new(&a[a_start..]);
136                        let b = Sample::new(&b[b_start..]);
137
138                        let distribution = if nresamples > 0 {
139                            univariate::bootstrap(a, b, nresamples, |a, b| (a.mean() - b.mean(),)).0
140                        } else {
141                            return TestResult::discard();
142                        };
143
144                        let min = <$ty>::min(a.min() - b.max(), b.min() - a.max());
145                        let max = <$ty>::max(a.max() - b.min(), b.max() - a.min());
146
147                        // Computed the correct number of resamples
148                        let pass = distribution.len() == nresamples &&
149                            // No uninitialized values
150                            distribution.iter().all(|&x| {
151                                (x > min || relative_eq!(x, min)) &&
152                                (x < max || relative_eq!(x, max))
153                            });
154
155                        if !pass {
156                            println!("A: {:?} (len={})", a.as_ref(), a.len());
157                            println!("B: {:?} (len={})", b.as_ref(), b.len());
158                            println!("Dist: {:?} (len={})", distribution.as_ref(), distribution.len());
159                            println!("Min: {}, Max: {}, nresamples: {}",
160                                min, max, nresamples);
161                        }
162
163                        TestResult::from_bool(pass)
164                    } else {
165                        TestResult::discard()
166                    }
167                }
168            }
169        }
170    }
171}
172
173#[cfg(test)]
174mod test {
175    test!(f32);
176    test!(f64);
177}