const-frac 0.0.3

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:: { Bounded, NumAssign, NumCast, Pow, Signed };
#[cfg(feature = "ratio")]
use num_integer::Integer;
/// 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<T> Real for Ratio<T>
where
    T: Clone + Debug
     + From<i128>
     + Integer
     + Neg<Output = T> + NumAssign + Signed + Bounded + NumCast + Pow<u32, Output = T> ,
{
    fn from_int(i: isize) -> Self {
        Ratio::new(
            <T as NumCast>::from(i).unwrap(),
            <T as NumCast>::from(1).unwrap()
        )
    }
    
    fn from_f64(d: f64) -> Self {
        Ratio::approximate_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 n128 = self.numer().clone().pow(n as u32);
        let d128 = self.denom().clone().pow(n as u32);

        Self::new(n128.into(), d128.into())
    }
}

#[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);
    }
}