From 8c05db962a1df33eb181f2eb39c26ded894cd626 Mon Sep 17 00:00:00 2001 From: Brendan Zabarauskas Date: Tue, 22 Dec 2015 00:43:15 +1100 Subject: [PATCH] Implement by-ref negations for matrices --- src/angle.rs | 12 +++++----- src/macros.rs | 56 +++++++++++++++++++++++++++++-------------- src/matrix.rs | 61 +++++++++++++++-------------------------------- src/point.rs | 10 ++++---- src/quaternion.rs | 30 +++++++++-------------- src/vector.rs | 20 ++++++++-------- 6 files changed, 89 insertions(+), 100 deletions(-) diff --git a/src/angle.rs b/src/angle.rs index 7a322ea..be6afc3 100644 --- a/src/angle.rs +++ b/src/angle.rs @@ -167,23 +167,23 @@ macro_rules! impl_angle { fn neg(self) -> $Angle { $Angle::new(-self.s) } } - impl_binary_operator!( Add<$Angle > for $Angle { + impl_operator!( Add<$Angle > for $Angle { fn add(lhs, rhs) -> $Angle { $Angle::new(lhs.s + rhs.s) } }); - impl_binary_operator!( Sub<$Angle > for $Angle { + impl_operator!( Sub<$Angle > for $Angle { fn sub(lhs, rhs) -> $Angle { $Angle::new(lhs.s - rhs.s) } }); - impl_binary_operator!( Div<$Angle > for $Angle { + impl_operator!( Div<$Angle > for $Angle { fn div(lhs, rhs) -> S { lhs.s / rhs.s } }); - impl_binary_operator!( Rem<$Angle > for $Angle { + impl_operator!( Rem<$Angle > for $Angle { fn rem(lhs, rhs) -> $Angle { $Angle::new(lhs.s % rhs.s) } }); - impl_binary_operator!( Mul for $Angle { + impl_operator!( Mul for $Angle { fn mul(lhs, scalar) -> $Angle { $Angle::new(lhs.s * scalar) } }); - impl_binary_operator!( Div for $Angle { + impl_operator!( Div for $Angle { fn div(lhs, scalar) -> $Angle { $Angle::new(lhs.s / scalar) } }); diff --git a/src/macros.rs b/src/macros.rs index 938f437..2a468f7 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -18,59 +18,79 @@ #![macro_use] /// Generates a binary operator implementation for the permutations of by-ref and by-val -macro_rules! impl_binary_operator { - // When the right operand is a scalar - (<$S:ident: $Constraint:ident> $Binop:ident<$Rhs:ident> for $Lhs:ty { - fn $binop:ident($lhs:ident, $rhs:ident) -> $Output:ty { $body:expr } +macro_rules! impl_operator { + // When it is an unary operator + (<$S:ident: $Constraint:ident> $Op:ident for $Lhs:ty { + fn $op:ident($x:ident) -> $Output:ty { $body:expr } }) => { - impl<$S: $Constraint> $Binop<$Rhs> for $Lhs { + impl<$S: $Constraint> $Op for $Lhs { type Output = $Output; #[inline] - fn $binop(self, other: $Rhs) -> $Output { + fn $op(self) -> $Output { + let $x = self; $body + } + } + + impl<'a, $S: $Constraint> $Op for &'a $Lhs { + type Output = $Output; + #[inline] + fn $op(self) -> $Output { + let $x = self; $body + } + } + }; + // When the right operand is a scalar + (<$S:ident: $Constraint:ident> $Op:ident<$Rhs:ident> for $Lhs:ty { + fn $op:ident($lhs:ident, $rhs:ident) -> $Output:ty { $body:expr } + }) => { + impl<$S: $Constraint> $Op<$Rhs> for $Lhs { + type Output = $Output; + #[inline] + fn $op(self, other: $Rhs) -> $Output { let ($lhs, $rhs) = (self, other); $body } } - impl<'a, $S: $Constraint> $Binop<$Rhs> for &'a $Lhs { + impl<'a, $S: $Constraint> $Op<$Rhs> for &'a $Lhs { type Output = $Output; #[inline] - fn $binop(self, other: $Rhs) -> $Output { + fn $op(self, other: $Rhs) -> $Output { let ($lhs, $rhs) = (self, other); $body } } }; // When the right operand is a compound type - (<$S:ident: $Constraint:ident> $Binop:ident<$Rhs:ty> for $Lhs:ty { - fn $binop:ident($lhs:ident, $rhs:ident) -> $Output:ty { $body:expr } + (<$S:ident: $Constraint:ident> $Op:ident<$Rhs:ty> for $Lhs:ty { + fn $op:ident($lhs:ident, $rhs:ident) -> $Output:ty { $body:expr } }) => { - impl<$S: $Constraint> $Binop<$Rhs> for $Lhs { + impl<$S: $Constraint> $Op<$Rhs> for $Lhs { type Output = $Output; #[inline] - fn $binop(self, other: $Rhs) -> $Output { + fn $op(self, other: $Rhs) -> $Output { let ($lhs, $rhs) = (self, other); $body } } - impl<'a, $S: $Constraint> $Binop<&'a $Rhs> for $Lhs { + impl<'a, $S: $Constraint> $Op<&'a $Rhs> for $Lhs { type Output = $Output; #[inline] - fn $binop(self, other: &'a $Rhs) -> $Output { + fn $op(self, other: &'a $Rhs) -> $Output { let ($lhs, $rhs) = (self, other); $body } } - impl<'a, $S: $Constraint> $Binop<$Rhs> for &'a $Lhs { + impl<'a, $S: $Constraint> $Op<$Rhs> for &'a $Lhs { type Output = $Output; #[inline] - fn $binop(self, other: $Rhs) -> $Output { + fn $op(self, other: $Rhs) -> $Output { let ($lhs, $rhs) = (self, other); $body } } - impl<'a, 'b, $S: $Constraint> $Binop<&'a $Rhs> for &'b $Lhs { + impl<'a, 'b, $S: $Constraint> $Op<&'a $Rhs> for &'b $Lhs { type Output = $Output; #[inline] - fn $binop(self, other: &'a $Rhs) -> $Output { + fn $op(self, other: &'a $Rhs) -> $Output { let ($lhs, $rhs) = (self, other); $body } } diff --git a/src/matrix.rs b/src/matrix.rs index a859e31..8970614 100644 --- a/src/matrix.rs +++ b/src/matrix.rs @@ -815,70 +815,47 @@ impl ApproxEq for Matrix4 { } } -impl Neg for Matrix2 { - type Output = Matrix2; - - #[inline] - fn neg(self) -> Matrix2 { - Matrix2::from_cols(-self.x, -self.y) - } -} - -impl Neg for Matrix3 { - type Output = Matrix3; - - #[inline] - fn neg(self) -> Matrix3 { - Matrix3::from_cols(-self.x, -self.y, -self.z) - } -} - -impl Neg for Matrix4 { - type Output = Matrix4; - - #[inline] - fn neg(self) -> Matrix4 { - Matrix4::from_cols(-self.x, -self.y, -self.z, -self.w) - } -} - -macro_rules! impl_binary_operators { +macro_rules! impl_operators { ($MatrixN:ident, $VectorN:ident { $($field:ident : $row_index:expr),+ }) => { - impl_binary_operator!( Mul for $MatrixN { + impl_operator!( Neg for $MatrixN { + fn neg(matrix) -> $MatrixN { $MatrixN { $($field: -matrix.$field),+ } } + }); + + impl_operator!( Mul for $MatrixN { fn mul(matrix, scalar) -> $MatrixN { $MatrixN { $($field: matrix.$field * scalar),+ } } }); - impl_binary_operator!( Div for $MatrixN { + impl_operator!( Div for $MatrixN { fn div(matrix, scalar) -> $MatrixN { $MatrixN { $($field: matrix.$field / scalar),+ } } }); - impl_binary_operator!( Rem for $MatrixN { + impl_operator!( Rem for $MatrixN { fn rem(matrix, scalar) -> $MatrixN { $MatrixN { $($field: matrix.$field % scalar),+ } } }); - impl_binary_operator!( Add<$MatrixN > for $MatrixN { - fn add(lhs, rhs) -> $MatrixN { $MatrixN { $($field: lhs.$field + rhs.$field ),+ } } + impl_operator!( Add<$MatrixN > for $MatrixN { + fn add(lhs, rhs) -> $MatrixN { $MatrixN { $($field: lhs.$field + rhs.$field),+ } } }); - impl_binary_operator!( Sub<$MatrixN > for $MatrixN { - fn sub(lhs, rhs) -> $MatrixN { $MatrixN { $($field: lhs.$field - rhs.$field ),+ } } + impl_operator!( Sub<$MatrixN > for $MatrixN { + fn sub(lhs, rhs) -> $MatrixN { $MatrixN { $($field: lhs.$field - rhs.$field),+ } } }); - impl_binary_operator!( Mul<$VectorN > for $MatrixN { + impl_operator!( Mul<$VectorN > for $MatrixN { fn mul(matrix, vector) -> $VectorN { $VectorN::new($(matrix.row($row_index).dot(vector.clone())),+) } }); } } -impl_binary_operators!(Matrix2, Vector2 { x: 0, y: 1 }); -impl_binary_operators!(Matrix3, Vector3 { x: 0, y: 1, z: 2 }); -impl_binary_operators!(Matrix4, Vector4 { x: 0, y: 1, z: 2, w: 3 }); +impl_operators!(Matrix2, Vector2 { x: 0, y: 1 }); +impl_operators!(Matrix3, Vector3 { x: 0, y: 1, z: 2 }); +impl_operators!(Matrix4, Vector4 { x: 0, y: 1, z: 2, w: 3 }); -impl_binary_operator!( Mul > for Matrix2 { +impl_operator!( Mul > for Matrix2 { fn mul(lhs, rhs) -> Matrix2 { Matrix2::new(lhs.row(0).dot(rhs[0]), lhs.row(1).dot(rhs[0]), lhs.row(0).dot(rhs[1]), lhs.row(1).dot(rhs[1])) } }); -impl_binary_operator!( Mul > for Matrix3 { +impl_operator!( Mul > for Matrix3 { fn mul(lhs, rhs) -> Matrix3 { Matrix3::new(lhs.row(0).dot(rhs[0]), lhs.row(1).dot(rhs[0]), lhs.row(2).dot(rhs[0]), lhs.row(0).dot(rhs[1]), lhs.row(1).dot(rhs[1]), lhs.row(2).dot(rhs[1]), @@ -899,7 +876,7 @@ macro_rules! dot_matrix4 { }; } -impl_binary_operator!( Mul > for Matrix4 { +impl_operator!( Mul > for Matrix4 { fn mul(lhs, rhs) -> Matrix4 { Matrix4::new(dot_matrix4!(lhs, rhs, 0, 0), dot_matrix4!(lhs, rhs, 1, 0), dot_matrix4!(lhs, rhs, 2, 0), dot_matrix4!(lhs, rhs, 3, 0), dot_matrix4!(lhs, rhs, 0, 1), dot_matrix4!(lhs, rhs, 1, 1), dot_matrix4!(lhs, rhs, 2, 1), dot_matrix4!(lhs, rhs, 3, 1), diff --git a/src/point.rs b/src/point.rs index 8e0b3c3..419864f 100644 --- a/src/point.rs +++ b/src/point.rs @@ -142,23 +142,23 @@ macro_rules! impl_point { } } - impl_binary_operator!( Add<$VectorN > for $PointN { + impl_operator!( Add<$VectorN > for $PointN { fn add(lhs, rhs) -> $PointN { $PointN::new($(lhs.$field + rhs.$field),+) } }); - impl_binary_operator!( Sub<$PointN > for $PointN { + impl_operator!( Sub<$PointN > for $PointN { fn sub(lhs, rhs) -> $VectorN { $VectorN::new($(lhs.$field - rhs.$field),+) } }); - impl_binary_operator!( Mul for $PointN { + impl_operator!( Mul for $PointN { fn mul(point, scalar) -> $PointN { $PointN::new($(point.$field * scalar),+) } }); - impl_binary_operator!( Div for $PointN { + impl_operator!( Div for $PointN { fn div(point, scalar) -> $PointN { $PointN::new($(point.$field / scalar),+) } }); - impl_binary_operator!( Rem for $PointN { + impl_operator!( Rem for $PointN { fn rem(point, scalar) -> $PointN { $PointN::new($(point.$field % scalar),+) } }); diff --git a/src/quaternion.rs b/src/quaternion.rs index 3d57ef3..54e2630 100644 --- a/src/quaternion.rs +++ b/src/quaternion.rs @@ -108,33 +108,25 @@ impl Quaternion { } } -impl Neg for Quaternion { - type Output = Quaternion; +impl_operator!( Neg for Quaternion { + fn neg(quat) -> Quaternion { + Quaternion::from_sv(-quat.s, -quat.v) + } +}); - #[inline] - fn neg(self) -> Quaternion { Quaternion::from_sv(-self.s, -self.v) } -} - -impl<'a, S: BaseFloat> Neg for &'a Quaternion { - type Output = Quaternion; - - #[inline] - fn neg(self) -> Quaternion { Quaternion::from_sv(-self.s, -self.v) } -} - -impl_binary_operator!( Mul for Quaternion { +impl_operator!( Mul for Quaternion { fn mul(lhs, rhs) -> Quaternion { Quaternion::from_sv(lhs.s * rhs, lhs.v * rhs) } }); -impl_binary_operator!( Div for Quaternion { +impl_operator!( Div for Quaternion { fn div(lhs, rhs) -> Quaternion { Quaternion::from_sv(lhs.s / rhs, lhs.v / rhs) } }); -impl_binary_operator!( Mul > for Quaternion { +impl_operator!( Mul > for Quaternion { fn mul(lhs, rhs) -> Vector3 {{ let rhs = rhs.clone(); let two: S = cast(2i8).unwrap(); @@ -143,19 +135,19 @@ impl_binary_operator!( Mul > for Quaternion { }} }); -impl_binary_operator!( Add > for Quaternion { +impl_operator!( Add > for Quaternion { fn add(lhs, rhs) -> Quaternion { Quaternion::from_sv(lhs.s + rhs.s, lhs.v + rhs.v) } }); -impl_binary_operator!( Sub > for Quaternion { +impl_operator!( Sub > for Quaternion { fn sub(lhs, rhs) -> Quaternion { Quaternion::from_sv(lhs.s - rhs.s, lhs.v - rhs.v) } }); -impl_binary_operator!( Mul > for Quaternion { +impl_operator!( Mul > for Quaternion { fn mul(lhs, rhs) -> Quaternion { Quaternion::new(lhs.s * rhs.s - lhs.v.x * rhs.v.x - lhs.v.y * rhs.v.y - lhs.v.z * rhs.v.z, lhs.s * rhs.v.x + lhs.v.x * rhs.s + lhs.v.y * rhs.v.z - lhs.v.z * rhs.v.y, diff --git a/src/vector.rs b/src/vector.rs index 6b4fcf6..6cf2c5d 100644 --- a/src/vector.rs +++ b/src/vector.rs @@ -212,38 +212,38 @@ macro_rules! impl_vector { } } - impl_binary_operator!( Add for $VectorN { + impl_operator!( Add for $VectorN { fn add(vector, scalar) -> $VectorN { $VectorN::new($(vector.$field + scalar),+) } }); - impl_binary_operator!( Add<$VectorN > for $VectorN { + impl_operator!( Add<$VectorN > for $VectorN { fn add(lhs, rhs) -> $VectorN { $VectorN::new($(lhs.$field + rhs.$field),+) } }); - impl_binary_operator!( Sub for $VectorN { + impl_operator!( Sub for $VectorN { fn sub(vector, scalar) -> $VectorN { $VectorN::new($(vector.$field - scalar),+) } }); - impl_binary_operator!( Sub<$VectorN > for $VectorN { + impl_operator!( Sub<$VectorN > for $VectorN { fn sub(lhs, rhs) -> $VectorN { $VectorN::new($(lhs.$field - rhs.$field),+) } }); - impl_binary_operator!( Mul for $VectorN { + impl_operator!( Mul for $VectorN { fn mul(vector, scalar) -> $VectorN { $VectorN::new($(vector.$field * scalar),+) } }); - impl_binary_operator!( Mul<$VectorN > for $VectorN { + impl_operator!( Mul<$VectorN > for $VectorN { fn mul(lhs, rhs) -> $VectorN { $VectorN::new($(lhs.$field * rhs.$field),+) } }); - impl_binary_operator!( Div for $VectorN { + impl_operator!( Div for $VectorN { fn div(vector, scalar) -> $VectorN { $VectorN::new($(vector.$field / scalar),+) } }); - impl_binary_operator!( Div<$VectorN > for $VectorN { + impl_operator!( Div<$VectorN > for $VectorN { fn div(lhs, rhs) -> $VectorN { $VectorN::new($(lhs.$field / rhs.$field),+) } }); - impl_binary_operator!( Rem for $VectorN { + impl_operator!( Rem for $VectorN { fn rem(vector, scalar) -> $VectorN { $VectorN::new($(vector.$field % scalar),+) } }); - impl_binary_operator!( Rem<$VectorN > for $VectorN { + impl_operator!( Rem<$VectorN > for $VectorN { fn rem(lhs, rhs) -> $VectorN { $VectorN::new($(lhs.$field % rhs.$field),+) } });