• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 use std::mem;
2 
3 use crate::stats::float::Float;
4 use crate::stats::rand_util::{new_rng, Rng};
5 use crate::stats::univariate::Sample;
6 
7 pub struct Resamples<'a, A>
8 where
9     A: Float,
10 {
11     rng: Rng,
12     sample: &'a [A],
13     stage: Option<Vec<A>>,
14 }
15 
16 #[cfg_attr(feature = "cargo-clippy", allow(clippy::should_implement_trait))]
17 impl<'a, A> Resamples<'a, A>
18 where
19     A: 'a + Float,
20 {
new(sample: &'a Sample<A>) -> Resamples<'a, A>21     pub fn new(sample: &'a Sample<A>) -> Resamples<'a, A> {
22         let slice = sample;
23 
24         Resamples {
25             rng: new_rng(),
26             sample: slice,
27             stage: None,
28         }
29     }
30 
next(&mut self) -> &Sample<A>31     pub fn next(&mut self) -> &Sample<A> {
32         let n = self.sample.len();
33         let rng = &mut self.rng;
34 
35         match self.stage {
36             None => {
37                 let mut stage = Vec::with_capacity(n);
38 
39                 for _ in 0..n {
40                     let idx = rng.rand_range(0u64..(self.sample.len() as u64));
41                     stage.push(self.sample[idx as usize])
42                 }
43 
44                 self.stage = Some(stage);
45             }
46             Some(ref mut stage) => {
47                 for elem in stage.iter_mut() {
48                     let idx = rng.rand_range(0u64..(self.sample.len() as u64));
49                     *elem = self.sample[idx as usize]
50                 }
51             }
52         }
53 
54         if let Some(ref v) = self.stage {
55             unsafe { mem::transmute::<&[_], _>(v) }
56         } else {
57             unreachable!();
58         }
59     }
60 }
61 
62 #[cfg(test)]
63 mod test {
64     use quickcheck::quickcheck;
65     use quickcheck::TestResult;
66     use std::collections::HashSet;
67 
68     use crate::stats::univariate::resamples::Resamples;
69     use crate::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]
different_subsets()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 }
118