criterion/stats/univariate/
resamples.rs

1use std::mem;
2
3use stats::float::Float;
4use stats::rand_util::{new_rng, Range, Rng};
5
6use stats::univariate::Sample;
7
8pub struct Resamples<'a, A>
9where
10    A: 'a + Float,
11{
12    range: Range,
13    rng: Rng,
14    sample: &'a [A],
15    stage: Option<Vec<A>>,
16}
17
18#[cfg_attr(feature = "cargo-clippy", allow(clippy::should_implement_trait))]
19impl<'a, A> Resamples<'a, A>
20where
21    A: 'a + Float,
22{
23    pub fn new(sample: &'a Sample<A>) -> Resamples<'a, A> {
24        let slice = sample;
25
26        Resamples {
27            range: Range::new_exclusive(0, slice.len()),
28            rng: new_rng(),
29            sample: slice,
30            stage: None,
31        }
32    }
33
34    pub fn next(&mut self) -> &Sample<A> {
35        let n = self.sample.len();
36        let rng = &mut self.rng;
37
38        match self.stage {
39            None => {
40                let mut stage = Vec::with_capacity(n);
41
42                for _ in 0..n {
43                    stage.push(self.sample[self.range.sample(rng)])
44                }
45
46                self.stage = Some(stage);
47            }
48            Some(ref mut stage) => {
49                for elem in stage.iter_mut() {
50                    *elem = self.sample[self.range.sample(rng)]
51                }
52            }
53        }
54
55        if let Some(ref v) = self.stage {
56            unsafe { mem::transmute::<&[_], _>(v) }
57        } else {
58            unreachable!();
59        }
60    }
61}
62
63#[cfg(test)]
64mod test {
65    use quickcheck::TestResult;
66    use std::collections::HashSet;
67
68    use stats::univariate::resamples::Resamples;
69    use stats::univariate::Sample;
70
71    // Check that the resample is a subset of the sample
72    quickcheck! {
73        fn subset(size: usize, nresamples: usize) -> TestResult {
74            if size > 1 {
75                let v: Vec<_> = (0..size).map(|i| i as f32).collect();
76                let sample = Sample::new(&v);
77                let mut resamples = Resamples::new(sample);
78                let sample = v.iter().map(|&x| x as i64).collect::<HashSet<_>>();
79
80                TestResult::from_bool((0..nresamples).all(|_| {
81                    let resample = resamples.next()
82
83                        .iter()
84                        .map(|&x| x as i64)
85                        .collect::<HashSet<_>>();
86
87                    resample.is_subset(&sample)
88                }))
89            } else {
90                TestResult::discard()
91            }
92        }
93    }
94
95    #[test]
96    fn different_subsets() {
97        let size = 1000;
98        let v: Vec<_> = (0..size).map(|i| i as f32).collect();
99        let sample = Sample::new(&v);
100        let mut resamples = Resamples::new(sample);
101
102        // Hypothetically, we might see one duplicate, but more than one is likely to be a bug.
103        let mut num_duplicated = 0;
104        for _ in 0..1000 {
105            let sample_1 = resamples.next().iter().cloned().collect::<Vec<_>>();
106            let sample_2 = resamples.next().iter().cloned().collect::<Vec<_>>();
107
108            if sample_1 == sample_2 {
109                num_duplicated += 1;
110            }
111        }
112
113        if num_duplicated > 1 {
114            panic!("Found {} duplicate samples", num_duplicated);
115        }
116    }
117}