use crate::FloatScalar;
use super::{ContinuousDistribution, StatsError};
#[derive(Debug, Clone, Copy)]
pub struct Exponential<T> {
lambda: T,
}
impl<T: FloatScalar> Exponential<T> {
pub fn new(lambda: T) -> Result<Self, StatsError> {
if lambda <= T::zero() {
return Err(StatsError::InvalidParameter);
}
Ok(Self { lambda })
}
}
impl<T: FloatScalar> Exponential<T> {
pub fn sample(&self, rng: &mut super::Rng) -> T {
let u: T = rng.next_float();
-(T::one() - u).ln() / self.lambda
}
pub fn sample_array<const K: usize>(&self, rng: &mut super::Rng) -> [T; K] {
let mut out = [T::zero(); K];
for v in out.iter_mut() {
*v = self.sample(rng);
}
out
}
}
impl<T: FloatScalar> ContinuousDistribution<T> for Exponential<T> {
fn pdf(&self, x: T) -> T {
if x < T::zero() {
T::zero()
} else {
self.lambda * (-self.lambda * x).exp()
}
}
fn ln_pdf(&self, x: T) -> T {
if x < T::zero() {
T::neg_infinity()
} else {
self.lambda.ln() - self.lambda * x
}
}
fn cdf(&self, x: T) -> T {
if x <= T::zero() {
T::zero()
} else {
T::one() - (-self.lambda * x).exp()
}
}
fn quantile(&self, p: T) -> T {
-(T::one() - p).ln() / self.lambda
}
fn mean(&self) -> T {
T::one() / self.lambda
}
fn variance(&self) -> T {
T::one() / (self.lambda * self.lambda)
}
}