gstreamer/fraction: Add impls for various other arithmetic operations on fractions

Any arithmetic operation on plain values or references in any order
should be possible now, and on fractions with i32.
This commit is contained in:
Sebastian Dröge 2019-06-03 10:56:40 +03:00 committed by Sebastian Dröge
parent c774bd8114
commit b2ffe98d59

View file

@ -66,85 +66,135 @@ impl AsRef<Rational32> for Fraction {
} }
} }
impl ops::Mul<Fraction> for Fraction { macro_rules! impl_fraction_binop {
type Output = Fraction; ($name:ident, $f:ident, $name_assign:ident, $f_assign:ident) => {
impl ops::$name<Fraction> for Fraction {
type Output = Fraction;
fn mul(self, other: Fraction) -> Fraction { fn $f(self, other: Fraction) -> Fraction {
Fraction(self.0.mul(other.0)) Fraction((self.0).$f(other.0))
} }
}
impl ops::$name<Fraction> for &Fraction {
type Output = Fraction;
fn $f(self, other: Fraction) -> Fraction {
Fraction((self.0).$f(other.0))
}
}
impl ops::$name<&Fraction> for Fraction {
type Output = Fraction;
fn $f(self, other: &Fraction) -> Fraction {
Fraction((self.0).$f(other.0))
}
}
impl ops::$name<&Fraction> for &Fraction {
type Output = Fraction;
fn $f(self, other: &Fraction) -> Fraction {
Fraction((self.0).$f(other.0))
}
}
impl ops::$name<i32> for Fraction {
type Output = Fraction;
fn $f(self, other: i32) -> Fraction {
self.$f(Fraction::from(other))
}
}
impl ops::$name<i32> for &Fraction {
type Output = Fraction;
fn $f(self, other: i32) -> Fraction {
self.$f(Fraction::from(other))
}
}
impl ops::$name<&i32> for Fraction {
type Output = Fraction;
fn $f(self, other: &i32) -> Fraction {
self.$f(Fraction::from(*other))
}
}
impl ops::$name<&i32> for &Fraction {
type Output = Fraction;
fn $f(self, other: &i32) -> Fraction {
self.$f(Fraction::from(*other))
}
}
impl ops::$name<Fraction> for i32 {
type Output = Fraction;
fn $f(self, other: Fraction) -> Fraction {
Fraction::from(self).$f(other)
}
}
impl ops::$name<&Fraction> for i32 {
type Output = Fraction;
fn $f(self, other: &Fraction) -> Fraction {
Fraction::from(self).$f(other)
}
}
impl ops::$name<Fraction> for &i32 {
type Output = Fraction;
fn $f(self, other: Fraction) -> Fraction {
Fraction::from(*self).$f(other)
}
}
impl ops::$name<&Fraction> for &i32 {
type Output = Fraction;
fn $f(self, other: &Fraction) -> Fraction {
Fraction::from(*self).$f(other)
}
}
impl ops::$name_assign<Fraction> for Fraction {
fn $f_assign(&mut self, other: Fraction) {
(self.0).$f_assign(other.0)
}
}
impl ops::$name_assign<&Fraction> for Fraction {
fn $f_assign(&mut self, other: &Fraction) {
(self.0).$f_assign(other.0)
}
}
impl ops::$name_assign<i32> for Fraction {
fn $f_assign(&mut self, other: i32) {
(self.0).$f_assign(other)
}
}
impl ops::$name_assign<&i32> for Fraction {
fn $f_assign(&mut self, other: &i32) {
(self.0).$f_assign(other)
}
}
};
} }
impl ops::Mul<i32> for Fraction { impl_fraction_binop!(Add, add, AddAssign, add_assign);
type Output = Fraction; impl_fraction_binop!(Sub, sub, SubAssign, sub_assign);
impl_fraction_binop!(Div, div, DivAssign, div_assign);
fn mul(self, other: i32) -> Fraction { impl_fraction_binop!(Mul, mul, MulAssign, mul_assign);
self.mul(Fraction::from(other)) impl_fraction_binop!(Rem, rem, RemAssign, rem_assign);
}
}
impl ops::Div<Fraction> for Fraction {
type Output = Fraction;
fn div(self, other: Fraction) -> Fraction {
Fraction(self.0.div(other.0))
}
}
impl ops::Div<i32> for Fraction {
type Output = Fraction;
fn div(self, other: i32) -> Fraction {
self.div(Fraction::from(other))
}
}
impl ops::Add<Fraction> for Fraction {
type Output = Fraction;
fn add(self, other: Fraction) -> Fraction {
Fraction(self.0.add(other.0))
}
}
impl ops::Add<i32> for Fraction {
type Output = Fraction;
fn add(self, other: i32) -> Fraction {
self.add(Fraction::from(other))
}
}
impl ops::Sub<Fraction> for Fraction {
type Output = Fraction;
fn sub(self, other: Fraction) -> Fraction {
Fraction(self.0.sub(other.0))
}
}
impl ops::Sub<i32> for Fraction {
type Output = Fraction;
fn sub(self, other: i32) -> Fraction {
self.sub(Fraction::from(other))
}
}
impl ops::Rem<Fraction> for Fraction {
type Output = Fraction;
fn rem(self, other: Fraction) -> Fraction {
Fraction(self.0.rem(other.0))
}
}
impl ops::Rem<i32> for Fraction {
type Output = Fraction;
fn rem(self, other: i32) -> Fraction {
self.rem(Fraction::from(other))
}
}
impl ops::Neg for Fraction { impl ops::Neg for Fraction {
type Output = Fraction; type Output = Fraction;
@ -154,6 +204,14 @@ impl ops::Neg for Fraction {
} }
} }
impl ops::Neg for &Fraction {
type Output = Fraction;
fn neg(self) -> Fraction {
Fraction(self.0.neg())
}
}
impl From<i32> for Fraction { impl From<i32> for Fraction {
fn from(x: i32) -> Fraction { fn from(x: i32) -> Fraction {
assert_initialized_main_thread!(); assert_initialized_main_thread!();
@ -842,3 +900,20 @@ impl GstValueExt for glib::Value {
} }
} }
} }
#[cfg(test)]
mod tests {
#[test]
fn test_fraction() {
::init().unwrap();
let f1 = ::Fraction::new(1, 2);
let f2 = ::Fraction::new(2, 3);
let mut f3 = f1 * f2;
let f4 = f1 * &f2;
f3 *= f2;
f3 *= &f4;
assert_eq!(f3, ::Fraction::new(2, 27));
}
}