const-frac 0.0.4

Types for supporting floating point constants.
Documentation
use core:: {
    fmt::Debug,
    ops:: {
        Add, AddAssign,
        Sub, SubAssign,
        Mul, MulAssign,
        Div, DivAssign,
        Neg
    },
};

#[cfg(feature = "ratio")]
use num_rational::Ratio;
#[cfg(feature = "ratio")]
use num_traits:: { One, Pow };
#[cfg(feature = "ratio")]
use num_bigint::BigInt;


/// Requirements for a type which represents real value.
pub trait Real
    : Clone
    + Debug
    + PartialEq
    + PartialOrd
    + Add<Output = Self> + AddAssign
    + Sub<Output = Self> + SubAssign
    + Mul<Output = Self> + MulAssign
    + Div<Output = Self> + DivAssign
    + Neg<Output = Self>
{
    fn from_int(i: isize) -> Self;
    fn from_f64(d: f64) -> Self;
    fn from_frac(frac: crate::Frac) -> Self;
    fn add_ref(self, rhs: &Self) -> Self;
    fn sub_ref(self, rhs: &Self) -> Self;
    fn mul_ref(self, rhs: &Self) -> Self;
    fn div_ref(self, rhs: &Self) -> Self;
    fn poweri(self, n: i16) -> Self;
}

impl Real for f64 {
    fn from_int(i: isize) -> Self { i as f64 }
    fn from_f64(d: f64) -> Self { d }

    fn from_frac(frac: crate::Frac) -> Self {
        frac.to_f64()
    }

    fn add_ref(self, rhs: &Self) -> Self { self + rhs }
    fn sub_ref(self, rhs: &Self) -> Self { self - rhs }
    fn mul_ref(self, rhs: &Self) -> Self { self * rhs }
    fn div_ref(self, rhs: &Self) -> Self { self / rhs }

    #[cfg(feature = "std")]
    fn poweri(self, n: i16) -> Self {
        self.powi(n as i32)
    }

    #[cfg(not(feature = "std"))]
    fn poweri(self, mut n: i16) -> Self {
        let mut retval = 1f64;

        while n > 0 {
            retval *= self;
            n -= 1;
        }
        retval
    }
}

#[cfg(feature = "ratio")]
impl Real for Ratio<BigInt> {
    fn from_int(i: isize) -> Self {
        Self::new(
            i.into(),
            <BigInt as One>::one()
        )
    }

    fn from_f64(d: f64) -> Self {
        Self::from_float(d).unwrap()
    }

    fn from_frac(frac: crate::Frac) -> Self {
        frac.into()
    }

    fn add_ref(self, rhs: &Self) -> Self { self + rhs }
    fn sub_ref(self, rhs: &Self) -> Self { self - rhs }
    fn mul_ref(self, rhs: &Self) -> Self { self * rhs }
    fn div_ref(self, rhs: &Self) -> Self { self / rhs }

    fn poweri(self, n: i16) -> Self {
        let numer = self.numer().clone().pow(n as u32);
        let denom = self.denom().clone().pow(n as u32);

        Self::new(numer, denom)
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use crate::Frac;

    #[test]
    fn test_infer() {
        let d: f64 = Default::default();
        let dd: f64 = Real::from_frac(Frac::from_int(1));

        assert_eq!(d, 0.0);
        assert_eq!(dd, 1.0);
    }
}