Support for scalar on the lhs of arithmetic operators
This commit is contained in:
parent
6cf7831275
commit
7426d8d807
3 changed files with 81 additions and 0 deletions
|
@ -95,6 +95,38 @@ macro_rules! impl_operator {
|
|||
}
|
||||
}
|
||||
};
|
||||
// When the left operand is a scalar
|
||||
($Op:ident<$Rhs:ident<$S:ident>> for $Lhs:ty {
|
||||
fn $op:ident($lhs:ident, $rhs:ident) -> $Output:ty { $body:expr }
|
||||
}) => {
|
||||
impl $Op<$Rhs<$S>> for $Lhs {
|
||||
type Output = $Output;
|
||||
#[inline]
|
||||
fn $op(self, other: $Rhs<$S>) -> $Output {
|
||||
let ($lhs, $rhs) = (self, other); $body
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
macro_rules! impl_scalar_ops {
|
||||
($VectorN:ident<$S:ident> { $($field:ident),+ }) => {
|
||||
impl_operator!(Add<$VectorN<$S>> for $S {
|
||||
fn add(scalar, vector) -> $VectorN<$S> { $VectorN::new($(scalar + vector.$field),+) }
|
||||
});
|
||||
impl_operator!(Sub<$VectorN<$S>> for $S {
|
||||
fn sub(scalar, vector) -> $VectorN<$S> { $VectorN::new($(scalar - vector.$field),+) }
|
||||
});
|
||||
impl_operator!(Mul<$VectorN<$S>> for $S {
|
||||
fn mul(scalar, vector) -> $VectorN<$S> { $VectorN::new($(scalar * vector.$field),+) }
|
||||
});
|
||||
impl_operator!(Div<$VectorN<$S>> for $S {
|
||||
fn div(scalar, vector) -> $VectorN<$S> { $VectorN::new($(scalar / vector.$field),+) }
|
||||
});
|
||||
impl_operator!(Rem<$VectorN<$S>> for $S {
|
||||
fn rem(scalar, vector) -> $VectorN<$S> { $VectorN::new($(scalar % vector.$field),+) }
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
macro_rules! impl_assignment_operator {
|
||||
|
|
|
@ -244,6 +244,7 @@ macro_rules! impl_vector {
|
|||
impl_operator!(<S: BaseNum> Mul<$VectorN<S> > for $VectorN<S> {
|
||||
fn mul(lhs, rhs) -> $VectorN<S> { $VectorN::new($(lhs.$field * rhs.$field),+) }
|
||||
});
|
||||
|
||||
impl_assignment_operator!(<S: BaseNum> MulAssign<S> for $VectorN<S> {
|
||||
fn mul_assign(&mut self, scalar) { $(self.$field *= scalar);+ }
|
||||
});
|
||||
|
@ -285,10 +286,20 @@ macro_rules! impl_vector {
|
|||
}
|
||||
}
|
||||
|
||||
macro_rules! impl_vector_scalar_ops {
|
||||
($($S:ident)*) => ($(
|
||||
impl_scalar_ops!(Vector2<$S> { x, y });
|
||||
impl_scalar_ops!(Vector3<$S> { x, y, z });
|
||||
impl_scalar_ops!(Vector4<$S> { x, y, z, w });
|
||||
)*)
|
||||
}
|
||||
|
||||
impl_vector!(Vector2<S> { x, y }, 2, vec2);
|
||||
impl_vector!(Vector3<S> { x, y, z }, 3, vec3);
|
||||
impl_vector!(Vector4<S> { x, y, z, w }, 4, vec4);
|
||||
|
||||
impl_vector_scalar_ops!(usize u8 u16 u32 u64 isize i8 i16 i32 i64 f32 f64);
|
||||
|
||||
impl_fixed_array_conversions!(Vector2<S> { x: 0, y: 1 }, 2);
|
||||
impl_fixed_array_conversions!(Vector3<S> { x: 0, y: 1, z: 2 }, 3);
|
||||
impl_fixed_array_conversions!(Vector4<S> { x: 0, y: 1, z: 2, w: 3 }, 4);
|
||||
|
|
|
@ -33,6 +33,44 @@ fn test_from_value() {
|
|||
assert_eq!(Vector4::from_value(76.5f64), Vector4::new(76.5f64, 76.5f64, 76.5f64, 76.5f64));
|
||||
}
|
||||
|
||||
macro_rules! test_ops {
|
||||
($VectorN:ident { $($field:ident),+ }, $s:expr, $v:expr) => (
|
||||
// add
|
||||
assert_eq!($v + $s, $VectorN::new($($v.$field + $s),+));
|
||||
assert_eq!($s + $v, $VectorN::new($($s + $v.$field),+));
|
||||
assert_eq!($v + $s, $s + $v);
|
||||
// sub
|
||||
assert_eq!($v - $s, $VectorN::new($($v.$field - $s),+));
|
||||
assert_eq!($s - $v, $VectorN::new($($s - $v.$field),+));
|
||||
assert_eq!($v - $s, -($s - $v));
|
||||
// mul
|
||||
assert_eq!($v * $s, $VectorN::new($($v.$field * $s),+));
|
||||
assert_eq!($s * $v, $VectorN::new($($s * $v.$field),+));
|
||||
assert_eq!($v * $s, $s * $v);
|
||||
// div
|
||||
assert_eq!($v / $s, $VectorN::new($($v.$field / $s),+));
|
||||
assert_eq!($s / $v, $VectorN::new($($s / $v.$field),+));
|
||||
// rem
|
||||
assert_eq!($v % $s, $VectorN::new($($v.$field % $s),+));
|
||||
assert_eq!($s % $v, $VectorN::new($($s % $v.$field),+));
|
||||
)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_ops() {
|
||||
let a = [3.0f32, 4.0f32, 5.0f32, 6.0f32];
|
||||
let s = 2.0f32;
|
||||
|
||||
let v4 = Vector4::from(a);
|
||||
test_ops!(Vector4 { x, y, z, w }, s, v4);
|
||||
|
||||
let v3 = v4.truncate();
|
||||
test_ops!(Vector3 { x, y, z }, s, v3);
|
||||
|
||||
let v2 = v3.truncate();
|
||||
test_ops!(Vector2 { x, y }, s, v2);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_dot() {
|
||||
assert_eq!(Vector2::new(1isize, 2isize).dot(Vector2::new(3isize, 4isize)), 11isize);
|
||||
|
|
Loading…
Reference in a new issue