From 085d9185a95691e94a8d438d2b8fccc26faaf83f Mon Sep 17 00:00:00 2001 From: Quaternions Date: Tue, 10 Sep 2024 13:04:43 -0700 Subject: [PATCH] ratio operators --- ratio_ops/src/ratio.rs | 165 ++++++++++++++++++++++++++++++++++++++++- 1 file changed, 163 insertions(+), 2 deletions(-) diff --git a/ratio_ops/src/ratio.rs b/ratio_ops/src/ratio.rs index 6ae0ad2..7f806da 100644 --- a/ratio_ops/src/ratio.rs +++ b/ratio_ops/src/ratio.rs @@ -1,10 +1,171 @@ #[derive(Clone,Copy,Debug,Hash)] pub struct Ratio{ - pub(crate)num:Num, - pub(crate)den:Den, + pub num:Num, + pub den:Den, } impl Ratio{ + #[inline(always)] pub const fn new(num:Num,den:Den)->Self{ Self{num,den} } } + +impl Ratio + where + Num:core::ops::Div, +{ + #[inline] + pub fn divide(num:Num,den:Den)->>::Output{ + num/den + } +} + +//take care to use the ratio methods to avoid nested ratios + +impl Ratio{ + #[inline] + pub fn mul_ratio(self,rhs:Ratio)->Ratio<>::Output,>::Output> + where + LhsNum:core::ops::Mul, + LhsDen:core::ops::Mul, + { + Ratio::new(self.num*rhs.num,self.den*rhs.den) + } + #[inline] + pub fn div_ratio(self,rhs:Ratio)->Ratio<>::Output,>::Output> + where + LhsNum:core::ops::Mul, + LhsDen:core::ops::Mul, + { + Ratio::new(self.num*rhs.den,self.den*rhs.num) + } +} +macro_rules! impl_ratio_method { + ($trait:ident, $method:ident, $ratio_method:ident) => { + impl Ratio{ + #[inline] + pub fn $ratio_method(self,rhs:Ratio)->Ratio<>::Output,>::Output> + where + LhsNum:core::ops::Mul, + LhsDen:core::ops::Mul, + LhsDen:core::ops::Mul, + LhsDen:Copy, + RhsDen:Copy, + LhsCrossMul:core::ops::$trait, + { + Ratio::new((self.num*rhs.den).$method(self.den*rhs.num),self.den*rhs.den) + } + } + }; +} +impl_ratio_method!(Add,add,add_ratio); +impl_ratio_method!(Sub,sub,sub_ratio); +impl_ratio_method!(Rem,rem,rem_ratio); + +/* generic rhs mul is not possible! +impl core::ops::Mul> for Lhs + where + Lhs:core::ops::Mul, +{ + type Output=Ratio<>::Output,RhsDen>; + #[inline] + fn mul(self,rhs:Ratio)->Self::Output{ + Ratio::new(self*rhs.num,rhs.den) + } +} +*/ + +//operators + +impl core::ops::Neg for Ratio + where + LhsNum:core::ops::Neg, +{ + type Output=Ratio<::Output,LhsDen>; + #[inline] + fn neg(self)->Self::Output{ + Ratio::new(-self.num,self.den) + } +} +impl core::ops::Mul for Ratio + where + LhsNum:core::ops::Mul, +{ + type Output=Ratio<>::Output,LhsDen>; + #[inline] + fn mul(self,rhs:Rhs)->Self::Output{ + Ratio::new(self.num*rhs,self.den) + } +} +impl core::ops::Div for Ratio + where + LhsDen:core::ops::Mul, +{ + type Output=Ratio>::Output>; + #[inline] + fn div(self,rhs:Rhs)->Self::Output{ + Ratio::new(self.num,self.den*rhs) + } +} + +macro_rules! impl_ratio_operator { + ($trait:ident, $method:ident) => { + impl core::ops::$trait for Ratio + where + LhsNum:core::ops::$trait, + LhsDen:Copy, + Rhs:core::ops::Mul, + { + type Output=Ratio<>::Output,LhsDen>; + #[inline] + fn $method(self,rhs:Rhs)->Self::Output{ + Ratio::new(self.num.$method(rhs*self.den),self.den) + } + } + }; +} + +impl_ratio_operator!(Add,add); +impl_ratio_operator!(Sub,sub); +impl_ratio_operator!(Rem,rem); + +//assign operators + +impl core::ops::MulAssign for Ratio + where + LhsNum:core::ops::MulAssign, +{ + #[inline] + fn mul_assign(&mut self,rhs:Rhs){ + self.num*=rhs; + } +} +impl core::ops::DivAssign for Ratio + where + LhsDen:core::ops::MulAssign, +{ + #[inline] + fn div_assign(&mut self,rhs:Rhs){ + self.den*=rhs; + } +} + +macro_rules! impl_ratio_assign_operator { + ($trait:ident, $method:ident) => { + impl core::ops::$trait for Ratio + where + LhsNum:core::ops::$trait, + LhsDen:Copy, + Rhs:core::ops::Mul, + { + #[inline] + fn $method(&mut self,rhs:Rhs){ + self.num.$method(rhs*self.den) + } + } + }; +} + +impl_ratio_assign_operator!(AddAssign,add_assign); +impl_ratio_assign_operator!(SubAssign,sub_assign); +impl_ratio_assign_operator!(RemAssign,rem_assign);