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}
178