Add a SquareMat trait for square matrices.

This commit is contained in:
Sébastien Crozet 2014-10-26 16:30:09 +01:00
parent 6a194b2b62
commit 27be1f0651
8 changed files with 36 additions and 35 deletions

View File

@ -152,6 +152,7 @@ pub use traits::{
ScalarAdd, ScalarSub, ScalarAdd, ScalarSub,
ScalarMul, ScalarDiv, ScalarMul, ScalarDiv,
Shape, Shape,
SquareMat,
ToHomogeneous, ToHomogeneous,
Transform, Transformation, Transform, Transformation,
Translate, Translation, Translate, Translation,
@ -644,7 +645,7 @@ pub fn append_rotation_wrt_center<LV: Neg<LV>,
/// Builds a rotation matrix from `r`. /// Builds a rotation matrix from `r`.
#[inline(always)] #[inline(always)]
pub fn to_rot_mat<LV, AV, M: Mat<LV, LV> + Rotation<AV>, R: RotationMatrix<LV, AV, M>>(r: &R) -> M { pub fn to_rot_mat<N, LV, AV, M: Mat<N, LV, LV> + Rotation<AV>, R: RotationMatrix<N, LV, AV, M>>(r: &R) -> M {
r.to_rot_mat() r.to_rot_mat()
} }

View File

@ -1,6 +1,6 @@
use std::num::{Zero, Float}; use std::num::{Zero, Float};
use traits::operations::{Transpose, ApproxEq}; use traits::operations::{Transpose, ApproxEq};
use traits::structure::{ColSlice, Eye, Indexable, Diag}; use traits::structure::{ColSlice, Eye, Indexable, Diag, SquareMat};
use traits::geometry::Norm; use traits::geometry::Norm;
use std::cmp::min; use std::cmp::min;
@ -73,19 +73,17 @@ pub fn qr<N, V, M>(m: &M) -> (M, M)
} }
/// Eigendecomposition of a square matrix using the qr algorithm. /// Eigendecomposition of a square matrix using the qr algorithm.
pub fn eigen_qr<N, V, V2, M>(m: &M, eps: &N, niter: uint) -> (M, V2) pub fn eigen_qr<N, V, VS, M>(m: &M, eps: &N, niter: uint) -> (M, V)
where N: Float, where N: Float,
V: Indexable<uint, N> + Norm<N>, VS: Indexable<uint, N> + Norm<N>,
V2: Zero, M: Indexable<(uint, uint), N> + SquareMat<N, V> + ColSlice<VS> + ApproxEq<N> + Clone {
M: Clone + Eye + ColSlice<V> + Transpose + Indexable<(uint, uint), N> + Mul<M, M>
+ Diag<V2> + ApproxEq<N> + Add<M, M> + Sub<M, M> {
let (rows, cols) = m.shape(); let (rows, cols) = m.shape();
assert!(rows == cols, "The matrix being decomposed must be square."); assert!(rows == cols, "The matrix being decomposed must be square.");
let mut eigenvectors: M = Eye::new_identity(rows); let mut eigenvectors: M = Eye::new_identity(rows);
let mut eigenvalues = m.clone(); let mut eigenvalues = m.clone();
let mut shifter: M = Eye::new_identity(rows); // let mut shifter: M = Eye::new_identity(rows);
let mut iter = 0u; let mut iter = 0u;
for _ in range(0, niter) { for _ in range(0, niter) {
@ -112,16 +110,9 @@ pub fn eigen_qr<N, V, V2, M>(m: &M, eps: &N, niter: uint) -> (M, V2)
} }
iter = iter + 1; iter = iter + 1;
// FIXME: This is a very naive implementation. let (q, r) = qr(&eigenvalues);;
let shift = unsafe { eigenvalues.unsafe_at((rows - 1, rows - 1)) };
for i in range(0, rows) { eigenvalues = r * q;
unsafe { shifter.unsafe_set((i, i), shift.clone()) }
}
let (q, r) = qr(&eigenvalues);// - shifter));
eigenvalues = r * q /*+ shifter*/;
eigenvectors = eigenvectors * q; eigenvectors = eigenvectors * q;
} }

View File

@ -27,7 +27,7 @@ macro_rules! iso_impl(
macro_rules! rotation_matrix_impl( macro_rules! rotation_matrix_impl(
($t: ident, $trot: ident, $tlv: ident, $tav: ident) => ( ($t: ident, $trot: ident, $tlv: ident, $tav: ident) => (
impl<N: Cast<f32> + FloatMath + Num + Clone> impl<N: Cast<f32> + FloatMath + Num + Clone>
RotationMatrix<$tlv<N>, $tav<N>, $trot<N>> for $t<N> { RotationMatrix<N, $tlv<N>, $tav<N>, $trot<N>> for $t<N> {
#[inline] #[inline]
fn to_rot_mat(&self) -> $trot<N> { fn to_rot_mat(&self) -> $trot<N> {
self.rotation.clone() self.rotation.clone()

View File

@ -122,8 +122,7 @@ macro_rules! dim_impl(
macro_rules! rotation_matrix_impl( macro_rules! rotation_matrix_impl(
($t: ident, $tlv: ident, $tav: ident) => ( ($t: ident, $tlv: ident, $tav: ident) => (
impl<N: Cast<f32> + FloatMath + Clone> impl<N: Cast<f32> + FloatMath> RotationMatrix<N, $tlv<N>, $tav<N>, $t<N>> for $t<N> {
RotationMatrix<$tlv<N>, $tav<N>, $t<N>> for $t<N> {
#[inline] #[inline]
fn to_rot_mat(&self) -> $t<N> { fn to_rot_mat(&self) -> $t<N> {
self.clone() self.clone()

View File

@ -141,7 +141,7 @@ impl<LV: Neg<LV>, AV, M: Rotation<AV> + Translation<LV>> RotationWithTranslation
/// Trait of transformation having a rotation extractable as a rotation matrix. This can typically /// Trait of transformation having a rotation extractable as a rotation matrix. This can typically
/// be implemented by quaternions to convert them to a rotation matrix. /// be implemented by quaternions to convert them to a rotation matrix.
pub trait RotationMatrix<LV, AV, M: Mat<LV, LV> + Rotation<AV>> : Rotation<AV> { pub trait RotationMatrix<N, LV, AV, M: Mat<N, LV, LV> + Rotation<AV>> : Rotation<AV> {
/// Gets the rotation matrix represented by `self`. /// Gets the rotation matrix represented by `self`.
fn to_rot_mat(&self) -> M; fn to_rot_mat(&self) -> M;
} }

View File

@ -1,16 +1,16 @@
//! Mathematical traits. //! Mathematical traits.
pub use self::geometry::{AbsoluteRotate, Cross, CrossMatrix, Dot, FromHomogeneous, Norm, Orig, pub use traits::geometry::{AbsoluteRotate, Cross, CrossMatrix, Dot, FromHomogeneous, Norm, Orig,
Rotate, Rotation, RotationMatrix, RotationWithTranslation, ToHomogeneous, Rotate, Rotation, RotationMatrix, RotationWithTranslation, ToHomogeneous,
Transform, Transformation, Translate, Translation, UniformSphereSample}; Transform, Transformation, Translate, Translation, UniformSphereSample};
pub use self::structure::{FloatVec, FloatPnt, Basis, Cast, Col, Dim, Indexable, Iterable, pub use traits::structure::{FloatVec, FloatPnt, Basis, Cast, Col, Dim, Indexable, Iterable,
IterableMut, Mat, Row, NumVec, NumPnt, PntAsVec, VecAsPnt, ColSlice, IterableMut, Mat, SquareMat, Row, NumVec, NumPnt, PntAsVec, VecAsPnt,
RowSlice, Diag, Eye, Shape}; ColSlice, RowSlice, Diag, Eye, Shape};
pub use self::operations::{Absolute, ApproxEq, Axpy, Cov, Det, Inv, LMul, Mean, Outer, POrd, pub use traits::operations::{Absolute, ApproxEq, Axpy, Cov, Det, Inv, LMul, Mean, Outer, POrd,
RMul, ScalarAdd, ScalarSub, ScalarMul, ScalarDiv, Transpose}; RMul, ScalarAdd, ScalarSub, ScalarMul, ScalarDiv, Transpose};
pub use self::operations::{POrdering, PartialLess, PartialEqual, PartialGreater, NotComparable}; pub use traits::operations::{POrdering, PartialLess, PartialEqual, PartialGreater, NotComparable};
pub mod geometry; pub mod geometry;
pub mod structure; pub mod structure;

View File

@ -2,7 +2,7 @@
use std::num::Zero; use std::num::Zero;
use std::slice::{Items, MutItems}; use std::slice::{Items, MutItems};
use traits::operations::{RMul, LMul, Axpy}; use traits::operations::{RMul, LMul, Axpy, Transpose};
use traits::geometry::{Dot, Norm, Orig}; use traits::geometry::{Dot, Norm, Orig};
/// Traits of objects which can be created from an object of type `T`. /// Traits of objects which can be created from an object of type `T`.
@ -14,9 +14,19 @@ pub trait Cast<T> {
/// Trait of matrices. /// Trait of matrices.
/// ///
/// A matrix has rows and columns and are able to multiply them. /// A matrix has rows and columns and are able to multiply them.
pub trait Mat<R, C> : Row<R> + Col<C> + RMul<R> + LMul<C> { } pub trait Mat<N, R, C>: Row<R> + Col<C> + RMul<R> + LMul<C> + Index<(uint, uint), N> { }
impl<M: Row<R> + Col<C> + RMul<R> + LMul<C>, R, C> Mat<R, C> for M { impl<N, M, R, C> Mat<N, R, C> for M
where M: Row<R> + Col<C> + RMul<R> + LMul<C> + Index<(uint, uint), N> {
}
/// Trait implemented by square matrices.
pub trait SquareMat<N, V>: Mat<N, V, V> + Mul<Self, Self> + Eye + Transpose + Add<Self, Self> +
Sub<Self, Self> + Diag<V> {
}
impl<N, V, M> SquareMat<N, V> for M
where M: Mat<N, V, V> + Mul<M, M> + Eye + Transpose + Add<M, M> + Sub<M, M> + Diag<V> {
} }
/// Trait for constructing the identity matrix /// Trait for constructing the identity matrix

View File

@ -6,7 +6,7 @@ use std::num::{Float, abs};
use std::rand::random; use std::rand::random;
use std::cmp::{min, max}; use std::cmp::{min, max};
use na::{Vec1, Vec3, Mat1, Mat2, Mat3, Mat4, Mat5, Mat6, Rot3, Persp3, PerspMat3, Ortho3, OrthoMat3, use na::{Vec1, Vec3, Mat1, Mat2, Mat3, Mat4, Mat5, Mat6, Rot3, Persp3, PerspMat3, Ortho3, OrthoMat3,
DMat, DVec, Indexable, Row, Col}; DMat, DVec, Row, Col};
macro_rules! test_inv_mat_impl( macro_rules! test_inv_mat_impl(
($t: ty) => ( ($t: ty) => (
@ -141,7 +141,7 @@ fn test_rotation2() {
fn test_index_mat2() { fn test_index_mat2() {
let mat: Mat2<f64> = random(); let mat: Mat2<f64> = random();
assert!(mat.at((0, 1)) == na::transpose(&mat).at((1, 0))); assert!(mat[(0, 1)] == na::transpose(&mat)[(1, 0)]);
} }
#[test] #[test]