1use std::mem;
2
3use crate::stats::float::Float;
4use crate::stats::rand_util::{new_rng, Rng};
5use crate::stats::univariate::Sample;
6
7pub struct Resamples<'a, A>
8where
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))]
17impl<'a, A> Resamples<'a, A>
18where
19 A: 'a + Float,
20{
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
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)]
63mod 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: u8, nresamples: u8) -> TestResult {
74 let size = size as usize;
75 let nresamples = nresamples as usize;
76 if size > 1 {
77 let v: Vec<_> = (0..size).map(|i| i as f32).collect();
78 let sample = Sample::new(&v);
79 let mut resamples = Resamples::new(sample);
80 let sample = v.iter().map(|&x| x as i64).collect::<HashSet<_>>();
81
82 TestResult::from_bool((0..nresamples).all(|_| {
83 let resample = resamples.next()
84
85 .iter()
86 .map(|&x| x as i64)
87 .collect::<HashSet<_>>();
88
89 resample.is_subset(&sample)
90 }))
91 } else {
92 TestResult::discard()
93 }
94 }
95 }
96
97 #[test]
98 fn different_subsets() {
99 let size = 1000;
100 let v: Vec<_> = (0..size).map(|i| i as f32).collect();
101 let sample = Sample::new(&v);
102 let mut resamples = Resamples::new(sample);
103
104 // Hypothetically, we might see one duplicate, but more than one is likely to be a bug.
105 let mut num_duplicated = 0;
106 for _ in 0..1000 {
107 let sample_1 = resamples.next().iter().cloned().collect::<Vec<_>>();
108 let sample_2 = resamples.next().iter().cloned().collect::<Vec<_>>();
109
110 if sample_1 == sample_2 {
111 num_duplicated += 1;
112 }
113 }
114
115 if num_duplicated > 1 {
116 panic!("Found {} duplicate samples", num_duplicated);
117 }
118 }
119}
120