From 840fa71e67ac9da230318e44343ba26d59f9c84f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Hlusi=C4=8Dka?= Date: Thu, 25 Aug 2016 19:51:01 +0200 Subject: [PATCH] implement common operations for references --- src/structs/common_macros.rs | 298 ++++++++++++++++++++++++----------- 1 file changed, 206 insertions(+), 92 deletions(-) diff --git a/src/structs/common_macros.rs b/src/structs/common_macros.rs index 78fabb5e..a3583a38 100644 --- a/src/structs/common_macros.rs +++ b/src/structs/common_macros.rs @@ -1,5 +1,49 @@ #![macro_use] +macro_rules! ref_binop( + // Symmetric to `std::ops::forward_ref_binop!` + (impl $imp:ident, $method:ident for $t:ident; $($compN:ident),+) => { + impl<'a, 'b, N> $imp<&'a $t> for &'b $t where &'b N: $imp<&'a N, Output = N> { + type Output = $t; + + #[inline] + fn $method(self, right: &'a $t) -> $t { + $t::new( + $( + $imp::$method(&self.$compN, &right.$compN) + ),+ + ) + } + } + + impl<'a, N> $imp<&'a $t> for $t where N: $imp<&'a N, Output = N> { + type Output = $t; + + #[inline] + fn $method(self, right: &'a $t) -> $t { + $t::new( + $( + $imp::$method(self.$compN, &right.$compN) + ),+ + ) + } + } + + impl<'a, N> $imp<$t> for &'a $t where &'a N: $imp { + type Output = $t; + + #[inline] + fn $method(self, right: $t) -> $t { + $t::new( + $( + $imp::$method(&self.$compN, right.$compN) + ),+ + ) + } + } + } +); + macro_rules! pointwise_mul( ($t: ident, $($compN: ident),+) => ( impl> Mul<$t> for $t { @@ -17,6 +61,8 @@ macro_rules! pointwise_mul( $( self.$compN *= right.$compN; )+ } } + + ref_binop!(impl Mul, mul for $t; $($compN),+); ) ); @@ -37,6 +83,8 @@ macro_rules! pointwise_div( $( self.$compN /= right.$compN; )+ } } + + ref_binop!(impl Div, div for $t; $($compN),+); ) ); @@ -57,6 +105,8 @@ macro_rules! pointwise_add( $( self.$compN += right.$compN; )+ } } + + ref_binop!(impl Add, add for $t; $($compN),+); ) ); @@ -79,21 +129,132 @@ macro_rules! pointwise_sub( $( self.$compN -= right.$compN; )+ } } + + ref_binop!(impl Sub, sub for $t; $($compN),+); ) ); +macro_rules! ref_binop_scalar_exact( + (impl $imp:ident<$lhs:ident>, $method:ident for $t:ident; $($compN:ident),+) => { + impl $imp<$t<$lhs>> for $lhs { + type Output = $t<$lhs>; + + #[inline] + fn $method(self, right: $t<$lhs>) -> $t<$lhs> { + $t::new( + $( + $imp::$method(right.$compN, self) + ),+ + ) + } + } + + impl<'a, 'b> $imp<&'a $t<$lhs>> for &'b $lhs { + type Output = $t<$lhs>; + + #[inline] + fn $method(self, right: &'a $t<$lhs>) -> $t<$lhs> { + $t::new( + $( + $imp::$method(right.$compN, self) + ),+ + ) + } + } + + impl<'a> $imp<$t<$lhs>> for &'a $lhs { + type Output = $t<$lhs>; + + #[inline] + fn $method(self, right: $t<$lhs>) -> $t<$lhs> { + $t::new( + $( + $imp::$method(right.$compN, self) + ),+ + ) + } + } + + impl<'a> $imp<&'a $t<$lhs>> for $lhs { + type Output = $t<$lhs>; + + #[inline] + fn $method(self, right: &'a $t<$lhs>) -> $t<$lhs> { + $t::new( + $( + $imp::$method(right.$compN, self) + ),+ + ) + } + } + }; +); + + +macro_rules! ref_binop_scalar( + // Symmetric to `std::ops::forward_ref_binop!` + (impl $imp:ident, $method:ident for $t:ident; $($compN:ident),+) => { + ref_binop_scalar_exact!(impl $imp, $method for $t; $($compN),+); + ref_binop_scalar_exact!(impl $imp, $method for $t; $($compN),+); + + impl> $imp for $t { + type Output = $t; + + #[inline] + fn $method(self, right: N) -> $t { + $t::new( + $( + $imp::$method(self.$compN, right) + ),+ + ) + } + } + + impl<'a, 'b, N> $imp<&'a N> for &'b $t where &'b N: $imp<&'a N, Output = N> { + type Output = $t; + + #[inline] + fn $method(self, right: &'a N) -> $t { + $t::new( + $( + $imp::$method(&self.$compN, &right) + ),+ + ) + } + } + + impl<'a, N> $imp for &'a $t where for<'b> &'a N: $imp<&'b N, Output = N> { + type Output = $t; + + #[inline] + fn $method(self, right: N) -> $t { + $t::new( + $( + $imp::$method(&self.$compN, &right) + ),+ + ) + } + } + + impl<'a, N> $imp<&'a N> for $t where N: $imp<&'a N, Output = N> { + type Output = $t; + + #[inline] + fn $method(self, right: &'a N) -> $t { + $t::new( + $( + $imp::$method(self.$compN, &right) + ),+ + ) + } + } + } +); + + macro_rules! pointwise_scalar_mul( ($t: ident, $($compN: ident),+) => ( - impl> Mul for $t { - type Output = $t; - - #[inline] - fn mul(self, right: N) -> $t { - $t::new($(self.$compN * right),+) - } - } - impl> MulAssign for $t { #[inline] fn mul_assign(&mut self, right: N) { @@ -101,59 +262,27 @@ macro_rules! pointwise_scalar_mul( } } - impl Mul<$t> for f32 { - type Output = $t; - - #[inline] - fn mul(self, right: $t) -> $t { - $t::new($(self * right.$compN),+) - } - } - - impl Mul<$t> for f64 { - type Output = $t; - - #[inline] - fn mul(self, right: $t) -> $t { - $t::new($(self * right.$compN),+) - } - } + ref_binop_scalar!(impl Mul, mul for $t; $($compN),+); ) ); macro_rules! pointwise_scalar_div( ($t: ident, $($compN: ident),+) => ( - impl> Div for $t { - type Output = $t; - - #[inline] - fn div(self, right: N) -> $t { - $t::new($(self.$compN / right),+) - } - } - impl> DivAssign for $t { #[inline] fn div_assign(&mut self, right: N) { $( self.$compN /= right; )+ } } + + ref_binop_scalar!(impl Div, div for $t; $($compN),+); ) ); macro_rules! pointwise_scalar_add( ($t: ident, $($compN: ident),+) => ( - impl> Add for $t { - type Output = $t; - - #[inline] - fn add(self, right: N) -> $t { - $t::new($(self.$compN + right),+) - } - } - impl> AddAssign for $t { #[inline] fn add_assign(&mut self, right: N) { @@ -161,37 +290,12 @@ macro_rules! pointwise_scalar_add( } } - impl Add<$t> for f32 { - type Output = $t; - - #[inline] - fn add(self, right: $t) -> $t { - $t::new($(self + right.$compN),+) - } - } - - impl Add<$t> for f64 { - type Output = $t; - - #[inline] - fn add(self, right: $t) -> $t { - $t::new($(self + right.$compN),+) - } - } + ref_binop_scalar!(impl Add, add for $t; $($compN),+); ) ); macro_rules! pointwise_scalar_sub( ($t: ident, $($compN: ident),+) => ( - impl> Sub for $t { - type Output = $t; - - #[inline] - fn sub(self, right: N) -> $t { - $t::new($(self.$compN - right),+) - } - } - impl> SubAssign for $t { #[inline] fn sub_assign(&mut self, right: N) { @@ -199,36 +303,46 @@ macro_rules! pointwise_scalar_sub( } } - impl Sub<$t> for f32 { - type Output = $t; - - #[inline] - fn sub(self, right: $t) -> $t { - $t::new($(self - right.$compN),+) - } - } - - impl Sub<$t> for f64 { - type Output = $t; - - #[inline] - fn sub(self, right: $t) -> $t { - $t::new($(self - right.$compN),+) - } - } + ref_binop_scalar!(impl Sub, sub for $t; $($compN),+); ) ); -macro_rules! componentwise_neg( - ($t: ident, $($compN: ident),+) => ( - impl + Copy> Neg for $t { + +macro_rules! ref_unop( + // Symmetric to `std::ops::forward_ref_unop!` + (impl $imp:ident, $method:ident for $t:ident; $($compN:ident),+) => { + impl + Copy> $imp for $t { type Output = $t; #[inline] - fn neg(self) -> $t { - $t::new($(-self.$compN ),+) + fn $method(self) -> $t { + $t::new( + $( + $imp::$method(self.$compN) + ),+ + ) } } + + impl<'a, N> $imp for &'a $t where &'a N: $imp { + type Output = $t; + + #[inline] + fn $method(self) -> $t { + $t::new( + $( + $imp::$method(&self.$compN) + ),+ + ) + } + } + } +); + + +macro_rules! componentwise_neg( + ($t: ident, $($compN: ident),+) => ( + ref_unop!(impl Neg, neg for $t; $($compN),+); ) );