Add a Det trait to compute the determinant + implement it for Mat{1,2,3}.

This commit is contained in:
Sébastien Crozet 2014-08-11 19:54:13 +02:00
parent 725f53d1e7
commit 7d6884c3df
5 changed files with 58 additions and 21 deletions

View File

@ -15,6 +15,7 @@ pub use traits::{
Cov, Cov,
Cross, Cross,
CrossMatrix, CrossMatrix,
Det,
Dim, Dim,
Dot, Dot,
FromHomogeneous, FromHomogeneous,
@ -580,6 +581,15 @@ pub fn normalize<V: Norm<N>, N: Float>(v: &V) -> V {
Norm::normalize_cpy(v) Norm::normalize_cpy(v)
} }
/*
* Det<N>
*/
/// Computes the determinant of a square matrix.
#[inline(always)]
pub fn det<M: Det<N>, N>(m: &M) -> N {
Det::det(m)
}
/* /*
* Cross<V> * Cross<V>
*/ */

View File

@ -327,7 +327,7 @@ impl<N: Float + Clone> Norm<N> for DVec<N> {
let l = Norm::norm(self); let l = Norm::norm(self);
for i in range(0u, self.at.len()) { for i in range(0u, self.at.len()) {
*self.at.get_mut(i) = *self.at.get(i) / l; *self.at.get_mut(i) = self.at[i] / l;
} }
l l

View File

@ -1,12 +1,11 @@
use std::num::{Zero, One}; use std::num::{Zero, One};
use structs::vec::{Vec2, Vec3, Vec2MulRhs, Vec3MulRhs}; use structs::vec::{Vec2, Vec3, Vec2MulRhs, Vec3MulRhs};
use structs::mat::{Mat1, Mat2, Mat3, Mat3MulRhs, Mat2MulRhs}; use structs::mat::{Mat1, Mat2, Mat3, Mat3MulRhs, Mat2MulRhs};
use traits::operations::Inv; use traits::operations::{Inv, Det};
use traits::structure::{Row, Col}; use traits::structure::{Row, Col};
// some specializations: // some specializations:
impl<N: Num + Clone> impl<N: Num + Clone> Inv for Mat1<N> {
Inv for Mat1<N> {
#[inline] #[inline]
fn inv_cpy(m: &Mat1<N>) -> Option<Mat1<N>> { fn inv_cpy(m: &Mat1<N>) -> Option<Mat1<N>> {
let mut res = m.clone(); let mut res = m.clone();
@ -26,14 +25,14 @@ Inv for Mat1<N> {
} }
else { else {
let _1: N = One::one(); let _1: N = One::one();
self.m11 = _1 / self.m11;
self.m11 = _1 / Det::det(self);
true true
} }
} }
} }
impl<N: Num + Clone> impl<N: Num + Clone> Inv for Mat2<N> {
Inv for Mat2<N> {
#[inline] #[inline]
fn inv_cpy(m: &Mat2<N>) -> Option<Mat2<N>> { fn inv_cpy(m: &Mat2<N>) -> Option<Mat2<N>> {
let mut res = m.clone(); let mut res = m.clone();
@ -48,7 +47,7 @@ Inv for Mat2<N> {
#[inline] #[inline]
fn inv(&mut self) -> bool { fn inv(&mut self) -> bool {
let det = self.m11 * self.m22 - self.m21 * self.m12; let det = Det::det(self);
if det.is_zero() { if det.is_zero() {
false false
@ -63,8 +62,7 @@ Inv for Mat2<N> {
} }
} }
impl<N: Num + Clone> impl<N: Num + Clone> Inv for Mat3<N> {
Inv for Mat3<N> {
#[inline] #[inline]
fn inv_cpy(m: &Mat3<N>) -> Option<Mat3<N>> { fn inv_cpy(m: &Mat3<N>) -> Option<Mat3<N>> {
let mut res = m.clone(); let mut res = m.clone();
@ -83,9 +81,7 @@ Inv for Mat3<N> {
let minor_m11_m23 = self.m21 * self.m33 - self.m31 * self.m23; let minor_m11_m23 = self.m21 * self.m33 - self.m31 * self.m23;
let minor_m11_m22 = self.m21 * self.m32 - self.m31 * self.m22; let minor_m11_m22 = self.m21 * self.m32 - self.m31 * self.m22;
let det = self.m11 * minor_m12_m23 let det = self.m11 * minor_m12_m23 - self.m12 * minor_m11_m23 + self.m13 * minor_m11_m22;
- self.m12 * minor_m11_m23
+ self.m13 * minor_m11_m22;
if det.is_zero() { if det.is_zero() {
false false
@ -110,6 +106,31 @@ Inv for Mat3<N> {
} }
} }
impl<N: Num + Clone> Det<N> for Mat1<N> {
#[inline]
fn det(m: &Mat1<N>) -> N {
m.m11.clone()
}
}
impl<N: Num> Det<N> for Mat2<N> {
#[inline]
fn det(m: &Mat2<N>) -> N {
m.m11 * m.m22 - m.m21 * m.m12
}
}
impl<N: Num> Det<N> for Mat3<N> {
#[inline]
fn det(m: &Mat3<N>) -> N {
let minor_m12_m23 = m.m22 * m.m33 - m.m32 * m.m23;
let minor_m11_m23 = m.m21 * m.m33 - m.m31 * m.m23;
let minor_m11_m22 = m.m21 * m.m32 - m.m31 * m.m22;
m.m11 * minor_m12_m23 - m.m12 * minor_m11_m23 + m.m13 * minor_m11_m22
}
}
impl<N: Clone> Row<Vec3<N>> for Mat3<N> { impl<N: Clone> Row<Vec3<N>> for Mat3<N> {
#[inline] #[inline]
fn nrows(&self) -> uint { fn nrows(&self) -> uint {

View File

@ -8,7 +8,7 @@ pub use self::structure::{FloatVec, FloatVecExt, Basis, Cast, Col, Dim, Indexabl
Iterable, IterableMut, Mat, Row, AnyVec, VecExt, Iterable, IterableMut, Mat, Row, AnyVec, VecExt,
ColSlice, RowSlice, Eye}; ColSlice, RowSlice, Eye};
pub use self::operations::{Absolute, ApproxEq, Cov, Inv, LMul, Mean, Outer, PartialOrd, RMul, pub use self::operations::{Absolute, ApproxEq, Cov, Det, Inv, LMul, Mean, Outer, PartialOrd, RMul,
ScalarAdd, ScalarSub, ScalarMul, ScalarDiv, Transpose}; ScalarAdd, ScalarSub, ScalarMul, ScalarDiv, Transpose};
pub use self::operations::{PartialOrdering, PartialLess, PartialEqual, PartialGreater, NotComparable}; pub use self::operations::{PartialOrdering, PartialLess, PartialEqual, PartialGreater, NotComparable};

View File

@ -196,13 +196,19 @@ pub trait Absolute<A> {
/// Trait of objects having an inverse. Typically used to implement matrix inverse. /// Trait of objects having an inverse. Typically used to implement matrix inverse.
pub trait Inv { pub trait Inv {
/// Returns the inverse of `self`. /// Returns the inverse of `m`.
fn inv_cpy(m: &Self) -> Option<Self>; fn inv_cpy(m: &Self) -> Option<Self>;
/// In-place version of `inverse`. /// In-place version of `inverse`.
fn inv(&mut self) -> bool; fn inv(&mut self) -> bool;
} }
/// Trait of objects having a determinant. Typically used by square matrices.
pub trait Det<N> {
/// Returns the determinant of `m`.
fn det(m: &Self) -> N;
}
/// Trait of objects which can be transposed. /// Trait of objects which can be transposed.
pub trait Transpose { pub trait Transpose {
/// Computes the transpose of a matrix. /// Computes the transpose of a matrix.
@ -214,19 +220,19 @@ pub trait Transpose {
/// Traits of objects having an outer product. /// Traits of objects having an outer product.
pub trait Outer<M> { pub trait Outer<M> {
/// Computes the outer product: `self * other` /// Computes the outer product: `a * b`
fn outer(a: &Self, b: &Self) -> M; fn outer(a: &Self, b: &Self) -> M;
} }
/// Trait for computing the covariance of a set of data. /// Trait for computing the covariance of a set of data.
pub trait Cov<M> { pub trait Cov<M> {
/// Computes the covariance of the obsevations stored by `self`: /// Computes the covariance of the obsevations stored by `m`:
/// ///
/// * For matrices, observations are stored in its rows. /// * For matrices, observations are stored in its rows.
/// * For vectors, observations are stored in its components (thus are 1-dimensional). /// * For vectors, observations are stored in its components (thus are 1-dimensional).
fn cov(&Self) -> M; fn cov(m: &Self) -> M;
/// Computes the covariance of the obsevations stored by `self`: /// Computes the covariance of the obsevations stored by `m`:
/// ///
/// * For matrices, observations are stored in its rows. /// * For matrices, observations are stored in its rows.
/// * For vectors, observations are stored in its components (thus are 1-dimensional). /// * For vectors, observations are stored in its components (thus are 1-dimensional).
@ -237,11 +243,11 @@ pub trait Cov<M> {
/// Trait for computing the covariance of a set of data. /// Trait for computing the covariance of a set of data.
pub trait Mean<N> { pub trait Mean<N> {
/// Computes the mean of the observations stored by `self`. /// Computes the mean of the observations stored by `v`.
/// ///
/// * For matrices, observations are stored in its rows. /// * For matrices, observations are stored in its rows.
/// * For vectors, observations are stored in its components (thus are 1-dimensional). /// * For vectors, observations are stored in its components (thus are 1-dimensional).
fn mean(&Self) -> N; fn mean(v: &Self) -> N;
} }