Add mut matrix methods

This commit is contained in:
Brendan Zabarauskas 2012-12-05 13:49:59 +10:00
parent 8acc8f6943
commit e2b134d51f
2 changed files with 377 additions and 87 deletions

View file

@ -149,6 +149,11 @@ pub trait MutableMatrix<T,V>: Matrix<T,V> {
*/ */
fn swap_rows(&mut self, a: uint, b: uint); fn swap_rows(&mut self, a: uint, b: uint);
/**
* Sets the matrix to `other`
*/
fn set(&mut self, other: &self);
/** /**
* Sets the matrix to the identity matrix * Sets the matrix to the identity matrix
*/ */
@ -158,6 +163,36 @@ pub trait MutableMatrix<T,V>: Matrix<T,V> {
* Sets each element of the matrix to zero * Sets each element of the matrix to zero
*/ */
fn to_zero(&mut self); fn to_zero(&mut self);
/**
* Multiplies the matrix by a scalar
*/
fn mul_self_t(&mut self, value: T);
/**
* Add the matrix `other` to `self`
*/
fn add_self_m(&mut self, other: &self);
/**
* Subtract the matrix `other` from `self`
*/
fn sub_self_m(&mut self, other: &self);
/**
* Sets the matrix to its inverse
*
* # Failure
*
* Fails if the matrix is not invertable. Make sure you check with the
* `is_invertible` method before you attempt this!
*/
fn invert_self(&mut self);
/**
* Sets the matrix to its transpose
*/
fn transpose_self(&mut self);
} }
/** /**
@ -436,7 +471,7 @@ pub impl<T:Copy Float> Mat2<T>: Matrix<T, Vec2<T>> {
} }
} }
pub impl<T:Copy Float> Mat2<T>: MutableMatrix<T, Vec2<T>> { pub impl<T:Copy Float Sign> Mat2<T>: MutableMatrix<T, Vec2<T>> {
#[inline(always)] #[inline(always)]
fn col_mut(&mut self, i: uint) -> &self/mut Vec2<T> { fn col_mut(&mut self, i: uint) -> &self/mut Vec2<T> {
match i { match i {
@ -458,14 +493,51 @@ pub impl<T:Copy Float> Mat2<T>: MutableMatrix<T, Vec2<T>> {
self.y.swap(a, b); self.y.swap(a, b);
} }
#[inline(always)]
fn set(&mut self, other: &Mat2<T>) {
(*self) = (*other);
}
#[inline(always)] #[inline(always)]
fn to_identity(&mut self) { fn to_identity(&mut self) {
*self = Mat2::identity(); (*self) = Mat2::identity();
} }
#[inline(always)] #[inline(always)]
fn to_zero(&mut self) { fn to_zero(&mut self) {
*self = Mat2::zero(); (*self) = Mat2::zero();
}
#[inline(always)]
fn mul_self_t(&mut self, value: T) {
self.col_mut(0).mul_self_t(&value);
self.col_mut(1).mul_self_t(&value);
}
#[inline(always)]
fn add_self_m(&mut self, other: &Mat2<T>) {
self.col_mut(0).add_self_v(&other[0]);
self.col_mut(1).add_self_v(&other[1]);
}
#[inline(always)]
fn sub_self_m(&mut self, other: &Mat2<T>) {
self.col_mut(0).sub_self_v(&other[0]);
self.col_mut(1).sub_self_v(&other[1]);
}
#[inline(always)]
fn invert_self(&mut self) {
match self.inverse() {
Some(m) => (*self) = m,
None => fail(~"Couldn't invert the matrix!")
}
}
#[inline(always)]
fn transpose_self(&mut self) {
util::swap(self.col_mut(0).index_mut(1), self.col_mut(1).index_mut(0));
util::swap(self.col_mut(1).index_mut(0), self.col_mut(0).index_mut(1));
} }
} }
@ -844,7 +916,7 @@ pub impl<T:Copy Float> Mat3<T>: Matrix<T, Vec3<T>> {
} }
} }
pub impl<T:Copy Float> Mat3<T>: MutableMatrix<T, Vec3<T>> { pub impl<T:Copy Float Sign> Mat3<T>: MutableMatrix<T, Vec3<T>> {
#[inline(always)] #[inline(always)]
fn col_mut(&mut self, i: uint) -> &self/mut Vec3<T> { fn col_mut(&mut self, i: uint) -> &self/mut Vec3<T> {
match i { match i {
@ -868,14 +940,60 @@ pub impl<T:Copy Float> Mat3<T>: MutableMatrix<T, Vec3<T>> {
self.z.swap(a, b); self.z.swap(a, b);
} }
#[inline(always)]
fn set(&mut self, other: &Mat3<T>) {
(*self) = (*other);
}
#[inline(always)] #[inline(always)]
fn to_identity(&mut self) { fn to_identity(&mut self) {
*self = Mat3::identity(); (*self) = Mat3::identity();
} }
#[inline(always)] #[inline(always)]
fn to_zero(&mut self) { fn to_zero(&mut self) {
*self = Mat3::zero(); (*self) = Mat3::zero();
}
#[inline(always)]
fn mul_self_t(&mut self, value: T) {
self.col_mut(0).mul_self_t(&value);
self.col_mut(1).mul_self_t(&value);
self.col_mut(2).mul_self_t(&value);
}
#[inline(always)]
fn add_self_m(&mut self, other: &Mat3<T>) {
self.col_mut(0).add_self_v(&other[0]);
self.col_mut(1).add_self_v(&other[1]);
self.col_mut(2).add_self_v(&other[2]);
}
#[inline(always)]
fn sub_self_m(&mut self, other: &Mat3<T>) {
self.col_mut(0).sub_self_v(&other[0]);
self.col_mut(1).sub_self_v(&other[1]);
self.col_mut(2).sub_self_v(&other[2]);
}
#[inline(always)]
fn invert_self(&mut self) {
match self.inverse() {
Some(m) => (*self) = m,
None => fail(~"Couldn't invert the matrix!")
}
}
#[inline(always)]
fn transpose_self(&mut self) {
util::swap(self.col_mut(0).index_mut(1), self.col_mut(1).index_mut(0));
util::swap(self.col_mut(0).index_mut(2), self.col_mut(2).index_mut(0));
util::swap(self.col_mut(1).index_mut(0), self.col_mut(0).index_mut(1));
util::swap(self.col_mut(1).index_mut(2), self.col_mut(2).index_mut(1));
util::swap(self.col_mut(2).index_mut(0), self.col_mut(0).index_mut(2));
util::swap(self.col_mut(2).index_mut(1), self.col_mut(1).index_mut(2));
} }
} }
@ -1403,7 +1521,7 @@ pub impl<T:Copy Float Sign> Mat4<T>: Matrix<T, Vec4<T>> {
} }
} }
pub impl<T:Copy Float> Mat4<T>: MutableMatrix<T, Vec4<T>> { pub impl<T:Copy Float Sign> Mat4<T>: MutableMatrix<T, Vec4<T>> {
#[inline(always)] #[inline(always)]
fn col_mut(&mut self, i: uint) -> &self/mut Vec4<T> { fn col_mut(&mut self, i: uint) -> &self/mut Vec4<T> {
match i { match i {
@ -1429,14 +1547,70 @@ pub impl<T:Copy Float> Mat4<T>: MutableMatrix<T, Vec4<T>> {
self.w.swap(a, b); self.w.swap(a, b);
} }
#[inline(always)]
fn set(&mut self, other: &Mat4<T>) {
(*self) = (*other);
}
#[inline(always)] #[inline(always)]
fn to_identity(&mut self) { fn to_identity(&mut self) {
*self = Mat4::identity(); (*self) = Mat4::identity();
} }
#[inline(always)] #[inline(always)]
fn to_zero(&mut self) { fn to_zero(&mut self) {
*self = Mat4::zero(); (*self) = Mat4::zero();
}
#[inline(always)]
fn mul_self_t(&mut self, value: T) {
self.col_mut(0).mul_self_t(&value);
self.col_mut(1).mul_self_t(&value);
self.col_mut(2).mul_self_t(&value);
self.col_mut(3).mul_self_t(&value);
}
#[inline(always)]
fn add_self_m(&mut self, other: &Mat4<T>) {
self.col_mut(0).add_self_v(&other[0]);
self.col_mut(1).add_self_v(&other[1]);
self.col_mut(2).add_self_v(&other[2]);
self.col_mut(3).add_self_v(&other[3]);
}
#[inline(always)]
fn sub_self_m(&mut self, other: &Mat4<T>) {
self.col_mut(0).sub_self_v(&other[0]);
self.col_mut(1).sub_self_v(&other[1]);
self.col_mut(2).sub_self_v(&other[2]);
self.col_mut(3).sub_self_v(&other[3]);
}
#[inline(always)]
fn invert_self(&mut self) {
match self.inverse() {
Some(m) => (*self) = m,
None => fail(~"Couldn't invert the matrix!")
}
}
#[inline(always)]
fn transpose_self(&mut self) {
util::swap(self.col_mut(0).index_mut(1), self.col_mut(1).index_mut(0));
util::swap(self.col_mut(0).index_mut(2), self.col_mut(2).index_mut(0));
util::swap(self.col_mut(0).index_mut(3), self.col_mut(3).index_mut(0));
util::swap(self.col_mut(1).index_mut(0), self.col_mut(0).index_mut(1));
util::swap(self.col_mut(1).index_mut(2), self.col_mut(2).index_mut(1));
util::swap(self.col_mut(1).index_mut(3), self.col_mut(3).index_mut(1));
util::swap(self.col_mut(2).index_mut(0), self.col_mut(0).index_mut(2));
util::swap(self.col_mut(2).index_mut(1), self.col_mut(1).index_mut(2));
util::swap(self.col_mut(2).index_mut(3), self.col_mut(3).index_mut(2));
util::swap(self.col_mut(3).index_mut(0), self.col_mut(0).index_mut(3));
util::swap(self.col_mut(3).index_mut(1), self.col_mut(1).index_mut(3));
util::swap(self.col_mut(3).index_mut(2), self.col_mut(2).index_mut(3));
} }
} }

View file

@ -10,8 +10,6 @@ fn test_Mat2() {
let b = Mat2 { x: Vec2 { x: 2f, y: 4f }, let b = Mat2 { x: Vec2 { x: 2f, y: 4f },
y: Vec2 { x: 3f, y: 5f } }; y: Vec2 { x: 3f, y: 5f } };
let mut mut_a = a;
let v1 = Vec2::new(1f, 2f); let v1 = Vec2::new(1f, 2f);
let f1 = 0.5f; let f1 = 0.5f;
@ -33,28 +31,11 @@ fn test_Mat2() {
assert a.col(0) == Vec2::new(1f, 3f); assert a.col(0) == Vec2::new(1f, 3f);
assert a.col(1) == Vec2::new(2f, 4f); assert a.col(1) == Vec2::new(2f, 4f);
mut_a.swap_cols(0, 1);
assert mut_a.col(0) == a.col(1);
assert mut_a.col(1) == a.col(0);
mut_a = a;
mut_a.swap_rows(0, 1);
assert mut_a.row(0) == a.row(1);
assert mut_a.row(1) == a.row(0);
mut_a = a;
assert Mat2::identity() == Mat2::new(1f, 0f, assert Mat2::identity() == Mat2::new(1f, 0f,
0f, 1f); 0f, 1f);
mut_a.to_identity();
assert mut_a.is_identity();
mut_a = a;
assert Mat2::zero() == Mat2::new(0f, 0f, assert Mat2::zero() == Mat2::new(0f, 0f,
0f, 0f); 0f, 0f);
mut_a.to_zero();
assert mut_a == Mat2::new(0f, 0f,
0f, 0f);
assert a.determinant() == -2f; assert a.determinant() == -2f;
assert a.trace() == 5f; assert a.trace() == 5f;
@ -123,6 +104,59 @@ fn test_Mat2() {
0f, 0f, 0f, 1f); 0f, 0f, 0f, 1f);
} }
fn test_Mat2_mut() {
let a = Mat2 { x: Vec2 { x: 1f, y: 3f },
y: Vec2 { x: 2f, y: 4f } };
let b = Mat2 { x: Vec2 { x: 2f, y: 4f },
y: Vec2 { x: 3f, y: 5f } };
let f1 = 0.5f;
let mut mut_a = a;
mut_a.swap_cols(0, 1);
assert mut_a.col(0) == a.col(1);
assert mut_a.col(1) == a.col(0);
mut_a = a;
mut_a.swap_rows(0, 1);
assert mut_a.row(0) == a.row(1);
assert mut_a.row(1) == a.row(0);
mut_a = a;
mut_a.set(&b);
assert mut_a == b;
mut_a = a;
mut_a.to_identity();
assert mut_a.is_identity();
mut_a = a;
mut_a.to_zero();
assert mut_a == Mat2::zero();
mut_a = a;
mut_a.mul_self_t(f1);
assert mut_a == a.mul_t(f1);
mut_a = a;
mut_a.add_self_m(&b);
assert mut_a == a.add_m(&b);
mut_a = a;
mut_a.sub_self_m(&b);
assert mut_a == a.sub_m(&b);
mut_a = a;
mut_a.invert_self();
assert mut_a == option::unwrap(a.inverse());
mut_a = a;
mut_a.transpose_self();
assert mut_a == a.transpose();
// mut_a = a;
}
#[test] #[test]
fn test_Mat3() { fn test_Mat3() {
let a = Mat3 { x: Vec3 { x: 1f, y: 4f, z: 7f }, let a = Mat3 { x: Vec3 { x: 1f, y: 4f, z: 7f },
@ -132,8 +166,6 @@ fn test_Mat3() {
y: Vec3 { x: 3f, y: 6f, z: 9f }, y: Vec3 { x: 3f, y: 6f, z: 9f },
z: Vec3 { x: 4f, y: 7f, z: 10f } }; z: Vec3 { x: 4f, y: 7f, z: 10f } };
let mut mut_a = a;
let v1 = Vec3::new(1f, 2f, 3f); let v1 = Vec3::new(1f, 2f, 3f);
let f1 = 0.5f; let f1 = 0.5f;
@ -166,40 +198,13 @@ fn test_Mat3() {
assert a.col(1) == Vec3::new(2f, 5f, 8f); assert a.col(1) == Vec3::new(2f, 5f, 8f);
assert a.col(2) == Vec3::new(3f, 6f, 9f); assert a.col(2) == Vec3::new(3f, 6f, 9f);
mut_a.swap_cols(0, 2);
assert mut_a.col(0) == a.col(2);
assert mut_a.col(2) == a.col(0);
mut_a = a;
mut_a.swap_cols(1, 2);
assert mut_a.col(1) == a.col(2);
assert mut_a.col(2) == a.col(1);
mut_a = a;
mut_a.swap_rows(0, 2);
assert mut_a.row(0) == a.row(2);
assert mut_a.row(2) == a.row(0);
mut_a = a;
mut_a.swap_rows(1, 2);
assert mut_a.row(1) == a.row(2);
assert mut_a.row(2) == a.row(1);
mut_a = a;
assert Mat3::identity() == Mat3::new(1f, 0f, 0f, assert Mat3::identity() == Mat3::new(1f, 0f, 0f,
0f, 1f, 0f, 0f, 1f, 0f,
0f, 0f, 1f); 0f, 0f, 1f);
mut_a.to_identity();
assert mut_a.is_identity();
mut_a = a;
assert Mat3::zero() == Mat3::new(0f, 0f, 0f, assert Mat3::zero() == Mat3::new(0f, 0f, 0f,
0f, 0f, 0f, 0f, 0f, 0f,
0f, 0f, 0f); 0f, 0f, 0f);
mut_a.to_zero();
assert mut_a == Mat3::new(0f, 0f, 0f,
0f, 0f, 0f,
0f, 0f, 0f);
assert a.determinant() == 0f; assert a.determinant() == 0f;
assert a.trace() == 15f; assert a.trace() == 15f;
@ -278,6 +283,75 @@ fn test_Mat3() {
// to_Quaternion // to_Quaternion
} }
fn test_Mat3_mut() {
let a = Mat3 { x: Vec3 { x: 1f, y: 4f, z: 7f },
y: Vec3 { x: 2f, y: 5f, z: 8f },
z: Vec3 { x: 3f, y: 6f, z: 9f } };
let b = Mat3 { x: Vec3 { x: 2f, y: 5f, z: 8f },
y: Vec3 { x: 3f, y: 6f, z: 9f },
z: Vec3 { x: 4f, y: 7f, z: 10f } };
let c = Mat3 { x: Vec3 { x: 2f, y: 4f, z: 6f },
y: Vec3 { x: 0f, y: 2f, z: 4f },
z: Vec3 { x: 0f, y: 0f, z: 1f } };
let f1 = 0.5f;
let mut mut_a = a;
let mut mut_c = c;
mut_a.swap_cols(0, 2);
assert mut_a.col(0) == a.col(2);
assert mut_a.col(2) == a.col(0);
mut_a = a;
mut_a.swap_cols(1, 2);
assert mut_a.col(1) == a.col(2);
assert mut_a.col(2) == a.col(1);
mut_a = a;
mut_a.swap_rows(0, 2);
assert mut_a.row(0) == a.row(2);
assert mut_a.row(2) == a.row(0);
mut_a = a;
mut_a.swap_rows(1, 2);
assert mut_a.row(1) == a.row(2);
assert mut_a.row(2) == a.row(1);
mut_a = a;
mut_a.set(&b);
assert mut_a == b;
mut_a = a;
mut_a.to_identity();
assert mut_a.is_identity();
mut_a = a;
mut_a.to_zero();
assert mut_a == Mat3::zero();
mut_a = a;
mut_a.mul_self_t(f1);
assert mut_a == a.mul_t(f1);
mut_a = a;
mut_a.add_self_m(&b);
assert mut_a == a.add_m(&b);
mut_a = a;
mut_a.sub_self_m(&b);
assert mut_a == a.sub_m(&b);
mut_a = a;
mut_c.invert_self();
assert mut_c == option::unwrap(c.inverse());
// mut_c = c;
mut_a.transpose_self();
assert mut_a == a.transpose();
// mut_a = a;
}
#[test] #[test]
fn test_Mat4() { fn test_Mat4() {
let a = Mat4 { x: Vec4 { x: 1f, y: 5f, z: 9f, w: 13f }, let a = Mat4 { x: Vec4 { x: 1f, y: 5f, z: 9f, w: 13f },
@ -293,8 +367,6 @@ fn test_Mat4() {
z: Vec4 { x: 1f, y: 2f, z: 3f, w: 3f }, z: Vec4 { x: 1f, y: 2f, z: 3f, w: 3f },
w: Vec4 { x: 0f, y: 1f, z: 1f, w: 0f } }; w: Vec4 { x: 0f, y: 1f, z: 1f, w: 0f } };
let mut mut_a = a;
let v1 = Vec4::new(1f, 2f, 3f, 4f); let v1 = Vec4::new(1f, 2f, 3f, 4f);
let f1 = 0.5f; let f1 = 0.5f;
@ -341,43 +413,15 @@ fn test_Mat4() {
assert a.col(2) == Vec4::new(3f, 7f, 11f, 15f); assert a.col(2) == Vec4::new(3f, 7f, 11f, 15f);
assert a.col(3) == Vec4::new(4f, 8f, 12f, 16f); assert a.col(3) == Vec4::new(4f, 8f, 12f, 16f);
mut_a.swap_cols(0, 3);
assert mut_a.col(0) == a.col(3);
assert mut_a.col(3) == a.col(0);
mut_a = a;
mut_a.swap_cols(1, 2);
assert mut_a.col(1) == a.col(2);
assert mut_a.col(2) == a.col(1);
mut_a = a;
mut_a.swap_rows(0, 3);
assert mut_a.row(0) == a.row(3);
assert mut_a.row(3) == a.row(0);
mut_a = a;
mut_a.swap_rows(1, 2);
assert mut_a.row(1) == a.row(2);
assert mut_a.row(2) == a.row(1);
mut_a = a;
assert Mat4::identity() == Mat4::new(1f, 0f, 0f, 0f, assert Mat4::identity() == Mat4::new(1f, 0f, 0f, 0f,
0f, 1f, 0f, 0f, 0f, 1f, 0f, 0f,
0f, 0f, 1f, 0f, 0f, 0f, 1f, 0f,
0f, 0f, 0f, 1f); 0f, 0f, 0f, 1f);
mut_a.to_identity();
assert mut_a.is_identity();
mut_a = a;
assert Mat4::zero() == Mat4::new(0f, 0f, 0f, 0f, assert Mat4::zero() == Mat4::new(0f, 0f, 0f, 0f,
0f, 0f, 0f, 0f, 0f, 0f, 0f, 0f,
0f, 0f, 0f, 0f, 0f, 0f, 0f, 0f,
0f, 0f, 0f, 0f); 0f, 0f, 0f, 0f);
mut_a.to_zero();
assert mut_a == Mat4::new(0f, 0f, 0f, 0f,
0f, 0f, 0f, 0f,
0f, 0f, 0f, 0f,
0f, 0f, 0f, 0f);
assert a.determinant() == 0f; assert a.determinant() == 0f;
assert a.trace() == 34f; assert a.trace() == 34f;
@ -452,3 +496,75 @@ fn test_Mat4() {
assert Mat4::from_value(6f).is_diagonal(); assert Mat4::from_value(6f).is_diagonal();
} }
fn test_Mat4_mut() {
let a = Mat4 { x: Vec4 { x: 1f, y: 5f, z: 9f, w: 13f },
y: Vec4 { x: 2f, y: 6f, z: 10f, w: 14f },
z: Vec4 { x: 3f, y: 7f, z: 11f, w: 15f },
w: Vec4 { x: 4f, y: 8f, z: 12f, w: 16f } };
let b = Mat4 { x: Vec4 { x: 2f, y: 6f, z: 10f, w: 14f },
y: Vec4 { x: 3f, y: 7f, z: 11f, w: 15f },
z: Vec4 { x: 4f, y: 8f, z: 12f, w: 16f },
w: Vec4 { x: 5f, y: 9f, z: 13f, w: 17f } };
let c = Mat4 { x: Vec4 { x: 3f, y: 2f, z: 1f, w: 1f },
y: Vec4 { x: 2f, y: 3f, z: 2f, w: 2f },
z: Vec4 { x: 1f, y: 2f, z: 3f, w: 3f },
w: Vec4 { x: 0f, y: 1f, z: 1f, w: 0f } };
let f1 = 0.5f;
let mut mut_a = a;
let mut mut_c = c;
mut_a.swap_cols(0, 3);
assert mut_a.col(0) == a.col(3);
assert mut_a.col(3) == a.col(0);
mut_a = a;
mut_a.swap_cols(1, 2);
assert mut_a.col(1) == a.col(2);
assert mut_a.col(2) == a.col(1);
mut_a = a;
mut_a.swap_rows(0, 3);
assert mut_a.row(0) == a.row(3);
assert mut_a.row(3) == a.row(0);
mut_a = a;
mut_a.swap_rows(1, 2);
assert mut_a.row(1) == a.row(2);
assert mut_a.row(2) == a.row(1);
mut_a = a;
mut_a.set(&b);
assert mut_a == b;
mut_a = a;
mut_a.to_identity();
assert mut_a.is_identity();
mut_a = a;
mut_a.to_zero();
assert mut_a == Mat4::zero();
mut_a = a;
mut_a.mul_self_t(f1);
assert mut_a == a.mul_t(f1);
mut_a = a;
mut_a.add_self_m(&b);
assert mut_a == a.add_m(&b);
mut_a = a;
mut_a.sub_self_m(&b);
assert mut_a == a.sub_m(&b);
mut_a = a;
mut_c.invert_self();
assert mut_c == option::unwrap(c.inverse());
// mut_c = c;
mut_a.transpose_self();
assert mut_a == a.transpose();
// mut_a = a;
}