extern crate rand;
use self::rand::{thread_rng, ThreadRng, Rng};
pub struct RandomChoice<RNG: Rng> {
rng: RNG,
}
pub fn random_choice() -> RandomChoice<ThreadRng> {
RandomChoice::new(thread_rng())
}
impl<RNG: Rng> RandomChoice<RNG> {
pub fn new(rng: RNG) -> Self {
RandomChoice { rng: rng }
}
pub fn random_choice_f64<'a, T>(&mut self,
samples: &'a [T],
weights: &[f64],
n: usize)
-> Vec<&'a T> {
if weights.len() == 0 || samples.len() == 0 || n == 0 {
return Vec::new();
}
let sum: f64 = weights.iter().fold(0.0, |acc, &i| acc + i);
let spoke_gap: f64 = sum / n as f64;
let spin = self.rng.next_f64() * spoke_gap;
let mut i: usize = 0;
let mut accumulated_weights = weights[0];
let mut choices: Vec<&T> = Vec::with_capacity(n);
let mut current_spoke: f64 = spin;
while current_spoke < sum {
while accumulated_weights < current_spoke {
i += 1;
accumulated_weights += weights[i];
}
choices.push(&samples[i]);
current_spoke += spoke_gap;
}
while choices.len() < n {
choices.push(&samples[i]);
}
choices
}
pub fn random_choice_f32<'a, T>(&mut self,
samples: &'a [T],
weights: &[f32],
n: usize)
-> Vec<&'a T> {
if weights.len() == 0 || samples.len() == 0 || n == 0 {
return Vec::new();
}
let sum: f64 = weights.iter().fold(0.0, |acc, &i| acc + i as f64);
let spoke_gap: f64 = sum / n as f64;
let spin = self.rng.next_f64() * spoke_gap;
let mut i: usize = 0;
let mut accumulated_weights = weights[0] as f64;
let mut choices: Vec<&T> = Vec::with_capacity(n);
let mut current_spoke: f64 = spin;
while current_spoke < sum {
while accumulated_weights < current_spoke {
i += 1;
accumulated_weights += weights[i] as f64;
}
choices.push(&samples[i]);
current_spoke += spoke_gap;
}
while choices.len() < n {
choices.push(&samples[i]);
}
choices
}
}