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