use std::{
cmp::Ordering,
error::Error,
fmt::{self, Display, Formatter}
};
use crate::Weight;
#[derive(Debug, Clone)]
pub struct Probability
{
numerator: Weight,
denominator: Weight
}
impl Probability
{
pub const ZERO: Self = Self {
numerator: Weight::ZERO,
denominator: Weight::ONE
};
pub const ONE: Self = Self {
numerator: Weight::ONE,
denominator: Weight::ONE
};
pub fn new(
numerator: Weight,
denominator: Weight
) -> Result<Self, ProbabilityError>
{
if denominator.is_zero()
{
return Err(ProbabilityError::ZeroDenominator)
}
if numerator > denominator
{
return Err(ProbabilityError::ExceedsOne)
}
Ok(Self::new_unchecked(numerator, denominator))
}
pub(crate) fn new_unchecked(numerator: Weight, denominator: Weight)
-> Self
{
debug_assert!(!denominator.is_zero() && numerator <= denominator);
Self {
numerator,
denominator
}
}
#[inline]
pub fn numerator(&self) -> &Weight { &self.numerator }
#[inline]
pub fn denominator(&self) -> &Weight { &self.denominator }
pub fn to_f64(&self) -> f64
{
self.numerator.ratio_to_f64(&self.denominator)
}
}
impl PartialEq for Probability
{
fn eq(&self, other: &Self) -> bool { self.cmp(other) == Ordering::Equal }
}
impl Eq for Probability {}
impl PartialOrd for Probability
{
fn partial_cmp(&self, other: &Self) -> Option<Ordering>
{
Some(self.cmp(other))
}
}
impl Ord for Probability
{
fn cmp(&self, other: &Self) -> Ordering
{
if self.denominator == other.denominator
{
return self.numerator.cmp(&other.numerator)
}
(&self.numerator * &other.denominator)
.cmp(&(&other.numerator * &self.denominator))
}
}
impl Display for Probability
{
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result
{
write!(f, "{}/{}", self.numerator, self.denominator)
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum ProbabilityError
{
ZeroDenominator,
ExceedsOne
}
impl Display for ProbabilityError
{
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result
{
match self
{
Self::ZeroDenominator =>
{
write!(f, "probability has a zero denominator")
},
Self::ExceedsOne => write!(f, "probability exceeds one")
}
}
}
impl Error for ProbabilityError {}