diff --git a/deferred_division/src/ratio.rs b/deferred_division/src/ratio.rs index 6ae0ad2..c5abad4 100644 --- a/deferred_division/src/ratio.rs +++ b/deferred_division/src/ratio.rs @@ -1,3 +1,5 @@ +use std::ops::Mul; + #[derive(Clone,Copy,Debug,Hash)] pub struct Ratio{ pub(crate)num:Num, @@ -8,3 +10,148 @@ impl Ratio{ Self{num,den} } } + +impl PartialEq for Ratio + where + Den:Copy, + Rhs:Mul+Copy, + Num:PartialEq<>::Output> +{ + fn eq(&self,rhs:&Rhs)->bool{ + self.num.eq(&rhs.mul(self.den)) + } +} +/* +//You can't do Ratio==Ratio I guess +impl Eq for Ratio +where + Num:Mul, + >::Output:PartialEq +{} +*/ + +// num/den == rhs +// num == rhs * den + +impl PartialOrd for Ratio + where + Den:Copy, + Rhs:Mul+Copy, + Num:PartialOrd<>::Output> +{ + fn partial_cmp(&self,rhs:&Rhs)->Option{ + self.num.partial_cmp(&rhs.mul(self.den)) + } +} +/* +impl Ord for Ratio<>::Output,Den> +where + Rhs:Mul, + Rhs:Ord, + >::Output:Ord, +{ + fn cmp(&self,other:&Rhs)->std::cmp::Ordering{ + self.num.cmp(&other.mul(self.den)) + } +} +*/ + +impl,Den> std::ops::Neg for Ratio{ + type Output=Ratio; + fn neg(self)->Self::Output{ + Ratio{ + num:self.num.neg(), + den:self.den, + } + } +} + +// num/den + rhs == new_num/den +// new_num = num + rhs * den + +macro_rules! impl_operator { + ($struct:ident,$trait:ident,$method:ident)=>{ + impl core::ops::$trait for $struct + where + Den:Copy, + Rhs:Mul, + Num:core::ops::$trait<>::Output>, + { + type Output=$struct<>::Output>>::Output,Den>; + + fn $method(self,rhs:Rhs)->Self::Output{ + $struct{ + num:self.num.$method(rhs.mul(self.den)), + den:self.den, + } + } + } + }; +} +macro_rules! impl_assign_operator{ + ($struct:ident,$trait:ident,$method:ident)=>{ + impl core::ops::$trait for $struct + where + Den:Copy, + Rhs:Mul, + Num:core::ops::$trait<>::Output>, + { + fn $method(&mut self,rhs:Rhs){ + self.num.$method(rhs.mul(self.den)); + } + } + }; +} + +// Impl arithmetic operators +impl_assign_operator!(Ratio,AddAssign,add_assign); +impl_operator!(Ratio,Add,add); +impl_assign_operator!(Ratio,SubAssign,sub_assign); +impl_operator!(Ratio,Sub,sub); +// num/den % rhs == new_num/den +// new_num = num % (rhs * den) +impl_assign_operator!(Ratio,RemAssign,rem_assign); +impl_operator!(Ratio,Rem,rem); + +//mul and div is special +impl Mul for Ratio + where + Num:Mul, +{ + type Output=Ratio<>::Output,Den>; + fn mul(self,rhs:Rhs)->Self::Output{ + Ratio{ + num:self.num.mul(rhs), + den:self.den, + } + } +} +impl core::ops::MulAssign for Ratio + where + Num:core::ops::MulAssign, +{ + fn mul_assign(&mut self,rhs:Rhs){ + self.num.mul_assign(rhs); + } +} + +impl core::ops::Div for Ratio + where + Den:Mul, +{ + type Output=Ratio>::Output>; + fn div(self,rhs:Rhs)->Self::Output{ + Ratio{ + num:self.num, + den:self.den.mul(rhs), + } + } +} +impl core::ops::DivAssign for Ratio + where + Den:core::ops::MulAssign, +{ + fn div_assign(&mut self,rhs:Rhs){ + self.den.mul_assign(rhs); + } +}