1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
#[cfg(feature = "unweighted")]
pub mod unweighted {
    pub mod core;

    use rand::thread_rng;
    
    /// An implementation of Algorithm `L` (https://en.wikipedia.org/wiki/Reservoir_sampling#An_optimal_algorithm)
    /// # Parameters:
    /// - Type implementing `std::iter::Iterator` as *source*,
    /// - Mutable array slice (i.e. `&mut [T]`) as *sample array (i.e. where sampled data is stored)*
    /// # Notes:
    /// - In case iterator yields less than sample amount, sample will be filled as much as possible, and returned.
    /// - This uses `rand::thread_rng` to provide RNG. To use your own RNG which implements `rand::RNG`, see `reservoir_sampling::core`
    
    pub fn l <I, T>(stream: I, sample: &mut [T])
    where
        I: Iterator<Item=T>,
    {
        let mut rng = thread_rng();
        core::l(stream, sample, &mut rng);
    }

    /// An implementation of algorithm `R` (https://en.wikipedia.org/wiki/Reservoir_sampling#Simple_algorithm)
    /// # Parameters:
    /// - Type implementing `std::iter::Iterator` as *source*,
    /// - Mutable array slice (i.e. `&mut [T]`) as *sample array (i.e. where sampled data is stored)*
    /// - Type implementing `rand::Rng` for random number generation.
    /// In case iterator yields less than sample amount, sample will be filled as much as possible, and returned.

    pub fn r <I, T>(stream: I, sample: &mut [T])
    where
        I: Iterator<Item=T>,
    {
        let mut rng = thread_rng();
        core::r(stream, sample, &mut rng);
    }
}

#[cfg(feature = "weighted")]
pub mod weighted {
    /*!
    Provides weighted reservoir sampling, i.e. the
    odds of a particular item occurring in the sampling
    can be influenced.

    Odds can be influenced via the `WeightedItem` struct,
    which is a wrapper struct around your item and 
    an associated weight which controls the frequency
    of the item occurring in the resulting sampling.

    The functions in this module take an iterator of `WeightedItem`,
    so remember to wrap your types in that struct and then pass an iterator of them.
    */

    pub mod core;

    use rand::thread_rng;
    use self::core::WeightedItem;

    /// An implementation of Algorithm `A-Res` (https://en.wikipedia.org/wiki/Reservoir_sampling#Algorithm_A-Res)
    /// # Parameters:
    /// - Iterator of `core::WeightedItem` as *source*,
    /// - `sample_len`, the size of the sampled reservoir.
    /// Returns a `Vec` of length `sample_len`
    /// In case iterator yields less than sample amount, sample will be filled as much as possible, and returned.

    pub fn a_res <I, T> (stream: I, sample_len: usize) -> Vec<T>
    where
        I: Iterator<Item=WeightedItem<T>>
    {
        let mut rng = thread_rng();
        core::a_res(stream, sample_len, &mut rng)
    }
}