Added scalar arithmetic operators for Point types

This commit is contained in:
Cameron Hart 2016-01-02 10:14:47 +11:00
parent 1e6f615f9e
commit 3febc46d5a
2 changed files with 79 additions and 1 deletions

View file

@ -172,6 +172,19 @@ macro_rules! impl_point {
fn rem_assign(&mut self, scalar) { $(self.$field %= scalar);+ } fn rem_assign(&mut self, scalar) { $(self.$field %= scalar);+ }
}); });
impl_scalar_ops!($PointN<usize> { $($field),+ });
impl_scalar_ops!($PointN<u8> { $($field),+ });
impl_scalar_ops!($PointN<u16> { $($field),+ });
impl_scalar_ops!($PointN<u32> { $($field),+ });
impl_scalar_ops!($PointN<u64> { $($field),+ });
impl_scalar_ops!($PointN<isize> { $($field),+ });
impl_scalar_ops!($PointN<i8> { $($field),+ });
impl_scalar_ops!($PointN<i16> { $($field),+ });
impl_scalar_ops!($PointN<i32> { $($field),+ });
impl_scalar_ops!($PointN<i64> { $($field),+ });
impl_scalar_ops!($PointN<f32> { $($field),+ });
impl_scalar_ops!($PointN<f64> { $($field),+ });
impl_index_operators!($PointN<S>, $n, S, usize); impl_index_operators!($PointN<S>, $n, S, usize);
impl_index_operators!($PointN<S>, $n, [S], Range<usize>); impl_index_operators!($PointN<S>, $n, [S], Range<usize>);
impl_index_operators!($PointN<S>, $n, [S], RangeTo<usize>); impl_index_operators!($PointN<S>, $n, [S], RangeTo<usize>);
@ -180,6 +193,20 @@ macro_rules! impl_point {
} }
} }
macro_rules! impl_scalar_ops {
($PointN:ident<$S:ident> { $($field:ident),+ }) => {
impl_operator!(Mul<$PointN<$S>> for $S {
fn mul(scalar, vector) -> $PointN<$S> { $PointN::new($(scalar * vector.$field),+) }
});
impl_operator!(Div<$PointN<$S>> for $S {
fn div(scalar, vector) -> $PointN<$S> { $PointN::new($(scalar / vector.$field),+) }
});
impl_operator!(Rem<$PointN<$S>> for $S {
fn rem(scalar, vector) -> $PointN<$S> { $PointN::new($(scalar % vector.$field),+) }
});
};
}
impl_point!(Point2 { x, y }, Vector2, 2); impl_point!(Point2 { x, y }, Vector2, 2);
impl_point!(Point3 { x, y, z }, Vector3, 3); impl_point!(Point3 { x, y, z }, Vector3, 3);

View file

@ -16,11 +16,62 @@
extern crate cgmath; extern crate cgmath;
use cgmath::Point3; use cgmath::{Point2, Point3};
use cgmath::ApproxEq; use cgmath::ApproxEq;
macro_rules! impl_test_mul {
($PointN:ident { $($field:ident),+ }, $s:expr, $v:expr) => (
// point * scalar ops
assert_eq!($v * $s, $PointN::new($($v.$field * $s),+));
assert_eq!($s * $v, $PointN::new($($s * $v.$field),+));
assert_eq!(&$v * $s, $v * $s);
assert_eq!($s * &$v, $s * $v);
// commutativity
assert_eq!($v * $s, $s * $v);
)
}
macro_rules! impl_test_div {
($PointN:ident { $($field:ident),+ }, $s:expr, $v:expr) => (
// point / scalar ops
assert_eq!($v / $s, $PointN::new($($v.$field / $s),+));
assert_eq!($s / $v, $PointN::new($($s / $v.$field),+));
assert_eq!(&$v / $s, $v / $s);
assert_eq!($s / &$v, $s / $v);
)
}
macro_rules! impl_test_rem {
($PointN:ident { $($field:ident),+ }, $s:expr, $v:expr) => (
// point % scalar ops
assert_eq!($v % $s, $PointN::new($($v.$field % $s),+));
assert_eq!($s % $v, $PointN::new($($s % $v.$field),+));
assert_eq!(&$v % $s, $v % $s);
assert_eq!($s % &$v, $s % $v);
)
}
#[test] #[test]
fn test_homogeneous() { fn test_homogeneous() {
let p = Point3::new(1.0f64, 2.0f64, 3.0f64); let p = Point3::new(1.0f64, 2.0f64, 3.0f64);
assert!(p.approx_eq(&Point3::from_homogeneous(p.to_homogeneous()))); assert!(p.approx_eq(&Point3::from_homogeneous(p.to_homogeneous())));
} }
#[test]
fn test_mul() {
impl_test_mul!(Point3 { x, y, z }, 2.0f32, Point3::new(2.0f32, 4.0, 6.0));
impl_test_mul!(Point2 { x, y }, 2.0f32, Point2::new(2.0f32, 4.0));
}
#[test]
fn test_div() {
impl_test_div!(Point3 { x, y, z }, 2.0f32, Point3::new(2.0f32, 4.0, 6.0));
impl_test_div!(Point2 { x, y }, 2.0f32, Point2::new(2.0f32, 4.0));
}
#[test]
fn test_rem() {
impl_test_rem!(Point3 { x, y, z }, 2.0f32, Point3::new(2.0f32, 4.0, 6.0));
impl_test_rem!(Point2 { x, y }, 2.0f32, Point2::new(2.0f32, 4.0));
}