Implement component-wise methods

This commit is contained in:
Brendan Zabarauskas 2013-07-14 16:18:25 +10:00
parent 19376dce32
commit 4008cf8121

View file

@ -27,23 +27,30 @@ pub trait NumVec<T,Slice>: Neg<T> {
pub fn mul_t(&self, value: T) -> Self;
pub fn div_t(&self, value: T) -> Self;
pub fn rem_t(&self, value: T) -> Self;
pub fn add_v(&self, other: &Self) -> Self;
pub fn sub_v(&self, other: &Self) -> Self;
pub fn mul_v(&self, other: &Self) -> Self;
pub fn div_v(&self, other: &Self) -> Self;
pub fn rem_v(&self, other: &Self) -> Self;
pub fn neg_self(&mut self);
pub fn add_self_t(&mut self, value: T);
pub fn sub_self_t(&mut self, value: T);
pub fn mul_self_t(&mut self, value: T);
pub fn div_self_t(&mut self, value: T);
pub fn rem_self_t(&mut self, value: T);
pub fn add_self_v(&mut self, other: &Self);
pub fn sub_self_v(&mut self, other: &Self);
pub fn mul_self_v(&mut self, other: &Self);
pub fn div_self_v(&mut self, other: &Self);
pub fn rem_self_v(&mut self, other: &Self);
pub fn dot(&self, other: &Self) -> T;
pub fn comp_add(&self) -> T;
pub fn comp_mul(&self) -> T;
}
/// Vectors with floating point components
@ -65,10 +72,14 @@ pub trait OrdVec<T,Slice,BV>: Vec<T,Slice> {
pub fn le_t(&self, value: T) -> BV;
pub fn ge_t(&self, value: T) -> BV;
pub fn gt_t(&self, value: T) -> BV;
pub fn lt_v(&self, other: &Self) -> BV;
pub fn le_v(&self, other: &Self) -> BV;
pub fn ge_v(&self, other: &Self) -> BV;
pub fn gt_v(&self, other: &Self) -> BV;
pub fn comp_min(&self) -> T;
pub fn comp_max(&self) -> T;
}
/// Vectors with components that can be tested for equality
@ -328,6 +339,18 @@ impl<T:Num> NumVec<T,[T,..2]> for Vec2<T> {
*self.index(0) * *other.index(0) +
*self.index(1) * *other.index(1)
}
/// Returns the sum of the vector's components.
#[inline]
pub fn comp_add(&self) -> T {
*self.index(0) + *self.index(1)
}
/// Returns the product of the vector's components.
#[inline]
pub fn comp_mul(&self) -> T {
*self.index(0) * *self.index(1)
}
}
impl<T:Num> Neg<Vec2<T>> for Vec2<T> {
@ -401,7 +424,7 @@ impl<T:Float> FloatVec<T,[T,..2]> for Vec2<T> {
}
}
impl<T:Ord> OrdVec<T,[T,..2],Vec2<bool>> for Vec2<T> {
impl<T:Orderable> OrdVec<T,[T,..2],Vec2<bool>> for Vec2<T> {
#[inline]
pub fn lt_t(&self, value: T) -> Vec2<bool> {
Vec2::new(*self.index(0) < value,
@ -449,6 +472,18 @@ impl<T:Ord> OrdVec<T,[T,..2],Vec2<bool>> for Vec2<T> {
Vec2::new(*self.index(0) > *other.index(0),
*self.index(1) > *other.index(1))
}
/// Returns the smallest component of the vector.
#[inline]
pub fn comp_min(&self) -> T {
self.index(0).min(self.index(1))
}
/// Returns the largest component of the vector.
#[inline]
pub fn comp_max(&self) -> T {
self.index(0).max(self.index(1))
}
}
impl<T:Eq> EqVec<T,[T,..2],Vec2<bool>> for Vec2<T> {
@ -561,6 +596,18 @@ mod vec2_tests {
assert_eq!(mut_a, A.div_v(&B));
}
#[test]
fn test_comp_add() {
assert_eq!(A.comp_add(), 3.0);
assert_eq!(B.comp_add(), 7.0);
}
#[test]
fn test_comp_mul() {
assert_eq!(A.comp_mul(), 2.0);
assert_eq!(B.comp_mul(), 12.0);
}
#[test]
fn test_approx_eq() {
assert!(!Vec2::new::<float>(0.000001, 0.000001).approx_eq(&Vec2::new::<float>(0.0, 0.0)));
@ -604,6 +651,18 @@ mod vec2_tests {
assert_eq!(mut_c, c.lerp(&d, 0.75));
}
#[test]
fn test_comp_min() {
assert_eq!(A.comp_min(), 1.0);
assert_eq!(B.comp_min(), 3.0);
}
#[test]
fn test_comp_max() {
assert_eq!(A.comp_max(), 2.0);
assert_eq!(B.comp_max(), 4.0);
}
#[test]
fn test_boolean() {
let tf = Vec2::new(true, false);
@ -905,6 +964,18 @@ impl<T:Num> NumVec<T,[T,..3]> for Vec3<T> {
*self.index(1) * *other.index(1) +
*self.index(2) * *other.index(2)
}
/// Returns the sum of the vector's components.
#[inline]
pub fn comp_add(&self) -> T {
*self.index(0) + *self.index(1) + *self.index(2)
}
/// Returns the product of the vector's components.
#[inline]
pub fn comp_mul(&self) -> T {
*self.index(0) * *self.index(1) * *self.index(2)
}
}
impl<T:Num> Neg<Vec3<T>> for Vec3<T> {
@ -979,7 +1050,7 @@ impl<T:Float> FloatVec<T,[T,..3]> for Vec3<T> {
}
}
impl<T:Ord> OrdVec<T,[T,..3],Vec3<bool>> for Vec3<T> {
impl<T:Orderable> OrdVec<T,[T,..3],Vec3<bool>> for Vec3<T> {
#[inline]
pub fn lt_t(&self, value: T) -> Vec3<bool> {
Vec3::new(*self.index(0) < value,
@ -1035,6 +1106,18 @@ impl<T:Ord> OrdVec<T,[T,..3],Vec3<bool>> for Vec3<T> {
*self.index(1) > *other.index(1),
*self.index(2) > *other.index(2))
}
/// Returns the smallest component of the vector.
#[inline]
pub fn comp_min(&self) -> T {
self.index(0).min(self.index(1)).min(self.index(2))
}
/// Returns the largest component of the vector.
#[inline]
pub fn comp_max(&self) -> T {
self.index(0).max(self.index(1)).max(self.index(2))
}
}
impl<T:Eq> EqVec<T,[T,..3],Vec3<bool>> for Vec3<T> {
@ -1167,6 +1250,18 @@ mod vec3_tests{
assert_eq!(mut_a, A.div_v(&B));
}
#[test]
fn test_comp_add() {
assert_eq!(A.comp_add(), 6.0);
assert_eq!(B.comp_add(), 15.0);
}
#[test]
fn test_comp_mul() {
assert_eq!(A.comp_mul(), 6.0);
assert_eq!(B.comp_mul(), 120.0);
}
#[test]
fn test_approx_eq() {
assert!(!Vec3::new::<float>(0.000001, 0.000001, 0.000001).approx_eq(&Vec3::new::<float>(0.0, 0.0, 0.0)));
@ -1211,6 +1306,18 @@ mod vec3_tests{
assert_eq!(mut_c, c.lerp(&d, 0.75));
}
#[test]
fn test_comp_min() {
assert_eq!(A.comp_min(), 1.0);
assert_eq!(B.comp_min(), 4.0);
}
#[test]
fn test_comp_max() {
assert_eq!(A.comp_max(), 3.0);
assert_eq!(B.comp_max(), 6.0);
}
#[test]
fn test_boolean() {
let tft = Vec3::new(true, false, true);
@ -1512,6 +1619,18 @@ impl<T:Num> NumVec<T,[T,..4]> for Vec4<T> {
*self.index(2) * *other.index(2) +
*self.index(3) * *other.index(3)
}
/// Returns the sum of the vector's components.
#[inline]
pub fn comp_add(&self) -> T {
*self.index(0) + *self.index(1) + *self.index(2) + *self.index(3)
}
/// Returns the product of the vector's components.
#[inline]
pub fn comp_mul(&self) -> T {
*self.index(0) * *self.index(1) * *self.index(2) * *self.index(3)
}
}
impl<T:Num> Neg<Vec4<T>> for Vec4<T> {
@ -1587,7 +1706,7 @@ impl<T:Float> FloatVec<T,[T,..4]> for Vec4<T> {
}
}
impl<T:Ord> OrdVec<T,[T,..4],Vec4<bool>> for Vec4<T> {
impl<T:Orderable> OrdVec<T,[T,..4],Vec4<bool>> for Vec4<T> {
#[inline]
pub fn lt_t(&self, value: T) -> Vec4<bool> {
Vec4::new(*self.index(0) < value,
@ -1651,6 +1770,18 @@ impl<T:Ord> OrdVec<T,[T,..4],Vec4<bool>> for Vec4<T> {
*self.index(2) > *other.index(2),
*self.index(3) > *other.index(3))
}
/// Returns the smallest component of the vector.
#[inline]
pub fn comp_min(&self) -> T {
self.index(0).min(self.index(1)).min(self.index(2)).min(self.index(3))
}
/// Returns the largest component of the vector.
#[inline]
pub fn comp_max(&self) -> T {
self.index(0).max(self.index(1)).max(self.index(2)).max(self.index(3))
}
}
impl<T:Eq> EqVec<T,[T,..4],Vec4<bool>> for Vec4<T> {
@ -1780,6 +1911,18 @@ mod vec4_tests {
assert_eq!(mut_a, A.div_v(&B));
}
#[test]
fn test_comp_add() {
assert_eq!(A.comp_add(), 10.0);
assert_eq!(B.comp_add(), 26.0);
}
#[test]
fn test_comp_mul() {
assert_eq!(A.comp_mul(), 24.0);
assert_eq!(B.comp_mul(), 1680.0);
}
#[test]
fn test_approx_eq() {
assert!(!Vec4::new::<float>(0.000001, 0.000001, 0.000001, 0.000001).approx_eq(&Vec4::new::<float>(0.0, 0.0, 0.0, 0.0)));
@ -1823,6 +1966,18 @@ mod vec4_tests {
assert_eq!(mut_c, c.lerp(&d, 0.75));
}
#[test]
fn test_comp_min() {
assert_eq!(A.comp_min(), 1.0);
assert_eq!(B.comp_min(), 5.0);
}
#[test]
fn test_comp_max() {
assert_eq!(A.comp_max(), 4.0);
assert_eq!(B.comp_max(), 8.0);
}
#[test]
fn test_boolean() {
let tftf = Vec4::new(true, false, true, false);