extern crate rand;
use std::iter::repeat;
use std::collections::VecDeque;
use std::collections::vec_deque::{ IntoIter, Iter, IterMut };
use self::rand::Rng;
pub struct RandomWheel<T> {
proba_sum: f32,
cards: VecDeque<(f32, T)>
}
impl<T: Clone> Clone for RandomWheel<T> {
fn clone(&self) -> RandomWheel<T> {
RandomWheel{
proba_sum: self.proba_sum,
cards: self.cards.clone()
}
}
}
impl<T> IntoIterator for RandomWheel<T> {
type Item = (f32, T);
type IntoIter = IntoIter<(f32, T)>;
#[inline]
fn into_iter(self) -> IntoIter<(f32, T)> {
self.cards.into_iter()
}
}
impl<T> RandomWheel<T> {
pub fn from_vec(vector: Vec<T>) -> RandomWheel<T> {
RandomWheel {
proba_sum: vector.len() as f32,
cards: repeat(1.0).into_iter().zip(vector).collect()
}
}
pub fn new() -> RandomWheel<T> {
RandomWheel {
proba_sum: 0.,
cards: VecDeque::new()
}
}
pub fn with_capacity(n: usize) -> RandomWheel<T> {
RandomWheel {
proba_sum: 0.,
cards: VecDeque::with_capacity(n)
}
}
pub fn reserve(&mut self, additional: usize) {
self.cards.reserve(additional);
}
pub fn capacity(&self) -> usize {
self.cards.capacity()
}
pub fn len(&self) -> usize {
self.cards.len()
}
pub fn clear(&mut self) {
self.cards.clear()
}
pub fn is_empty(&self) -> bool {
self.len() == 0
}
pub fn iter(&self) -> Iter<(f32, T)> {
self.cards.iter()
}
pub fn iter_mut(&mut self) -> IterMut<(f32, T)> {
self.cards.iter_mut()
}
pub fn push(&mut self, proba: f32, data: T) {
assert!(proba > 0.0, "proba {} is lower or equal to zero!", proba);
self.cards.push_back((proba, data));
self.proba_sum += proba;
if self.proba_sum.is_infinite() {
panic!("Probability sum reached an Inf value!");
}
}
pub fn compute_proba_sum(&mut self) {
let mut sum = 0.0;
for &(proba, _) in self.cards.iter() {
assert!(proba > 0.0, "proba {} is lower or equal to zero!", proba);
sum += proba;
}
self.proba_sum = sum;
if self.proba_sum.is_infinite() {
panic!("Probability sum reached an Inf value!");
}
}
pub fn proba_sum(&self) -> f32 {
self.proba_sum
}
fn gen_random_dist(&self) -> f32 {
match self.proba_sum {
sum if sum > 0. => rand::thread_rng().gen_range(0., sum),
_ => 0.
}
}
fn get_random_index(&self) -> Option<usize> {
if self.is_empty() == false {
let mut dist = self.gen_random_dist();
for (id, &(ref proba, _)) in self.cards.iter().enumerate() {
dist -= *proba;
if dist <= 0. {
return Some(id);
}
}
None
}
else { None }
}
pub fn peek(&self) -> Option<(f32, &T)> {
if let Some(index) = self.get_random_index() {
if let Some(&(proba, ref data)) = self.cards.get(index) {
Some((proba, data))
}
else { None }
}
else { None }
}
pub fn peek_mut(&mut self) -> Option<(f32, &mut T)> {
if let Some(index) = self.get_random_index() {
if let Some(&mut (proba, ref mut data)) = self.cards.get_mut(index) {
Some((proba, data))
}
else { None }
}
else { None }
}
pub fn pop(&mut self) -> Option<(f32, T)> {
if let Some(index) = self.get_random_index() {
if let Some((proba, data)) = self.cards.remove(index) {
self.proba_sum -= proba;
Some((proba, data))
}
else { None }
}
else { None }
}
}