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