1 #[cfg(test)]
2 macro_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)]
174 mod test {
175     test!(f32);
176     test!(f64);
177 }
178