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