use crate::numeric::UnsignedInteger;
pub trait DispersionParameter: Clone {
fn get_standard_dev(&self) -> f64;
fn get_variance(&self) -> f64;
fn get_log_standard_dev(&self) -> f64;
fn get_modular_standard_dev<Uint>(&self) -> f64
where
Uint: UnsignedInteger;
fn get_modular_variance<Uint>(&self) -> f64
where
Uint: UnsignedInteger;
fn get_modular_log_standard_dev<Uint>(&self) -> f64
where
Uint: UnsignedInteger;
}
#[derive(Debug, Copy, Clone, PartialEq, PartialOrd)]
pub struct LogStandardDev(pub f64);
impl LogStandardDev {
pub fn from_log_standard_dev(log_std: f64) -> LogStandardDev {
LogStandardDev(log_std)
}
pub fn from_modular_log_standard_dev<Uint>(log_std: f64) -> LogStandardDev
where
Uint: UnsignedInteger,
{
LogStandardDev(log_std - Uint::BITS as f64)
}
}
impl DispersionParameter for LogStandardDev {
fn get_standard_dev(&self) -> f64 {
f64::powf(2., self.0)
}
fn get_variance(&self) -> f64 {
f64::powf(2., self.0 * 2.)
}
fn get_log_standard_dev(&self) -> f64 {
self.0
}
fn get_modular_standard_dev<Uint>(&self) -> f64
where
Uint: UnsignedInteger,
{
f64::powf(2., Uint::BITS as f64 + self.0)
}
fn get_modular_variance<Uint>(&self) -> f64
where
Uint: UnsignedInteger,
{
f64::powf(2., (Uint::BITS as f64 + self.0) * 2.)
}
fn get_modular_log_standard_dev<Uint>(&self) -> f64
where
Uint: UnsignedInteger,
{
Uint::BITS as f64 + self.0
}
}
#[derive(Debug, Copy, Clone, PartialEq, PartialOrd)]
pub struct StandardDev(f64);
impl StandardDev {
pub fn from_standard_dev(std: f64) -> StandardDev {
StandardDev(std)
}
pub fn from_modular_standard_dev<Uint>(std: f64) -> StandardDev
where
Uint: UnsignedInteger,
{
StandardDev(std / 2_f64.powf(Uint::BITS as f64))
}
}
impl DispersionParameter for StandardDev {
fn get_standard_dev(&self) -> f64 {
self.0
}
fn get_variance(&self) -> f64 {
self.0.powi(2)
}
fn get_log_standard_dev(&self) -> f64 {
self.0.log2()
}
fn get_modular_standard_dev<Uint>(&self) -> f64
where
Uint: UnsignedInteger,
{
2_f64.powf(Uint::BITS as f64 + self.0.log2())
}
fn get_modular_variance<Uint>(&self) -> f64
where
Uint: UnsignedInteger,
{
2_f64.powf(2. * (Uint::BITS as f64 + self.0.log2()))
}
fn get_modular_log_standard_dev<Uint>(&self) -> f64
where
Uint: UnsignedInteger,
{
Uint::BITS as f64 + self.0.log2()
}
}
#[derive(Debug, Copy, Clone, PartialEq, PartialOrd)]
pub struct Variance(pub f64);
impl Variance {
pub fn from_variance(var: f64) -> Variance {
Variance(var)
}
pub fn from_modular_variance<Uint>(var: f64) -> Variance
where
Uint: UnsignedInteger,
{
Variance(var / 2_f64.powf(Uint::BITS as f64 * 2.))
}
}
impl DispersionParameter for Variance {
fn get_standard_dev(&self) -> f64 {
self.0.sqrt()
}
fn get_variance(&self) -> f64 {
self.0
}
fn get_log_standard_dev(&self) -> f64 {
self.0.sqrt().log2()
}
fn get_modular_standard_dev<Uint>(&self) -> f64
where
Uint: UnsignedInteger,
{
2_f64.powf(Uint::BITS as f64 + self.0.sqrt().log2())
}
fn get_modular_variance<Uint>(&self) -> f64
where
Uint: UnsignedInteger,
{
2_f64.powf(2. * (Uint::BITS as f64 + self.0.sqrt().log2()))
}
fn get_modular_log_standard_dev<Uint>(&self) -> f64
where
Uint: UnsignedInteger,
{
Uint::BITS as f64 + self.0.sqrt().log2()
}
}