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