158 lines
3.2 KiB
Rust
158 lines
3.2 KiB
Rust
use std::ops::Mul;
|
|
|
|
#[derive(Clone,Copy,Debug,Hash)]
|
|
pub struct Ratio<Num,Den>{
|
|
pub(crate)num:Num,
|
|
pub(crate)den:Den,
|
|
}
|
|
impl<Num,Den> Ratio<Num,Den>{
|
|
pub const fn new(num:Num,den:Den)->Self{
|
|
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);
|
|
}
|
|
}
|