use nalgebra::Complex;
use num_traits::{Float, FloatConst};
use rand::{
Rng,
distr::{Distribution, StandardUniform},
};
use crate::Generator;
#[derive(Debug, Clone, Copy)]
pub struct Gaussian<T> {
centre: Complex<T>,
std_dev: T,
}
impl<T: Float> Gaussian<T> {
#[inline]
pub fn new(centre: Complex<T>, std_dev: T) -> Self {
debug_assert!(std_dev > T::zero(), "Standard deviation must be positive");
Self { centre, std_dev }
}
}
impl<T: Float + FloatConst> Generator<T> for Gaussian<T>
where
StandardUniform: Distribution<T>,
{
#[inline]
fn sample<R: Rng>(&self, rng: &mut R) -> Complex<T> {
let u1: T = rng.random();
let u2: T = rng.random();
let r = (T::from(-2).unwrap() * u1.ln()).sqrt() * self.std_dev;
let theta = T::TAU() * u2;
let x = r * theta.cos();
let y = r * theta.sin();
self.centre + Complex::new(x, y)
}
}