use crate::{algebra::abstr::Real, statistics::distrib::Continuous};
use rand;
#[cfg(feature = "serde")]
use serde::{Deserialize, Serialize};
use std::clone::Clone;
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[derive(Clone, Copy, Debug)]
pub struct Exponential<T> {
lambda: T,
}
impl<T> Exponential<T>
where
T: Real,
{
pub fn new(lambda: T) -> Exponential<T> {
if lambda <= T::zero() {
panic!()
}
Exponential { lambda }
}
pub fn from_data(data: &[T]) -> Self {
let lambda: T = T::one() / Exponential::calc_mean(data);
Exponential::new(lambda)
}
fn calc_mean(data: &[T]) -> T {
let mut sum: T = T::zero();
for x in data.iter() {
sum += *x;
}
sum / T::from_u64(data.len() as u64)
}
}
impl<T> Continuous<T> for Exponential<T>
where
T: Real,
{
fn pdf(&self, x: T) -> T {
if x < T::zero() {
return T::zero();
}
self.lambda * (-self.lambda * x).exp()
}
fn cdf(&self, x: T) -> T {
if x < T::zero() {
return T::zero();
}
T::one() - (-x * self.lambda).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.pow(T::from_u8(2))
}
fn skewness(&self) -> T {
T::from_f64(2.0)
}
fn median(&self) -> T {
T::from_f64(2.0).ln() / self.lambda
}
fn entropy(&self) -> T {
T::one() - self.lambda.ln()
}
}
impl<T> Exponential<T>
where
T: Real,
{
pub fn random(&self) -> T {
let y: T = T::from_f64(rand::random::<f64>());
let p: T = self.quantile(y);
p
}
}