From 7d6884c3df72fb16c4e24adffeff6d9c40ec2061 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Crozet?= Date: Mon, 11 Aug 2014 19:54:13 +0200 Subject: [PATCH] Add a `Det` trait to compute the determinant + implement it for `Mat{1,2,3}`. --- src/na.rs | 10 +++++++++ src/structs/dvec.rs | 2 +- src/structs/spec/mat.rs | 45 +++++++++++++++++++++++++++++----------- src/traits/mod.rs | 2 +- src/traits/operations.rs | 20 +++++++++++------- 5 files changed, 58 insertions(+), 21 deletions(-) diff --git a/src/na.rs b/src/na.rs index d7a5bc28..0c5c6804 100644 --- a/src/na.rs +++ b/src/na.rs @@ -15,6 +15,7 @@ pub use traits::{ Cov, Cross, CrossMatrix, + Det, Dim, Dot, FromHomogeneous, @@ -580,6 +581,15 @@ pub fn normalize, N: Float>(v: &V) -> V { Norm::normalize_cpy(v) } +/* + * Det + */ +/// Computes the determinant of a square matrix. +#[inline(always)] +pub fn det, N>(m: &M) -> N { + Det::det(m) +} + /* * Cross */ diff --git a/src/structs/dvec.rs b/src/structs/dvec.rs index 58f43383..9b2fd38a 100644 --- a/src/structs/dvec.rs +++ b/src/structs/dvec.rs @@ -327,7 +327,7 @@ impl Norm for DVec { let l = Norm::norm(self); 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 diff --git a/src/structs/spec/mat.rs b/src/structs/spec/mat.rs index c99cb9f5..d35e0d75 100644 --- a/src/structs/spec/mat.rs +++ b/src/structs/spec/mat.rs @@ -1,12 +1,11 @@ use std::num::{Zero, One}; use structs::vec::{Vec2, Vec3, Vec2MulRhs, Vec3MulRhs}; use structs::mat::{Mat1, Mat2, Mat3, Mat3MulRhs, Mat2MulRhs}; -use traits::operations::Inv; +use traits::operations::{Inv, Det}; use traits::structure::{Row, Col}; // some specializations: -impl -Inv for Mat1 { +impl Inv for Mat1 { #[inline] fn inv_cpy(m: &Mat1) -> Option> { let mut res = m.clone(); @@ -26,14 +25,14 @@ Inv for Mat1 { } else { let _1: N = One::one(); - self.m11 = _1 / self.m11; + + self.m11 = _1 / Det::det(self); true } } } -impl -Inv for Mat2 { +impl Inv for Mat2 { #[inline] fn inv_cpy(m: &Mat2) -> Option> { let mut res = m.clone(); @@ -48,7 +47,7 @@ Inv for Mat2 { #[inline] fn inv(&mut self) -> bool { - let det = self.m11 * self.m22 - self.m21 * self.m12; + let det = Det::det(self); if det.is_zero() { false @@ -63,8 +62,7 @@ Inv for Mat2 { } } -impl -Inv for Mat3 { +impl Inv for Mat3 { #[inline] fn inv_cpy(m: &Mat3) -> Option> { let mut res = m.clone(); @@ -83,9 +81,7 @@ Inv for Mat3 { 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 det = self.m11 * minor_m12_m23 - - self.m12 * minor_m11_m23 - + self.m13 * minor_m11_m22; + let det = self.m11 * minor_m12_m23 - self.m12 * minor_m11_m23 + self.m13 * minor_m11_m22; if det.is_zero() { false @@ -110,6 +106,31 @@ Inv for Mat3 { } } +impl Det for Mat1 { + #[inline] + fn det(m: &Mat1) -> N { + m.m11.clone() + } +} + +impl Det for Mat2 { + #[inline] + fn det(m: &Mat2) -> N { + m.m11 * m.m22 - m.m21 * m.m12 + } +} + +impl Det for Mat3 { + #[inline] + fn det(m: &Mat3) -> 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 Row> for Mat3 { #[inline] fn nrows(&self) -> uint { diff --git a/src/traits/mod.rs b/src/traits/mod.rs index a4901797..299f11ab 100644 --- a/src/traits/mod.rs +++ b/src/traits/mod.rs @@ -8,7 +8,7 @@ pub use self::structure::{FloatVec, FloatVecExt, Basis, Cast, Col, Dim, Indexabl Iterable, IterableMut, Mat, Row, AnyVec, VecExt, 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}; pub use self::operations::{PartialOrdering, PartialLess, PartialEqual, PartialGreater, NotComparable}; diff --git a/src/traits/operations.rs b/src/traits/operations.rs index cb09a0ee..58600e9c 100644 --- a/src/traits/operations.rs +++ b/src/traits/operations.rs @@ -196,13 +196,19 @@ pub trait Absolute { /// Trait of objects having an inverse. Typically used to implement matrix inverse. pub trait Inv { - /// Returns the inverse of `self`. + /// Returns the inverse of `m`. fn inv_cpy(m: &Self) -> Option; /// In-place version of `inverse`. fn inv(&mut self) -> bool; } +/// Trait of objects having a determinant. Typically used by square matrices. +pub trait Det { + /// Returns the determinant of `m`. + fn det(m: &Self) -> N; +} + /// Trait of objects which can be transposed. pub trait Transpose { /// Computes the transpose of a matrix. @@ -214,19 +220,19 @@ pub trait Transpose { /// Traits of objects having an outer product. pub trait Outer { - /// Computes the outer product: `self * other` + /// Computes the outer product: `a * b` fn outer(a: &Self, b: &Self) -> M; } /// Trait for computing the covariance of a set of data. pub trait Cov { - /// 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 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 vectors, observations are stored in its components (thus are 1-dimensional). @@ -237,11 +243,11 @@ pub trait Cov { /// Trait for computing the covariance of a set of data. pub trait Mean { - /// 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 vectors, observations are stored in its components (thus are 1-dimensional). - fn mean(&Self) -> N; + fn mean(v: &Self) -> N; }