ratio operators
This commit is contained in:
parent
1fd7a6eafd
commit
085d9185a9
@ -1,10 +1,171 @@
|
||||
#[derive(Clone,Copy,Debug,Hash)]
|
||||
pub struct Ratio<Num,Den>{
|
||||
pub(crate)num:Num,
|
||||
pub(crate)den:Den,
|
||||
pub num:Num,
|
||||
pub den:Den,
|
||||
}
|
||||
impl<Num,Den> Ratio<Num,Den>{
|
||||
#[inline(always)]
|
||||
pub const fn new(num:Num,den:Den)->Self{
|
||||
Self{num,den}
|
||||
}
|
||||
}
|
||||
|
||||
impl<Num,Den> Ratio<Num,Den>
|
||||
where
|
||||
Num:core::ops::Div<Den>,
|
||||
{
|
||||
#[inline]
|
||||
pub fn divide(num:Num,den:Den)-><Num as core::ops::Div<Den>>::Output{
|
||||
num/den
|
||||
}
|
||||
}
|
||||
|
||||
//take care to use the ratio methods to avoid nested ratios
|
||||
|
||||
impl<LhsNum,LhsDen> Ratio<LhsNum,LhsDen>{
|
||||
#[inline]
|
||||
pub fn mul_ratio<RhsNum,RhsDen>(self,rhs:Ratio<RhsNum,RhsDen>)->Ratio<<LhsNum as core::ops::Mul<RhsNum>>::Output,<LhsDen as core::ops::Mul<RhsDen>>::Output>
|
||||
where
|
||||
LhsNum:core::ops::Mul<RhsNum>,
|
||||
LhsDen:core::ops::Mul<RhsDen>,
|
||||
{
|
||||
Ratio::new(self.num*rhs.num,self.den*rhs.den)
|
||||
}
|
||||
#[inline]
|
||||
pub fn div_ratio<RhsNum,RhsDen>(self,rhs:Ratio<RhsNum,RhsDen>)->Ratio<<LhsNum as core::ops::Mul<RhsDen>>::Output,<LhsDen as core::ops::Mul<RhsNum>>::Output>
|
||||
where
|
||||
LhsNum:core::ops::Mul<RhsDen>,
|
||||
LhsDen:core::ops::Mul<RhsNum>,
|
||||
{
|
||||
Ratio::new(self.num*rhs.den,self.den*rhs.num)
|
||||
}
|
||||
}
|
||||
macro_rules! impl_ratio_method {
|
||||
($trait:ident, $method:ident, $ratio_method:ident) => {
|
||||
impl<LhsNum,LhsDen> Ratio<LhsNum,LhsDen>{
|
||||
#[inline]
|
||||
pub fn $ratio_method<RhsNum,RhsDen,LhsCrossMul,RhsCrossMul>(self,rhs:Ratio<RhsNum,RhsDen>)->Ratio<<LhsCrossMul as core::ops::$trait<RhsCrossMul>>::Output,<LhsDen as core::ops::Mul<RhsDen>>::Output>
|
||||
where
|
||||
LhsNum:core::ops::Mul<RhsDen,Output=LhsCrossMul>,
|
||||
LhsDen:core::ops::Mul<RhsNum,Output=RhsCrossMul>,
|
||||
LhsDen:core::ops::Mul<RhsDen>,
|
||||
LhsDen:Copy,
|
||||
RhsDen:Copy,
|
||||
LhsCrossMul:core::ops::$trait<RhsCrossMul>,
|
||||
{
|
||||
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<Lhs,RhsNum,RhsDen> core::ops::Mul<Ratio<RhsNum,RhsDen>> for Lhs
|
||||
where
|
||||
Lhs:core::ops::Mul<RhsNum>,
|
||||
{
|
||||
type Output=Ratio<<Lhs as core::ops::Mul<RhsNum>>::Output,RhsDen>;
|
||||
#[inline]
|
||||
fn mul(self,rhs:Ratio<RhsNum,RhsDen>)->Self::Output{
|
||||
Ratio::new(self*rhs.num,rhs.den)
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
//operators
|
||||
|
||||
impl<LhsNum,LhsDen> core::ops::Neg for Ratio<LhsNum,LhsDen>
|
||||
where
|
||||
LhsNum:core::ops::Neg,
|
||||
{
|
||||
type Output=Ratio<<LhsNum as core::ops::Neg>::Output,LhsDen>;
|
||||
#[inline]
|
||||
fn neg(self)->Self::Output{
|
||||
Ratio::new(-self.num,self.den)
|
||||
}
|
||||
}
|
||||
impl<LhsNum,LhsDen,Rhs> core::ops::Mul<Rhs> for Ratio<LhsNum,LhsDen>
|
||||
where
|
||||
LhsNum:core::ops::Mul<Rhs>,
|
||||
{
|
||||
type Output=Ratio<<LhsNum as core::ops::Mul<Rhs>>::Output,LhsDen>;
|
||||
#[inline]
|
||||
fn mul(self,rhs:Rhs)->Self::Output{
|
||||
Ratio::new(self.num*rhs,self.den)
|
||||
}
|
||||
}
|
||||
impl<LhsNum,LhsDen,Rhs> core::ops::Div<Rhs> for Ratio<LhsNum,LhsDen>
|
||||
where
|
||||
LhsDen:core::ops::Mul<Rhs>,
|
||||
{
|
||||
type Output=Ratio<LhsNum,<LhsDen as core::ops::Mul<Rhs>>::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<LhsNum,LhsDen,Rhs,Intermediate> core::ops::$trait<Rhs> for Ratio<LhsNum,LhsDen>
|
||||
where
|
||||
LhsNum:core::ops::$trait<Intermediate>,
|
||||
LhsDen:Copy,
|
||||
Rhs:core::ops::Mul<LhsDen,Output=Intermediate>,
|
||||
{
|
||||
type Output=Ratio<<LhsNum as core::ops::$trait<Intermediate>>::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<LhsNum,LhsDen,Rhs> core::ops::MulAssign<Rhs> for Ratio<LhsNum,LhsDen>
|
||||
where
|
||||
LhsNum:core::ops::MulAssign<Rhs>,
|
||||
{
|
||||
#[inline]
|
||||
fn mul_assign(&mut self,rhs:Rhs){
|
||||
self.num*=rhs;
|
||||
}
|
||||
}
|
||||
impl<LhsNum,LhsDen,Rhs> core::ops::DivAssign<Rhs> for Ratio<LhsNum,LhsDen>
|
||||
where
|
||||
LhsDen:core::ops::MulAssign<Rhs>,
|
||||
{
|
||||
#[inline]
|
||||
fn div_assign(&mut self,rhs:Rhs){
|
||||
self.den*=rhs;
|
||||
}
|
||||
}
|
||||
|
||||
macro_rules! impl_ratio_assign_operator {
|
||||
($trait:ident, $method:ident) => {
|
||||
impl<LhsNum,LhsDen,Rhs> core::ops::$trait<Rhs> for Ratio<LhsNum,LhsDen>
|
||||
where
|
||||
LhsNum:core::ops::$trait,
|
||||
LhsDen:Copy,
|
||||
Rhs:core::ops::Mul<LhsDen,Output=LhsNum>,
|
||||
{
|
||||
#[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);
|
||||
|
Loading…
Reference in New Issue
Block a user