const-frac 0.0.1

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

#[cfg(feature = "num")]
use num:: {
    self, Integer,
    rational::Ratio,
    traits::NumAssign,
};

/// 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_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_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 = "num")]
impl<T> Real for Ratio<T>
where
    T: Clone + Debug + From<i128>,
{
    fn from_f64(d: f64) -> Self {
        Ratio::approximate_float(d).unwrap()
    }

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

    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 {
        self.pow(n as i32)
    }
}

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