use rand::Rng;
use num_traits::Float as NumFloat;
use num_traits::{NumCast, Zero};
use alga::general::AbstractField;
use alga::linear::{FiniteDimVectorSpace, NormedSpace};
#[macro_use]
extern crate lazy_static;
use std::marker::PhantomData;
use std::ops::{AddAssign, DivAssign, Index, IndexMut, MulAssign, SubAssign};
use crate::algorithm::{Algorithm, Creator};
use crate::utils::math::calc_radius;
pub mod algorithm;
mod utils;
pub trait Float: NumFloat + AbstractField + AddAssign + SubAssign + MulAssign + DivAssign {
fn cast(n: usize) -> Self {
NumCast::from(n).expect("Casting usize to float should always succeed.")
}
}
impl<T> Float for T where T: NumFloat + AbstractField + AddAssign + SubAssign + MulAssign + DivAssign
{}
pub trait Vector<F>:
Zero
+ FiniteDimVectorSpace<Field = F>
+ NormedSpace<Field = F>
+ Index<usize>
+ IndexMut<usize>
+ Clone
where
F: Float,
{
}
impl<T, F> Vector<F> for T
where
F: Float,
T: Zero
+ FiniteDimVectorSpace<Field = F>
+ NormedSpace<Field = F>
+ Index<usize>
+ IndexMut<usize>
+ Clone
{
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum Type {
Normal,
Perioditic,
}
impl Default for Type {
fn default() -> Type {
Type::Normal
}
}
#[derive(Default, Clone, Debug, PartialEq)]
pub struct Builder<F, V>
where
F: Float,
V: Vector<F>,
{
radius: F,
poisson_type: Type,
_marker: PhantomData<V>,
}
impl<V, F> Builder<F, V>
where
F: Float,
V: Vector<F>,
{
pub fn with_radius(radius: F, poisson_type: Type) -> Self {
assert!(F::cast(0) < radius);
assert!(
radius
<= NumCast::from(2f64.sqrt() / 2.).expect("Casting constant should always work.")
);
Builder {
radius: radius,
poisson_type: poisson_type,
_marker: PhantomData,
}
}
pub fn with_relative_radius(relative: F, poisson_type: Type) -> Self {
assert!(relative >= F::cast(0));
assert!(relative <= F::cast(1));
Builder {
radius: relative
* NumCast::from(2f64.sqrt() / 2.).expect("Casting constant should always work."),
poisson_type: poisson_type,
_marker: PhantomData,
}
}
pub fn with_samples(samples: usize, relative: F, poisson_type: Type) -> Self {
Builder {
radius: calc_radius::<F, V>(samples, relative, poisson_type),
poisson_type: poisson_type,
_marker: PhantomData,
}
}
pub fn radius(&self) -> F {
self.radius
}
pub fn poisson_type(&self) -> Type {
self.poisson_type
}
pub fn build<R, A>(self, rng: R, _algo: A) -> Generator<F, V, R, A>
where
R: Rng,
A: Creator<F, V>,
{
Generator::new(self, rng)
}
}
#[derive(Clone, Debug)]
pub struct Generator<F, V, R, A>
where
F: Float,
V: Vector<F>,
R: Rng,
A: Creator<F, V>,
{
poisson: Builder<F, V>,
rng: R,
_algo: PhantomData<A>,
}
impl<F, V, R, A> Generator<F, V, R, A>
where
F: Float,
V: Vector<F>,
R: Rng,
A: Creator<F, V>,
{
fn new(poisson: Builder<F, V>, rng: R) -> Self {
Generator {
rng: rng,
poisson: poisson,
_algo: PhantomData,
}
}
pub fn set_radius(&mut self, radius: F) {
assert!(F::cast(0) < radius);
assert!(
radius
<= NumCast::from(2f64.sqrt() / 2.).expect("Casting constant should always work.")
);
self.poisson.radius = radius;
}
pub fn radius(&self) -> F {
self.poisson.radius
}
pub fn poisson_type(&self) -> Type {
self.poisson.poisson_type
}
}
impl<F, V, R, A> Generator<F, V, R, A>
where
F: Float,
V: Vector<F>,
R: Rng + Clone,
A: Creator<F, V>,
{
pub fn generate(&self) -> Vec<V> {
self.clone().into_iter().collect()
}
}
impl<F, V, R, A> IntoIterator for Generator<F, V, R, A>
where
F: Float,
V: Vector<F>,
R: Rng,
A: Creator<F, V>,
{
type IntoIter = PoissonIter<F, V, R, A::Algo>;
type Item = V;
fn into_iter(self) -> Self::IntoIter {
PoissonIter {
rng: self.rng,
algo: A::create(&self.poisson),
poisson: self.poisson,
}
}
}
#[derive(Clone)]
pub struct PoissonIter<F, V, R, A>
where
F: Float,
V: Vector<F>,
R: Rng,
A: Algorithm<F, V>,
{
poisson: Builder<F, V>,
rng: R,
algo: A,
}
impl<F, V, R, A> Iterator for PoissonIter<F, V, R, A>
where
F: Float,
V: Vector<F>,
R: Rng,
A: Algorithm<F, V>,
{
type Item = V;
fn next(&mut self) -> Option<Self::Item> {
self.algo.next(&mut self.poisson, &mut self.rng)
}
fn size_hint(&self) -> (usize, Option<usize>) {
self.algo.size_hint(&self.poisson)
}
}
impl<F, V, R, A> PoissonIter<F, V, R, A>
where
F: Float,
V: Vector<F>,
R: Rng,
A: Algorithm<F, V>,
{
pub fn radius(&self) -> F {
self.poisson.radius
}
pub fn poisson_type(&self) -> Type {
self.poisson.poisson_type
}
pub fn restrict(&mut self, value: V) {
self.algo.restrict(value);
}
pub fn stays_legal(&self, value: V) -> bool {
self.algo.stays_legal(&self.poisson, value)
}
}