ebi_arithmetic 0.3.13

Exact arithmetic for Ebi - a stochastic process mining utility
Documentation
use crate::{
    MaybeExact, is_exact_globally,
    log_polynomial::{
        log_polynomial_enum::LogPolynomialEnum, log_polynomial_exact::LogPolynomialExact,
        log_polynomial_f64::LogPolynomialF64,
    },
};
use anyhow::{Result, anyhow};

impl MaybeExact for LogPolynomialExact {
    type Approximate = LogPolynomialF64;
    type Exact = LogPolynomialExact;

    fn is_exact(&self) -> bool {
        true
    }

    fn approx_ref(&self) -> Result<&Self::Approximate> {
        Err(anyhow!("cannot extract a float from a fraction"))
    }

    fn exact_ref(&self) -> Result<&Self::Exact> {
        Ok(self)
    }

    fn approx(self) -> Result<Self::Approximate> {
        Err(anyhow!("cannot extract a float from a fraction"))
    }

    fn exact(self) -> Result<Self::Exact> {
        Ok(self)
    }

    fn try_to_exact(exact: Self::Exact) -> Result<Self> {
        Ok(exact)
    }

    fn try_to_approx(_: Self::Approximate) -> Result<Self> {
        Err(anyhow!("cannot put float in a fraction"))
    }
}

impl MaybeExact for LogPolynomialF64 {
    type Approximate = LogPolynomialF64;
    type Exact = LogPolynomialExact;

    fn is_exact(&self) -> bool {
        false
    }

    fn approx_ref(&self) -> Result<&Self::Approximate> {
        Ok(self)
    }

    fn exact_ref(&self) -> Result<&Self::Exact> {
        Err(anyhow!("cannot extract a fraction from a float"))
    }

    fn approx(self) -> Result<Self::Approximate> {
        Ok(self)
    }

    fn exact(self) -> Result<Self::Exact> {
        Err(anyhow!("cannot extract a fraction from a float"))
    }

    fn try_to_exact(_: Self::Exact) -> Result<Self> {
        Err(anyhow!("cannot put fraction in a float"))
    }

    fn try_to_approx(approx: Self::Approximate) -> Result<Self> {
        Ok(approx)
    }
}

impl MaybeExact for LogPolynomialEnum {
    type Approximate = LogPolynomialF64;
    type Exact = LogPolynomialExact;

    fn is_exact(&self) -> bool {
        match self {
            LogPolynomialEnum::Approx(_) => false,
            LogPolynomialEnum::Exact(_) => true,
            LogPolynomialEnum::CannotCombineExactAndApprox => false,
        }
    }

    fn approx_ref(&self) -> Result<&Self::Approximate> {
        match self {
            LogPolynomialEnum::Approx(f) => Ok(f),
            LogPolynomialEnum::Exact(_) => Err(anyhow!("cannot extract a fraction from a float")),
            LogPolynomialEnum::CannotCombineExactAndApprox => {
                Err(anyhow!("Cannot combine exact and approximate arithmetic."))
            }
        }
    }

    fn exact_ref(&self) -> Result<&<LogPolynomialEnum as MaybeExact>::Exact> {
        match self {
            LogPolynomialEnum::Approx(_) => Err(anyhow!("cannot extract a float from a fraction")),
            LogPolynomialEnum::Exact(f) => Ok(f),
            LogPolynomialEnum::CannotCombineExactAndApprox => {
                Err(anyhow!("Cannot combine exact and approximate arithmetic."))
            }
        }
    }

    fn approx(self) -> Result<Self::Approximate> {
        match self {
            LogPolynomialEnum::Approx(f) => Ok(f),
            LogPolynomialEnum::Exact(_) => Err(anyhow!("cannot extract a fraction from a float")),
            LogPolynomialEnum::CannotCombineExactAndApprox => {
                Err(anyhow!("Cannot combine exact and approximate arithmetic."))
            }
        }
    }

    fn exact(self) -> Result<<LogPolynomialEnum as MaybeExact>::Exact> {
        match self {
            LogPolynomialEnum::Approx(_) => Err(anyhow!("cannot extract a float from a fraction")),
            LogPolynomialEnum::Exact(f) => Ok(f),
            LogPolynomialEnum::CannotCombineExactAndApprox => {
                Err(anyhow!("Cannot combine exact and approximate arithmetic."))
            }
        }
    }

    fn try_to_exact(exact: <Self as MaybeExact>::Exact) -> Result<Self> {
        if is_exact_globally() {
            Ok(Self::Exact(exact))
        } else {
            Err(anyhow!("cannot put float in a fraction"))
        }
    }

    fn try_to_approx(approx: Self::Approximate) -> Result<Self> {
        if !is_exact_globally() {
            Ok(Self::Approx(approx))
        } else {
            Err(anyhow!("cannot put fraction in a float"))
        }
    }
}