ratio operators

This commit is contained in:
Quaternions 2024-08-28 15:21:36 -07:00
parent 617952c1e3
commit ac250e9d84

View File

@ -1,3 +1,5 @@
use std::ops::Mul;
#[derive(Clone,Copy,Debug,Hash)] #[derive(Clone,Copy,Debug,Hash)]
pub struct Ratio<Num,Den>{ pub struct Ratio<Num,Den>{
pub(crate)num:Num, pub(crate)num:Num,
@ -8,3 +10,148 @@ impl<Num,Den> Ratio<Num,Den>{
Self{num,den} Self{num,den}
} }
} }
impl<Num,Den,Rhs> PartialEq<Rhs> for Ratio<Num,Den>
where
Den:Copy,
Rhs:Mul<Den>+Copy,
Num:PartialEq<<Rhs as Mul<Den>>::Output>
{
fn eq(&self,rhs:&Rhs)->bool{
self.num.eq(&rhs.mul(self.den))
}
}
/*
//You can't do Ratio==Ratio I guess
impl<Num,Den> Eq for Ratio<Num,Den>
where
Num:Mul<Den>,
<Num as Mul<Den>>::Output:PartialEq
{}
*/
// num/den == rhs
// num == rhs * den
impl<Num,Den,Rhs> PartialOrd<Rhs> for Ratio<Num,Den>
where
Den:Copy,
Rhs:Mul<Den>+Copy,
Num:PartialOrd<<Rhs as Mul<Den>>::Output>
{
fn partial_cmp(&self,rhs:&Rhs)->Option<std::cmp::Ordering>{
self.num.partial_cmp(&rhs.mul(self.den))
}
}
/*
impl<Den,Rhs> Ord for Ratio<<Rhs as Mul<Den>>::Output,Den>
where
Rhs:Mul<Den>,
Rhs:Ord,
<Rhs as Mul<Den>>::Output:Ord,
{
fn cmp(&self,other:&Rhs)->std::cmp::Ordering{
self.num.cmp(&other.mul(self.den))
}
}
*/
impl<NewNum,Num:std::ops::Neg<Output=NewNum>,Den> std::ops::Neg for Ratio<Num,Den>{
type Output=Ratio<NewNum,Den>;
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<Num,Den,Rhs> core::ops::$trait<Rhs> for $struct<Num,Den>
where
Den:Copy,
Rhs:Mul<Den>,
Num:core::ops::$trait<<Rhs as Mul<Den>>::Output>,
{
type Output=$struct<<Num as core::ops::$trait<<Rhs as Mul<Den>>::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<Num,Den,Rhs> core::ops::$trait<Rhs> for $struct<Num,Den>
where
Den:Copy,
Rhs:Mul<Den>,
Num:core::ops::$trait<<Rhs as Mul<Den>>::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<Num,Den,Rhs> Mul<Rhs> for Ratio<Num,Den>
where
Num:Mul<Rhs>,
{
type Output=Ratio<<Num as Mul<Rhs>>::Output,Den>;
fn mul(self,rhs:Rhs)->Self::Output{
Ratio{
num:self.num.mul(rhs),
den:self.den,
}
}
}
impl<Num,Den,Rhs> core::ops::MulAssign<Rhs> for Ratio<Num,Den>
where
Num:core::ops::MulAssign<Rhs>,
{
fn mul_assign(&mut self,rhs:Rhs){
self.num.mul_assign(rhs);
}
}
impl<Num,Den,Rhs> core::ops::Div<Rhs> for Ratio<Num,Den>
where
Den:Mul<Rhs>,
{
type Output=Ratio<Num,<Den as Mul<Rhs>>::Output>;
fn div(self,rhs:Rhs)->Self::Output{
Ratio{
num:self.num,
den:self.den.mul(rhs),
}
}
}
impl<Num,Den,Rhs> core::ops::DivAssign<Rhs> for Ratio<Num,Den>
where
Den:core::ops::MulAssign<Rhs>,
{
fn div_assign(&mut self,rhs:Rhs){
self.den.mul_assign(rhs);
}
}