use crate::distributions::*;
const EULER_MASCHERONI: f64 = 0.577215664901532860606512090082402431042159335939923598805767234884867726777664670936947063291746749;
const PISQ6: f64 = std::f64::consts::PI;
#[derive(Debug, Clone, Copy)]
pub struct Gumbel {
mu: f64,
beta: f64,
uniform_gen: Uniform,
}
impl Gumbel {
pub fn new(mu: f64, beta: f64) -> Self {
if beta <= 0. {
panic!("Beta must be positive.");
}
Gumbel {
mu,
beta,
uniform_gen: Uniform::new(0., 1.),
}
}
pub fn set_mu(&mut self, mu: f64) -> &mut Self {
self.mu = mu;
self
}
pub fn set_beta(&mut self, beta: f64) -> &mut Self {
if beta <= 0. {
panic!("Beta must be positive.");
}
self.beta = beta;
self
}
}
impl Default for Gumbel {
fn default() -> Self {
Self::new(0., 1.)
}
}
impl Distribution for Gumbel {
type Output = f64;
fn sample(&self) -> Self::Output {
self.mu - self.beta * (-self.uniform_gen.sample().ln()).ln()
}
}
impl Distribution1D for Gumbel {
fn update(&mut self, params: &[f64]) {
self.set_mu(params[0]).set_beta(params[1]);
}
}
impl Continuous for Gumbel {
type PDFType = f64;
fn pdf(&self, x: f64) -> Self::PDFType {
let z = (x - self.mu) / self.beta;
1. / self.beta * (-(z + (-z).exp())).exp()
}
}
impl Mean for Gumbel {
type MeanType = f64;
fn mean(&self) -> Self::MeanType {
self.mu + self.beta * EULER_MASCHERONI
}
}
impl Variance for Gumbel {
type VarianceType = f64;
fn var(&self) -> Self::VarianceType {
PISQ6 * self.beta.powi(2)
}
}