Merge pull request #9 from vbarrielle/genericQR
Generic QR factorization
This commit is contained in:
commit
cfa18252bc
|
@ -50,6 +50,7 @@ and keeps an optimized set of tools for computational graphics and physics. Thos
|
||||||
* Dynamically sized vector: `DVec`.
|
* Dynamically sized vector: `DVec`.
|
||||||
* Dynamically sized (square or rectangular) matrix: `DMat`.
|
* Dynamically sized (square or rectangular) matrix: `DMat`.
|
||||||
* A few methods for data analysis: `Cov`, `Mean`.
|
* A few methods for data analysis: `Cov`, `Mean`.
|
||||||
|
* Some matrix factorization algorithms: QR decomposition, ...
|
||||||
* Almost one trait per functionality: useful for generic programming.
|
* Almost one trait per functionality: useful for generic programming.
|
||||||
* Operator overloading using the double trait dispatch
|
* Operator overloading using the double trait dispatch
|
||||||
[trick](http://smallcultfollowing.com/babysteps/blog/2012/10/04/refining-traits-slash-impls/).
|
[trick](http://smallcultfollowing.com/babysteps/blog/2012/10/04/refining-traits-slash-impls/).
|
||||||
|
|
|
@ -1,54 +1,65 @@
|
||||||
use std::num::{Zero, Float};
|
use std::num::{Zero, Float};
|
||||||
use na::DVec;
|
|
||||||
use na::DMat;
|
|
||||||
use traits::operations::Transpose;
|
use traits::operations::Transpose;
|
||||||
use traits::structure::ColSlice;
|
use traits::structure::{ColSlice, Eye, Indexable};
|
||||||
use traits::geometry::Norm;
|
use traits::geometry::Norm;
|
||||||
use std::cmp::min;
|
use std::cmp::min;
|
||||||
|
|
||||||
|
/// Get the householder matrix corresponding to a reflexion to the hyperplane
|
||||||
|
/// defined by `vec̀ . It can be a reflexion contained in a subspace.
|
||||||
|
///
|
||||||
|
/// # Arguments
|
||||||
|
/// * `dim` - the dimension of the space the resulting matrix operates in
|
||||||
|
/// * `start` - the starting dimension of the subspace of the reflexion
|
||||||
|
/// * `vec` - the vector defining the reflection.
|
||||||
|
pub fn householder_matrix<N: Float,
|
||||||
|
M: Eye + Indexable<(uint, uint), N>,
|
||||||
|
V: Indexable<uint, N>>
|
||||||
|
(dim: uint, start: uint, vec: V) -> M {
|
||||||
|
let mut qk : M = Eye::new_identity(dim);
|
||||||
|
let stop = start + vec.shape();
|
||||||
|
assert!(stop <= dim);
|
||||||
|
for j in range(start, stop) {
|
||||||
|
for i in range(start, stop) {
|
||||||
|
unsafe {
|
||||||
|
let vv = vec.unsafe_at(i) * vec.unsafe_at(j);
|
||||||
|
let qkij = qk.unsafe_at((i, j));
|
||||||
|
qk.unsafe_set((i, j), qkij - vv - vv);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
qk
|
||||||
|
}
|
||||||
|
|
||||||
/// QR decomposition using Householder reflections
|
/// QR decomposition using Householder reflections
|
||||||
/// # Arguments
|
/// # Arguments
|
||||||
/// * `m` - matrix to decompose
|
/// * `m` - matrix to decompose
|
||||||
pub fn decomp_qr<N: Clone + Float>(m: &DMat<N>) -> (DMat<N>, DMat<N>) {
|
pub fn decomp_qr<N: Float,
|
||||||
let rows = m.nrows();
|
V: Indexable<uint, N> + Norm<N>,
|
||||||
let cols = m.ncols();
|
M: Clone + Eye + ColSlice<V> + Transpose
|
||||||
|
+ Indexable<(uint, uint), N> + Mul<M, M>>
|
||||||
|
(m: &M) -> (M, M) {
|
||||||
|
let (rows, cols) = m.shape();
|
||||||
assert!(rows >= cols);
|
assert!(rows >= cols);
|
||||||
let mut q : DMat<N> = DMat::new_identity(rows);
|
let mut q : M = Eye::new_identity(rows);
|
||||||
let mut r = m.clone();
|
let mut r = m.clone();
|
||||||
|
|
||||||
let subtract_reflection = |vec: DVec<N>| -> DMat<N> {
|
|
||||||
// FIXME: we don't handle the complex case here
|
|
||||||
let mut qk : DMat<N> = DMat::new_identity(rows);
|
|
||||||
let start = rows - vec.at.len();
|
|
||||||
for j in range(start, rows) {
|
|
||||||
for i in range(start, rows) {
|
|
||||||
unsafe {
|
|
||||||
let vv = vec.at_fast(i - start) * vec.at_fast(j - start);
|
|
||||||
let qkij = qk.at_fast(i, j);
|
|
||||||
qk.set_fast(i, j, qkij - vv - vv);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
qk
|
|
||||||
};
|
|
||||||
|
|
||||||
let iterations = min(rows - 1, cols);
|
let iterations = min(rows - 1, cols);
|
||||||
|
|
||||||
for ite in range(0u, iterations) {
|
for ite in range(0u, iterations) {
|
||||||
let mut v = r.col_slice(ite, ite, rows);
|
let mut v = r.col_slice(ite, ite, rows);
|
||||||
let alpha =
|
let alpha =
|
||||||
if unsafe { v.at_fast(ite) } >= Zero::zero() {
|
if unsafe { v.unsafe_at(ite) } >= Zero::zero() {
|
||||||
-Norm::norm(&v)
|
-Norm::norm(&v)
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
Norm::norm(&v)
|
Norm::norm(&v)
|
||||||
};
|
};
|
||||||
unsafe {
|
unsafe {
|
||||||
let x = v.at_fast(0);
|
let x = v.unsafe_at(0);
|
||||||
v.set_fast(0, x - alpha);
|
v.unsafe_set(0, x - alpha);
|
||||||
}
|
}
|
||||||
let _ = v.normalize();
|
let _ = v.normalize();
|
||||||
let qk = subtract_reflection(v);
|
let qk: M = householder_matrix(rows, 0, v);
|
||||||
r = qk * r;
|
r = qk * r;
|
||||||
q = q * Transpose::transpose_cpy(&qk);
|
q = q * Transpose::transpose_cpy(&qk);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
|
|
||||||
pub use self::decompositions::decomp_qr;
|
pub use self::decompositions::{decomp_qr, householder_matrix};
|
||||||
|
|
||||||
mod decompositions;
|
mod decompositions;
|
||||||
|
|
14
src/na.rs
14
src/na.rs
|
@ -1,6 +1,6 @@
|
||||||
//! **nalgebra** prelude.
|
//! **nalgebra** prelude.
|
||||||
|
|
||||||
use std::num::{Zero, One};
|
use std::num::{Zero, One, FloatMath};
|
||||||
use std::cmp;
|
use std::cmp;
|
||||||
pub use traits::{PartialLess, PartialEqual, PartialGreater, NotComparable};
|
pub use traits::{PartialLess, PartialEqual, PartialGreater, NotComparable};
|
||||||
pub use traits::{
|
pub use traits::{
|
||||||
|
@ -40,7 +40,8 @@ pub use traits::{
|
||||||
UniformSphereSample,
|
UniformSphereSample,
|
||||||
AnyVec,
|
AnyVec,
|
||||||
VecExt,
|
VecExt,
|
||||||
ColSlice, RowSlice
|
ColSlice, RowSlice,
|
||||||
|
Eye
|
||||||
};
|
};
|
||||||
|
|
||||||
pub use structs::{
|
pub use structs::{
|
||||||
|
@ -54,7 +55,8 @@ pub use structs::{
|
||||||
};
|
};
|
||||||
|
|
||||||
pub use linalg::{
|
pub use linalg::{
|
||||||
decomp_qr
|
decomp_qr,
|
||||||
|
householder_matrix
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Traits to work around the language limitations related to operator overloading.
|
/// Traits to work around the language limitations related to operator overloading.
|
||||||
|
@ -215,7 +217,7 @@ pub fn one<T: One>() -> T {
|
||||||
*/
|
*/
|
||||||
/// Computes a projection matrix given the frustrum near plane width, height, the field of
|
/// Computes a projection matrix given the frustrum near plane width, height, the field of
|
||||||
/// view, and the distance to the clipping planes (`znear` and `zfar`).
|
/// view, and the distance to the clipping planes (`znear` and `zfar`).
|
||||||
pub fn perspective3d<N: Float + Cast<f32> + Zero + One>(width: N, height: N, fov: N, znear: N, zfar: N) -> Mat4<N> {
|
pub fn perspective3d<N: FloatMath + Cast<f32> + Zero + One>(width: N, height: N, fov: N, znear: N, zfar: N) -> Mat4<N> {
|
||||||
let aspect = width / height;
|
let aspect = width / height;
|
||||||
|
|
||||||
let _1: N = one();
|
let _1: N = one();
|
||||||
|
@ -720,6 +722,10 @@ pub fn mean<N, M: Mean<N>>(observations: &M) -> N {
|
||||||
//
|
//
|
||||||
//
|
//
|
||||||
|
|
||||||
|
/// Construct the identity matrix for a given dimension
|
||||||
|
#[inline(always)]
|
||||||
|
pub fn new_identity<M: Eye>(dim: uint) -> M { Eye::new_identity(dim) }
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Basis
|
* Basis
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -9,7 +9,7 @@ use traits::operations::ApproxEq;
|
||||||
use std::mem;
|
use std::mem;
|
||||||
use structs::dvec::{DVec, DVecMulRhs};
|
use structs::dvec::{DVec, DVecMulRhs};
|
||||||
use traits::operations::{Inv, Transpose, Mean, Cov};
|
use traits::operations::{Inv, Transpose, Mean, Cov};
|
||||||
use traits::structure::{Cast, ColSlice, RowSlice};
|
use traits::structure::{Cast, ColSlice, RowSlice, Eye, Indexable};
|
||||||
use std::fmt::{Show, Formatter, Result};
|
use std::fmt::{Show, Formatter, Result};
|
||||||
|
|
||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
|
@ -181,19 +181,19 @@ impl<N> DMat<N> {
|
||||||
|
|
||||||
// FIXME: add a function to modify the dimension (to avoid useless allocations)?
|
// FIXME: add a function to modify the dimension (to avoid useless allocations)?
|
||||||
|
|
||||||
impl<N: One + Zero + Clone> DMat<N> {
|
impl<N: One + Zero + Clone> Eye for DMat<N> {
|
||||||
/// Builds an identity matrix.
|
/// Builds an identity matrix.
|
||||||
///
|
///
|
||||||
/// # Arguments
|
/// # Arguments
|
||||||
/// * `dim` - The dimension of the matrix. A `dim`-dimensional matrix contains `dim * dim`
|
/// * `dim` - The dimension of the matrix. A `dim`-dimensional matrix contains `dim * dim`
|
||||||
/// components.
|
/// components.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn new_identity(dim: uint) -> DMat<N> {
|
fn new_identity(dim: uint) -> DMat<N> {
|
||||||
let mut res = DMat::new_zeros(dim, dim);
|
let mut res = DMat::new_zeros(dim, dim);
|
||||||
|
|
||||||
for i in range(0u, dim) {
|
for i in range(0u, dim) {
|
||||||
let _1: N = One::one();
|
let _1: N = One::one();
|
||||||
res.set(i, i, _1);
|
res.set((i, i), _1);
|
||||||
}
|
}
|
||||||
|
|
||||||
res
|
res
|
||||||
|
@ -206,13 +206,16 @@ impl<N: Clone> DMat<N> {
|
||||||
i + j * self.nrows
|
i + j * self.nrows
|
||||||
}
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<N: Clone> Indexable<(uint, uint), N> for DMat<N> {
|
||||||
/// Changes the value of a component of the matrix.
|
/// Changes the value of a component of the matrix.
|
||||||
///
|
///
|
||||||
/// # Arguments
|
/// # Arguments
|
||||||
/// * `row` - 0-based index of the line to be changed
|
/// * `rowcol` - 0-based tuple (row, col) to be changed
|
||||||
/// * `col` - 0-based index of the column to be changed
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn set(&mut self, row: uint, col: uint, val: N) {
|
fn set(&mut self, rowcol: (uint, uint), val: N) {
|
||||||
|
let (row, col) = rowcol;
|
||||||
assert!(row < self.nrows);
|
assert!(row < self.nrows);
|
||||||
assert!(col < self.ncols);
|
assert!(col < self.ncols);
|
||||||
|
|
||||||
|
@ -222,7 +225,8 @@ impl<N: Clone> DMat<N> {
|
||||||
|
|
||||||
/// Just like `set` without bounds checking.
|
/// Just like `set` without bounds checking.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub unsafe fn set_fast(&mut self, row: uint, col: uint, val: N) {
|
unsafe fn unsafe_set(&mut self, rowcol: (uint, uint), val: N) {
|
||||||
|
let (row, col) = rowcol;
|
||||||
let offset = self.offset(row, col);
|
let offset = self.offset(row, col);
|
||||||
*self.mij.as_mut_slice().unsafe_mut_ref(offset) = val
|
*self.mij.as_mut_slice().unsafe_mut_ref(offset) = val
|
||||||
}
|
}
|
||||||
|
@ -230,20 +234,38 @@ impl<N: Clone> DMat<N> {
|
||||||
/// Reads the value of a component of the matrix.
|
/// Reads the value of a component of the matrix.
|
||||||
///
|
///
|
||||||
/// # Arguments
|
/// # Arguments
|
||||||
/// * `row` - 0-based index of the line to be read
|
/// * `rowcol` - 0-based tuple (row, col) to be read
|
||||||
/// * `col` - 0-based index of the column to be read
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn at(&self, row: uint, col: uint) -> N {
|
fn at(&self, rowcol: (uint, uint)) -> N {
|
||||||
|
let (row, col) = rowcol;
|
||||||
assert!(row < self.nrows);
|
assert!(row < self.nrows);
|
||||||
assert!(col < self.ncols);
|
assert!(col < self.ncols);
|
||||||
unsafe { self.at_fast(row, col) }
|
unsafe { self.unsafe_at((row, col)) }
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Just like `at` without bounds checking.
|
/// Just like `at` without bounds checking.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub unsafe fn at_fast(&self, row: uint, col: uint) -> N {
|
unsafe fn unsafe_at(&self, rowcol: (uint, uint)) -> N {
|
||||||
|
let (row, col) = rowcol;
|
||||||
(*self.mij.as_slice().unsafe_ref(self.offset(row, col))).clone()
|
(*self.mij.as_slice().unsafe_ref(self.offset(row, col))).clone()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn swap(&mut self, rowcol1: (uint, uint), rowcol2: (uint, uint)) {
|
||||||
|
let (row1, col1) = rowcol1;
|
||||||
|
let (row2, col2) = rowcol2;
|
||||||
|
let offset1 = self.offset(row1, col1);
|
||||||
|
let offset2 = self.offset(row2, col2);
|
||||||
|
let count = self.mij.len();
|
||||||
|
assert!(offset1 < count);
|
||||||
|
assert!(offset2 < count);
|
||||||
|
self.mij.as_mut_slice().swap(offset1, offset2);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn shape(&self) -> (uint, uint) {
|
||||||
|
(self.nrows, self.ncols)
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<N: Clone + Mul<N, N> + Add<N, N> + Zero> DMatMulRhs<N, DMat<N>> for DMat<N> {
|
impl<N: Clone + Mul<N, N> + Add<N, N> + Zero> DMatMulRhs<N, DMat<N>> for DMat<N> {
|
||||||
|
@ -258,10 +280,11 @@ impl<N: Clone + Mul<N, N> + Add<N, N> + Zero> DMatMulRhs<N, DMat<N>> for DMat<N>
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
for k in range(0u, left.ncols) {
|
for k in range(0u, left.ncols) {
|
||||||
acc = acc + left.at_fast(i, k) * right.at_fast(k, j);
|
acc = acc
|
||||||
|
+ left.unsafe_at((i, k)) * right.unsafe_at((k, j));
|
||||||
}
|
}
|
||||||
|
|
||||||
res.set_fast(i, j, acc);
|
res.unsafe_set((i, j), acc);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -282,7 +305,7 @@ DMatMulRhs<N, DVec<N>> for DVec<N> {
|
||||||
|
|
||||||
for j in range(0u, left.ncols) {
|
for j in range(0u, left.ncols) {
|
||||||
unsafe {
|
unsafe {
|
||||||
acc = acc + left.at_fast(i, j) * right.at_fast(j);
|
acc = acc + left.unsafe_at((i, j)) * right.unsafe_at(j);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -306,7 +329,7 @@ DVecMulRhs<N, DVec<N>> for DMat<N> {
|
||||||
|
|
||||||
for j in range(0u, right.nrows) {
|
for j in range(0u, right.nrows) {
|
||||||
unsafe {
|
unsafe {
|
||||||
acc = acc + left.at_fast(j) * right.at_fast(j, i);
|
acc = acc + left.unsafe_at(j) * right.unsafe_at((j, i));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -335,7 +358,7 @@ Inv for DMat<N> {
|
||||||
assert!(self.nrows == self.ncols);
|
assert!(self.nrows == self.ncols);
|
||||||
|
|
||||||
let dim = self.nrows;
|
let dim = self.nrows;
|
||||||
let mut res: DMat<N> = DMat::new_identity(dim);
|
let mut res: DMat<N> = Eye::new_identity(dim);
|
||||||
let _0T: N = Zero::zero();
|
let _0T: N = Zero::zero();
|
||||||
|
|
||||||
// inversion using Gauss-Jordan elimination
|
// inversion using Gauss-Jordan elimination
|
||||||
|
@ -347,7 +370,7 @@ Inv for DMat<N> {
|
||||||
let mut n0 = k; // index of a non-zero entry
|
let mut n0 = k; // index of a non-zero entry
|
||||||
|
|
||||||
while n0 != dim {
|
while n0 != dim {
|
||||||
if unsafe { self.at_fast(n0, k) } != _0T {
|
if unsafe { self.unsafe_at((n0, k)) } != _0T {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -370,30 +393,30 @@ Inv for DMat<N> {
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
let pivot = self.at_fast(k, k);
|
let pivot = self.unsafe_at((k, k));
|
||||||
|
|
||||||
for j in range(k, dim) {
|
for j in range(k, dim) {
|
||||||
let selfval = self.at_fast(k, j) / pivot;
|
let selfval = self.unsafe_at((k, j)) / pivot;
|
||||||
self.set_fast(k, j, selfval);
|
self.unsafe_set((k, j), selfval);
|
||||||
}
|
}
|
||||||
|
|
||||||
for j in range(0u, dim) {
|
for j in range(0u, dim) {
|
||||||
let resval = res.at_fast(k, j) / pivot;
|
let resval = res.unsafe_at((k, j)) / pivot;
|
||||||
res.set_fast(k, j, resval);
|
res.unsafe_set((k, j), resval);
|
||||||
}
|
}
|
||||||
|
|
||||||
for l in range(0u, dim) {
|
for l in range(0u, dim) {
|
||||||
if l != k {
|
if l != k {
|
||||||
let normalizer = self.at_fast(l, k);
|
let normalizer = self.unsafe_at((l, k));
|
||||||
|
|
||||||
for j in range(k, dim) {
|
for j in range(k, dim) {
|
||||||
let selfval = self.at_fast(l, j) - self.at_fast(k, j) * normalizer;
|
let selfval = self.unsafe_at((l, j)) - self.unsafe_at((k, j)) * normalizer;
|
||||||
self.set_fast(l, j, selfval);
|
self.unsafe_set((l, j), selfval);
|
||||||
}
|
}
|
||||||
|
|
||||||
for j in range(0u, dim) {
|
for j in range(0u, dim) {
|
||||||
let resval = res.at_fast(l, j) - res.at_fast(k, j) * normalizer;
|
let resval = res.unsafe_at((l, j)) - res.unsafe_at((k, j)) * normalizer;
|
||||||
res.set_fast(l, j, resval);
|
res.unsafe_set((l, j), resval);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -422,7 +445,7 @@ impl<N: Clone> Transpose for DMat<N> {
|
||||||
for i in range(0u, m.nrows) {
|
for i in range(0u, m.nrows) {
|
||||||
for j in range(0u, m.ncols) {
|
for j in range(0u, m.ncols) {
|
||||||
unsafe {
|
unsafe {
|
||||||
res.set_fast(j, i, m.at_fast(i, j))
|
res.unsafe_set((j, i), m.unsafe_at((i, j)))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -460,8 +483,8 @@ impl<N: Num + Cast<f32> + Clone> Mean<DVec<N>> for DMat<N> {
|
||||||
for i in range(0u, m.nrows) {
|
for i in range(0u, m.nrows) {
|
||||||
for j in range(0u, m.ncols) {
|
for j in range(0u, m.ncols) {
|
||||||
unsafe {
|
unsafe {
|
||||||
let acc = res.at_fast(j) + m.at_fast(i, j) * normalizer;
|
let acc = res.unsafe_at(j) + m.unsafe_at((i, j)) * normalizer;
|
||||||
res.set_fast(j, acc);
|
res.unsafe_set(j, acc);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -482,7 +505,7 @@ impl<N: Clone + Num + Cast<f32> + DMatDivRhs<N, DMat<N>> + ToStr > Cov<DMat<N>>
|
||||||
for i in range(0u, m.nrows) {
|
for i in range(0u, m.nrows) {
|
||||||
for j in range(0u, m.ncols) {
|
for j in range(0u, m.ncols) {
|
||||||
unsafe {
|
unsafe {
|
||||||
centered.set_fast(i, j, m.at_fast(i, j) - mean.at_fast(j));
|
centered.unsafe_set((i, j), m.unsafe_at((i, j)) - mean.unsafe_at(j));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -520,7 +543,7 @@ impl<N: Clone> RowSlice<DVec<N>> for DMat<N> {
|
||||||
let mut slice_idx = 0u;
|
let mut slice_idx = 0u;
|
||||||
for col_id in range(col_start, col_end) {
|
for col_id in range(col_start, col_end) {
|
||||||
unsafe {
|
unsafe {
|
||||||
slice.set_fast(slice_idx, self.at_fast(row_id, col_id));
|
slice.unsafe_set(slice_idx, self.unsafe_at((row_id, col_id)));
|
||||||
}
|
}
|
||||||
slice_idx += 1;
|
slice_idx += 1;
|
||||||
}
|
}
|
||||||
|
@ -553,11 +576,11 @@ impl<N: Show + Clone> Show for DMat<N> {
|
||||||
fn fmt(&self, form:&mut Formatter) -> Result {
|
fn fmt(&self, form:&mut Formatter) -> Result {
|
||||||
for i in range(0u, self.nrows()) {
|
for i in range(0u, self.nrows()) {
|
||||||
for j in range(0u, self.ncols()) {
|
for j in range(0u, self.ncols()) {
|
||||||
let _ = write!(form.buf, "{} ", self.at(i, j));
|
let _ = write!(form, "{} ", self.at((i, j)));
|
||||||
}
|
}
|
||||||
let _ = write!(form.buf, "\n");
|
let _ = write!(form, "\n");
|
||||||
}
|
}
|
||||||
write!(form.buf, "\n")
|
write!(form, "\n")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -9,7 +9,7 @@ use std::slice::{Items, MutItems};
|
||||||
use traits::operations::ApproxEq;
|
use traits::operations::ApproxEq;
|
||||||
use std::iter::FromIterator;
|
use std::iter::FromIterator;
|
||||||
use traits::geometry::{Dot, Norm};
|
use traits::geometry::{Dot, Norm};
|
||||||
use traits::structure::{Iterable, IterableMut};
|
use traits::structure::{Iterable, IterableMut, Indexable};
|
||||||
|
|
||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
mod metal;
|
mod metal;
|
||||||
|
@ -48,11 +48,42 @@ impl<N: Zero + Clone> DVec<N> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<N: Clone> DVec<N> {
|
impl<N: Clone> Indexable<uint, N> for DVec<N> {
|
||||||
/// Indexing without bounds checking.
|
|
||||||
pub unsafe fn at_fast(&self, i: uint) -> N {
|
fn at(&self, i: uint) -> N {
|
||||||
|
assert!(i < self.at.len());
|
||||||
|
unsafe {
|
||||||
|
self.unsafe_at(i)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn set(&mut self, i: uint, val: N) {
|
||||||
|
assert!(i < self.at.len());
|
||||||
|
unsafe {
|
||||||
|
self.unsafe_set(i, val);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn swap(&mut self, i: uint, j: uint) {
|
||||||
|
assert!(i < self.at.len());
|
||||||
|
assert!(j < self.at.len());
|
||||||
|
self.at.as_mut_slice().swap(i, j);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn shape(&self) -> uint {
|
||||||
|
self.at.len()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
unsafe fn unsafe_at(&self, i: uint) -> N {
|
||||||
(*self.at.as_slice().unsafe_ref(i)).clone()
|
(*self.at.as_slice().unsafe_ref(i)).clone()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
unsafe fn unsafe_set(&mut self, i: uint, val: N) {
|
||||||
|
*self.at.as_mut_slice().unsafe_mut_ref(i) = val
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<N: One + Clone> DVec<N> {
|
impl<N: One + Clone> DVec<N> {
|
||||||
|
@ -86,11 +117,6 @@ impl<N> DVec<N> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
|
||||||
pub unsafe fn set_fast(&mut self, i: uint, val: N) {
|
|
||||||
*self.at.as_mut_slice().unsafe_mut_ref(i) = val
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Gets a reference to of this vector data.
|
/// Gets a reference to of this vector data.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn as_vec<'r>(&'r self) -> &'r [N] {
|
pub fn as_vec<'r>(&'r self) -> &'r [N] {
|
||||||
|
@ -172,7 +198,7 @@ impl<N> FromIterator<N> for DVec<N> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<N: Clone + Num + Float + ApproxEq<N> + DVecMulRhs<N, DVec<N>>> DVec<N> {
|
impl<N: Clone + Float + ApproxEq<N> + DVecMulRhs<N, DVec<N>>> DVec<N> {
|
||||||
/// Computes the canonical basis for the given dimension. A canonical basis is a set of
|
/// Computes the canonical basis for the given dimension. A canonical basis is a set of
|
||||||
/// vectors, mutually orthogonal, with all its component equal to 0.0 except one which is equal
|
/// vectors, mutually orthogonal, with all its component equal to 0.0 except one which is equal
|
||||||
/// to 1.0.
|
/// to 1.0.
|
||||||
|
@ -261,7 +287,7 @@ impl<N: Num + Clone> Dot<N> for DVec<N> {
|
||||||
let mut res: N = Zero::zero();
|
let mut res: N = Zero::zero();
|
||||||
|
|
||||||
for i in range(0u, a.at.len()) {
|
for i in range(0u, a.at.len()) {
|
||||||
res = res + unsafe { a.at_fast(i) * b.at_fast(i) };
|
res = res + unsafe { a.unsafe_at(i) * b.unsafe_at(i) };
|
||||||
}
|
}
|
||||||
|
|
||||||
res
|
res
|
||||||
|
@ -272,14 +298,14 @@ impl<N: Num + Clone> Dot<N> for DVec<N> {
|
||||||
let mut res: N = Zero::zero();
|
let mut res: N = Zero::zero();
|
||||||
|
|
||||||
for i in range(0u, a.at.len()) {
|
for i in range(0u, a.at.len()) {
|
||||||
res = res + unsafe { (a.at_fast(i) - b.at_fast(i)) * c.at_fast(i) };
|
res = res + unsafe { (a.unsafe_at(i) - b.unsafe_at(i)) * c.unsafe_at(i) };
|
||||||
}
|
}
|
||||||
|
|
||||||
res
|
res
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<N: Num + Float + Clone> Norm<N> for DVec<N> {
|
impl<N: Float + Clone> Norm<N> for DVec<N> {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn sqnorm(v: &DVec<N>) -> N {
|
fn sqnorm(v: &DVec<N>) -> N {
|
||||||
Dot::dot(v, v)
|
Dot::dot(v, v)
|
||||||
|
|
|
@ -51,7 +51,7 @@ pub struct Iso4<N> {
|
||||||
pub translation: Vec4<N>
|
pub translation: Vec4<N>
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<N: Clone + Num + Float> Iso3<N> {
|
impl<N: Clone + Float> Iso3<N> {
|
||||||
/// Reorient and translate this transformation such that its local `x` axis points to a given
|
/// Reorient and translate this transformation such that its local `x` axis points to a given
|
||||||
/// direction. Note that the usually known `look_at` function does the same thing but with the
|
/// direction. Note that the usually known `look_at` function does the same thing but with the
|
||||||
/// `z` axis. See `look_at_z` for that.
|
/// `z` axis. See `look_at_z` for that.
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
macro_rules! iso_impl(
|
macro_rules! iso_impl(
|
||||||
($t: ident, $submat: ident, $subvec: ident, $subrotvec: ident) => (
|
($t: ident, $submat: ident, $subvec: ident, $subrotvec: ident) => (
|
||||||
impl<N: Clone + Float + Float + Num> $t<N> {
|
impl<N: Clone + FloatMath + Num> $t<N> {
|
||||||
/// Creates a new isometry from a rotation matrix and a vector.
|
/// Creates a new isometry from a rotation matrix and a vector.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn new(translation: $subvec<N>, rotation: $subrotvec<N>) -> $t<N> {
|
pub fn new(translation: $subvec<N>, rotation: $subrotvec<N>) -> $t<N> {
|
||||||
|
@ -26,7 +26,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> + Float + Float + Num + Clone>
|
impl<N: Cast<f32> + FloatMath + Num + Clone>
|
||||||
RotationMatrix<$tlv<N>, $tav<N>, $trot<N>> for $t<N> {
|
RotationMatrix<$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> {
|
||||||
|
@ -50,7 +50,7 @@ macro_rules! dim_impl(
|
||||||
|
|
||||||
macro_rules! one_impl(
|
macro_rules! one_impl(
|
||||||
($t: ident) => (
|
($t: ident) => (
|
||||||
impl<N: Float + Float + Num + Clone> One for $t<N> {
|
impl<N: FloatMath + Clone> One for $t<N> {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn one() -> $t<N> {
|
fn one() -> $t<N> {
|
||||||
$t::new_with_rotmat(Zero::zero(), One::one())
|
$t::new_with_rotmat(Zero::zero(), One::one())
|
||||||
|
@ -61,7 +61,7 @@ macro_rules! one_impl(
|
||||||
|
|
||||||
macro_rules! iso_mul_iso_impl(
|
macro_rules! iso_mul_iso_impl(
|
||||||
($t: ident, $tmul: ident) => (
|
($t: ident, $tmul: ident) => (
|
||||||
impl<N: Num + Float + Float + Clone> $tmul<N, $t<N>> for $t<N> {
|
impl<N: FloatMath + Clone> $tmul<N, $t<N>> for $t<N> {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn binop(left: &$t<N>, right: &$t<N>) -> $t<N> {
|
fn binop(left: &$t<N>, right: &$t<N>) -> $t<N> {
|
||||||
$t::new_with_rotmat(
|
$t::new_with_rotmat(
|
||||||
|
@ -96,7 +96,7 @@ macro_rules! vec_mul_iso_impl(
|
||||||
|
|
||||||
macro_rules! translation_impl(
|
macro_rules! translation_impl(
|
||||||
($t: ident, $tv: ident) => (
|
($t: ident, $tv: ident) => (
|
||||||
impl<N: Float + Num + Float + Clone> Translation<$tv<N>> for $t<N> {
|
impl<N: FloatMath + Clone> Translation<$tv<N>> for $t<N> {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn translation(&self) -> $tv<N> {
|
fn translation(&self) -> $tv<N> {
|
||||||
self.translation.clone()
|
self.translation.clone()
|
||||||
|
@ -153,7 +153,7 @@ macro_rules! translate_impl(
|
||||||
|
|
||||||
macro_rules! rotation_impl(
|
macro_rules! rotation_impl(
|
||||||
($t: ident, $trot: ident, $tav: ident) => (
|
($t: ident, $trot: ident, $tav: ident) => (
|
||||||
impl<N: Cast<f32> + Num + Float + Float + Clone> Rotation<$tav<N>> for $t<N> {
|
impl<N: Cast<f32> + FloatMath + Clone> Rotation<$tav<N>> for $t<N> {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn rotation(&self) -> $tav<N> {
|
fn rotation(&self) -> $tav<N> {
|
||||||
self.rotation.rotation()
|
self.rotation.rotation()
|
||||||
|
@ -220,7 +220,7 @@ macro_rules! rotate_impl(
|
||||||
|
|
||||||
macro_rules! transformation_impl(
|
macro_rules! transformation_impl(
|
||||||
($t: ident) => (
|
($t: ident) => (
|
||||||
impl<N: Num + Float + Float + Clone> Transformation<$t<N>> for $t<N> {
|
impl<N: FloatMath + Clone> Transformation<$t<N>> for $t<N> {
|
||||||
fn transformation(&self) -> $t<N> {
|
fn transformation(&self) -> $t<N> {
|
||||||
self.clone()
|
self.clone()
|
||||||
}
|
}
|
||||||
|
@ -336,7 +336,7 @@ macro_rules! approx_eq_impl(
|
||||||
|
|
||||||
macro_rules! rand_impl(
|
macro_rules! rand_impl(
|
||||||
($t: ident) => (
|
($t: ident) => (
|
||||||
impl<N: Rand + Clone + Float + Float + Num> Rand for $t<N> {
|
impl<N: Rand + Clone + FloatMath> Rand for $t<N> {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn rand<R: Rng>(rng: &mut R) -> $t<N> {
|
fn rand<R: Rng>(rng: &mut R) -> $t<N> {
|
||||||
$t::new(rng.gen(), rng.gen())
|
$t::new(rng.gen(), rng.gen())
|
||||||
|
|
|
@ -8,8 +8,10 @@ use traits::operations::ApproxEq;
|
||||||
use std::slice::{Items, MutItems};
|
use std::slice::{Items, MutItems};
|
||||||
use structs::vec::{Vec1, Vec2, Vec3, Vec4, Vec5, Vec6, Vec1MulRhs, Vec4MulRhs,
|
use structs::vec::{Vec1, Vec2, Vec3, Vec4, Vec5, Vec6, Vec1MulRhs, Vec4MulRhs,
|
||||||
Vec5MulRhs, Vec6MulRhs};
|
Vec5MulRhs, Vec6MulRhs};
|
||||||
|
use structs::dvec::DVec;
|
||||||
|
|
||||||
use traits::structure::{Cast, Row, Col, Iterable, IterableMut, Dim, Indexable};
|
use traits::structure::{Cast, Row, Col, Iterable, IterableMut, Dim, Indexable,
|
||||||
|
Eye, ColSlice, RowSlice};
|
||||||
use traits::operations::{Absolute, Transpose, Inv, Outer};
|
use traits::operations::{Absolute, Transpose, Inv, Outer};
|
||||||
use traits::geometry::{ToHomogeneous, FromHomogeneous};
|
use traits::geometry::{ToHomogeneous, FromHomogeneous};
|
||||||
|
|
||||||
|
@ -34,6 +36,8 @@ pub struct Mat1<N> {
|
||||||
pub m11: N
|
pub m11: N
|
||||||
}
|
}
|
||||||
|
|
||||||
|
eye_impl!(Mat1, 1, m11)
|
||||||
|
|
||||||
double_dispatch_binop_decl_trait!(Mat1, Mat1MulRhs)
|
double_dispatch_binop_decl_trait!(Mat1, Mat1MulRhs)
|
||||||
double_dispatch_binop_decl_trait!(Mat1, Mat1DivRhs)
|
double_dispatch_binop_decl_trait!(Mat1, Mat1DivRhs)
|
||||||
double_dispatch_binop_decl_trait!(Mat1, Mat1AddRhs)
|
double_dispatch_binop_decl_trait!(Mat1, Mat1AddRhs)
|
||||||
|
@ -116,6 +120,8 @@ transpose_impl!(Mat1, 1)
|
||||||
approx_eq_impl!(Mat1)
|
approx_eq_impl!(Mat1)
|
||||||
row_impl!(Mat1, Vec1, 1)
|
row_impl!(Mat1, Vec1, 1)
|
||||||
col_impl!(Mat1, Vec1, 1)
|
col_impl!(Mat1, Vec1, 1)
|
||||||
|
col_slice_impl!(Mat1, Vec1, 1)
|
||||||
|
row_slice_impl!(Mat1, Vec1, 1)
|
||||||
to_homogeneous_impl!(Mat1, Mat2, 1, 2)
|
to_homogeneous_impl!(Mat1, Mat2, 1, 2)
|
||||||
from_homogeneous_impl!(Mat1, Mat2, 1, 2)
|
from_homogeneous_impl!(Mat1, Mat2, 1, 2)
|
||||||
outer_impl!(Vec1, Mat1)
|
outer_impl!(Vec1, Mat1)
|
||||||
|
@ -127,6 +133,8 @@ pub struct Mat2<N> {
|
||||||
pub m12: N, pub m22: N
|
pub m12: N, pub m22: N
|
||||||
}
|
}
|
||||||
|
|
||||||
|
eye_impl!(Mat2, 2, m11, m22)
|
||||||
|
|
||||||
double_dispatch_binop_decl_trait!(Mat2, Mat2MulRhs)
|
double_dispatch_binop_decl_trait!(Mat2, Mat2MulRhs)
|
||||||
double_dispatch_binop_decl_trait!(Mat2, Mat2DivRhs)
|
double_dispatch_binop_decl_trait!(Mat2, Mat2DivRhs)
|
||||||
double_dispatch_binop_decl_trait!(Mat2, Mat2AddRhs)
|
double_dispatch_binop_decl_trait!(Mat2, Mat2AddRhs)
|
||||||
|
@ -213,6 +221,8 @@ transpose_impl!(Mat2, 2)
|
||||||
approx_eq_impl!(Mat2)
|
approx_eq_impl!(Mat2)
|
||||||
row_impl!(Mat2, Vec2, 2)
|
row_impl!(Mat2, Vec2, 2)
|
||||||
col_impl!(Mat2, Vec2, 2)
|
col_impl!(Mat2, Vec2, 2)
|
||||||
|
col_slice_impl!(Mat2, Vec2, 2)
|
||||||
|
row_slice_impl!(Mat2, Vec2, 2)
|
||||||
to_homogeneous_impl!(Mat2, Mat3, 2, 3)
|
to_homogeneous_impl!(Mat2, Mat3, 2, 3)
|
||||||
from_homogeneous_impl!(Mat2, Mat3, 2, 3)
|
from_homogeneous_impl!(Mat2, Mat3, 2, 3)
|
||||||
outer_impl!(Vec2, Mat2)
|
outer_impl!(Vec2, Mat2)
|
||||||
|
@ -225,6 +235,8 @@ pub struct Mat3<N> {
|
||||||
pub m13: N, pub m23: N, pub m33: N
|
pub m13: N, pub m23: N, pub m33: N
|
||||||
}
|
}
|
||||||
|
|
||||||
|
eye_impl!(Mat3, 3, m11, m22, m33)
|
||||||
|
|
||||||
double_dispatch_binop_decl_trait!(Mat3, Mat3MulRhs)
|
double_dispatch_binop_decl_trait!(Mat3, Mat3MulRhs)
|
||||||
double_dispatch_binop_decl_trait!(Mat3, Mat3DivRhs)
|
double_dispatch_binop_decl_trait!(Mat3, Mat3DivRhs)
|
||||||
double_dispatch_binop_decl_trait!(Mat3, Mat3AddRhs)
|
double_dispatch_binop_decl_trait!(Mat3, Mat3AddRhs)
|
||||||
|
@ -324,6 +336,8 @@ transpose_impl!(Mat3, 3)
|
||||||
approx_eq_impl!(Mat3)
|
approx_eq_impl!(Mat3)
|
||||||
// (specialized) row_impl!(Mat3, Vec3, 3)
|
// (specialized) row_impl!(Mat3, Vec3, 3)
|
||||||
// (specialized) col_impl!(Mat3, Vec3, 3)
|
// (specialized) col_impl!(Mat3, Vec3, 3)
|
||||||
|
col_slice_impl!(Mat3, Vec3, 3)
|
||||||
|
row_slice_impl!(Mat3, Vec3, 3)
|
||||||
to_homogeneous_impl!(Mat3, Mat4, 3, 4)
|
to_homogeneous_impl!(Mat3, Mat4, 3, 4)
|
||||||
from_homogeneous_impl!(Mat3, Mat4, 3, 4)
|
from_homogeneous_impl!(Mat3, Mat4, 3, 4)
|
||||||
outer_impl!(Vec3, Mat3)
|
outer_impl!(Vec3, Mat3)
|
||||||
|
@ -337,6 +351,8 @@ pub struct Mat4<N> {
|
||||||
pub m14: N, pub m24: N, pub m34: N, pub m44: N
|
pub m14: N, pub m24: N, pub m34: N, pub m44: N
|
||||||
}
|
}
|
||||||
|
|
||||||
|
eye_impl!(Mat4, 4, m11, m22, m33, m44)
|
||||||
|
|
||||||
double_dispatch_binop_decl_trait!(Mat4, Mat4MulRhs)
|
double_dispatch_binop_decl_trait!(Mat4, Mat4MulRhs)
|
||||||
double_dispatch_binop_decl_trait!(Mat4, Mat4DivRhs)
|
double_dispatch_binop_decl_trait!(Mat4, Mat4DivRhs)
|
||||||
double_dispatch_binop_decl_trait!(Mat4, Mat4AddRhs)
|
double_dispatch_binop_decl_trait!(Mat4, Mat4AddRhs)
|
||||||
|
@ -487,6 +503,8 @@ transpose_impl!(Mat4, 4)
|
||||||
approx_eq_impl!(Mat4)
|
approx_eq_impl!(Mat4)
|
||||||
row_impl!(Mat4, Vec4, 4)
|
row_impl!(Mat4, Vec4, 4)
|
||||||
col_impl!(Mat4, Vec4, 4)
|
col_impl!(Mat4, Vec4, 4)
|
||||||
|
col_slice_impl!(Mat4, Vec4, 4)
|
||||||
|
row_slice_impl!(Mat4, Vec4, 4)
|
||||||
to_homogeneous_impl!(Mat4, Mat5, 4, 5)
|
to_homogeneous_impl!(Mat4, Mat5, 4, 5)
|
||||||
from_homogeneous_impl!(Mat4, Mat5, 4, 5)
|
from_homogeneous_impl!(Mat4, Mat5, 4, 5)
|
||||||
outer_impl!(Vec4, Mat4)
|
outer_impl!(Vec4, Mat4)
|
||||||
|
@ -501,6 +519,8 @@ pub struct Mat5<N> {
|
||||||
pub m15: N, pub m25: N, pub m35: N, pub m45: N, pub m55: N
|
pub m15: N, pub m25: N, pub m35: N, pub m45: N, pub m55: N
|
||||||
}
|
}
|
||||||
|
|
||||||
|
eye_impl!(Mat5, 5, m11, m22, m33, m44, m55)
|
||||||
|
|
||||||
double_dispatch_binop_decl_trait!(Mat5, Mat5MulRhs)
|
double_dispatch_binop_decl_trait!(Mat5, Mat5MulRhs)
|
||||||
double_dispatch_binop_decl_trait!(Mat5, Mat5DivRhs)
|
double_dispatch_binop_decl_trait!(Mat5, Mat5DivRhs)
|
||||||
double_dispatch_binop_decl_trait!(Mat5, Mat5AddRhs)
|
double_dispatch_binop_decl_trait!(Mat5, Mat5AddRhs)
|
||||||
|
@ -666,6 +686,8 @@ transpose_impl!(Mat5, 5)
|
||||||
approx_eq_impl!(Mat5)
|
approx_eq_impl!(Mat5)
|
||||||
row_impl!(Mat5, Vec5, 5)
|
row_impl!(Mat5, Vec5, 5)
|
||||||
col_impl!(Mat5, Vec5, 5)
|
col_impl!(Mat5, Vec5, 5)
|
||||||
|
col_slice_impl!(Mat5, Vec5, 5)
|
||||||
|
row_slice_impl!(Mat5, Vec5, 5)
|
||||||
to_homogeneous_impl!(Mat5, Mat6, 5, 6)
|
to_homogeneous_impl!(Mat5, Mat6, 5, 6)
|
||||||
from_homogeneous_impl!(Mat5, Mat6, 5, 6)
|
from_homogeneous_impl!(Mat5, Mat6, 5, 6)
|
||||||
outer_impl!(Vec5, Mat5)
|
outer_impl!(Vec5, Mat5)
|
||||||
|
@ -681,6 +703,8 @@ pub struct Mat6<N> {
|
||||||
pub m16: N, pub m26: N, pub m36: N, pub m46: N, pub m56: N, pub m66: N
|
pub m16: N, pub m26: N, pub m36: N, pub m46: N, pub m56: N, pub m66: N
|
||||||
}
|
}
|
||||||
|
|
||||||
|
eye_impl!(Mat6, 6, m11, m22, m33, m44, m55, m66)
|
||||||
|
|
||||||
double_dispatch_binop_decl_trait!(Mat6, Mat6MulRhs)
|
double_dispatch_binop_decl_trait!(Mat6, Mat6MulRhs)
|
||||||
double_dispatch_binop_decl_trait!(Mat6, Mat6DivRhs)
|
double_dispatch_binop_decl_trait!(Mat6, Mat6DivRhs)
|
||||||
double_dispatch_binop_decl_trait!(Mat6, Mat6AddRhs)
|
double_dispatch_binop_decl_trait!(Mat6, Mat6AddRhs)
|
||||||
|
@ -897,4 +921,6 @@ transpose_impl!(Mat6, 6)
|
||||||
approx_eq_impl!(Mat6)
|
approx_eq_impl!(Mat6)
|
||||||
row_impl!(Mat6, Vec6, 6)
|
row_impl!(Mat6, Vec6, 6)
|
||||||
col_impl!(Mat6, Vec6, 6)
|
col_impl!(Mat6, Vec6, 6)
|
||||||
|
col_slice_impl!(Mat6, Vec6, 6)
|
||||||
|
row_slice_impl!(Mat6, Vec6, 6)
|
||||||
outer_impl!(Vec6, Mat6)
|
outer_impl!(Vec6, Mat6)
|
||||||
|
|
|
@ -98,6 +98,20 @@ macro_rules! scalar_add_impl(
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
macro_rules! eye_impl(
|
||||||
|
($t: ident, $ndim: expr, $($comp_diagN: ident),+) => (
|
||||||
|
impl<N: Zero + One> Eye for $t<N> {
|
||||||
|
fn new_identity(dim: uint) -> $t<N> {
|
||||||
|
assert!(dim == $ndim);
|
||||||
|
let mut eye: $t<N> = Zero::zero();
|
||||||
|
$(eye.$comp_diagN = One::one();)+
|
||||||
|
eye
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
macro_rules! scalar_sub_impl(
|
macro_rules! scalar_sub_impl(
|
||||||
($t: ident, $n: ident, $trhs: ident, $comp0: ident $(,$compN: ident)*) => (
|
($t: ident, $n: ident, $trhs: ident, $comp0: ident $(,$compN: ident)*) => (
|
||||||
impl $trhs<$n, $t<$n>> for $n {
|
impl $trhs<$n, $t<$n>> for $n {
|
||||||
|
@ -193,6 +207,11 @@ macro_rules! indexable_impl(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn shape(&self) -> (uint, uint) {
|
||||||
|
($dim, $dim)
|
||||||
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
unsafe fn unsafe_at(&self, (i, j): (uint, uint)) -> N {
|
unsafe fn unsafe_at(&self, (i, j): (uint, uint)) -> N {
|
||||||
(*mem::transmute::<&$t<N>, &[N, ..$dim * $dim]>(self).unsafe_ref(i + j * $dim)).clone()
|
(*mem::transmute::<&$t<N>, &[N, ..$dim * $dim]>(self).unsafe_ref(i + j * $dim)).clone()
|
||||||
|
@ -206,6 +225,26 @@ macro_rules! indexable_impl(
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
macro_rules! col_slice_impl(
|
||||||
|
($t: ident, $tv: ident, $dim: expr) => (
|
||||||
|
impl<N: Clone + Zero> ColSlice<DVec<N>> for $t<N> {
|
||||||
|
fn col_slice(& self, cid: uint, rstart: uint, rend: uint) -> DVec<N> {
|
||||||
|
assert!(cid < $dim);
|
||||||
|
assert!(rstart < rend);
|
||||||
|
assert!(rend <= $dim);
|
||||||
|
let col = self.col(cid);
|
||||||
|
let res = DVec::from_vec(
|
||||||
|
rend - rstart,
|
||||||
|
unsafe {
|
||||||
|
mem::transmute::<&$tv<N>, & [N, ..$dim]>
|
||||||
|
(&col).slice(rstart, rend)
|
||||||
|
});
|
||||||
|
res
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
macro_rules! row_impl(
|
macro_rules! row_impl(
|
||||||
($t: ident, $tv: ident, $dim: expr) => (
|
($t: ident, $tv: ident, $dim: expr) => (
|
||||||
impl<N: Clone + Zero> Row<$tv<N>> for $t<N> {
|
impl<N: Clone + Zero> Row<$tv<N>> for $t<N> {
|
||||||
|
@ -235,6 +274,26 @@ macro_rules! row_impl(
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
macro_rules! row_slice_impl(
|
||||||
|
($t: ident, $tv: ident, $dim: expr) => (
|
||||||
|
impl<N: Clone + Zero> RowSlice<DVec<N>> for $t<N> {
|
||||||
|
fn row_slice(& self, rid: uint, cstart: uint, cend: uint) -> DVec<N> {
|
||||||
|
assert!(rid < $dim);
|
||||||
|
assert!(cstart < cend);
|
||||||
|
assert!(cend <= $dim);
|
||||||
|
let row = self.row(rid);
|
||||||
|
let res = DVec::from_vec(
|
||||||
|
cend - cstart,
|
||||||
|
unsafe {
|
||||||
|
mem::transmute::<&$tv<N>, & [N, ..$dim]>
|
||||||
|
(&row).slice(cstart, cend)
|
||||||
|
});
|
||||||
|
res
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
macro_rules! col_impl(
|
macro_rules! col_impl(
|
||||||
($t: ident, $tv: ident, $dim: expr) => (
|
($t: ident, $tv: ident, $dim: expr) => (
|
||||||
impl<N: Clone + Zero> Col<$tv<N>> for $t<N> {
|
impl<N: Clone + Zero> Col<$tv<N>> for $t<N> {
|
||||||
|
|
|
@ -20,7 +20,7 @@ pub struct Rot2<N> {
|
||||||
submat: Mat2<N>
|
submat: Mat2<N>
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<N: Clone + Float + Neg<N>> Rot2<N> {
|
impl<N: Clone + FloatMath + Neg<N>> Rot2<N> {
|
||||||
/// Builds a 2 dimensional rotation matrix from an angle in radian.
|
/// Builds a 2 dimensional rotation matrix from an angle in radian.
|
||||||
pub fn new(angle: Vec1<N>) -> Rot2<N> {
|
pub fn new(angle: Vec1<N>) -> Rot2<N> {
|
||||||
let (sia, coa) = angle.x.sin_cos();
|
let (sia, coa) = angle.x.sin_cos();
|
||||||
|
@ -31,7 +31,7 @@ impl<N: Clone + Float + Neg<N>> Rot2<N> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<N: Float + Num + Clone>
|
impl<N: FloatMath + Clone>
|
||||||
Rotation<Vec1<N>> for Rot2<N> {
|
Rotation<Vec1<N>> for Rot2<N> {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn rotation(&self) -> Vec1<N> {
|
fn rotation(&self) -> Vec1<N> {
|
||||||
|
@ -69,7 +69,7 @@ Rotation<Vec1<N>> for Rot2<N> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<N: Clone + Rand + Float + Neg<N>> Rand for Rot2<N> {
|
impl<N: Clone + Rand + FloatMath + Neg<N>> Rand for Rot2<N> {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn rand<R: Rng>(rng: &mut R) -> Rot2<N> {
|
fn rand<R: Rng>(rng: &mut R) -> Rot2<N> {
|
||||||
Rot2::new(rng.gen())
|
Rot2::new(rng.gen())
|
||||||
|
@ -99,7 +99,7 @@ pub struct Rot3<N> {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
impl<N: Clone + Float + Num + Float> Rot3<N> {
|
impl<N: Clone + FloatMath> Rot3<N> {
|
||||||
/// Builds a 3 dimensional rotation matrix from an axis and an angle.
|
/// Builds a 3 dimensional rotation matrix from an axis and an angle.
|
||||||
///
|
///
|
||||||
/// # Arguments
|
/// # Arguments
|
||||||
|
@ -140,7 +140,7 @@ impl<N: Clone + Float + Num + Float> Rot3<N> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<N: Clone + Num + Float> Rot3<N> {
|
impl<N: Clone + Float> Rot3<N> {
|
||||||
/// Reorient this matrix such that its local `x` axis points to a given point. Note that the
|
/// Reorient this matrix such that its local `x` axis points to a given point. Note that the
|
||||||
/// usually known `look_at` function does the same thing but with the `z` axis. See `look_at_z`
|
/// usually known `look_at` function does the same thing but with the `z` axis. See `look_at_z`
|
||||||
/// for that.
|
/// for that.
|
||||||
|
@ -180,7 +180,7 @@ impl<N: Clone + Num + Float> Rot3<N> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<N: Clone + Float + Num + Float + Cast<f32>>
|
impl<N: Clone + FloatMath + Cast<f32>>
|
||||||
Rotation<Vec3<N>> for Rot3<N> {
|
Rotation<Vec3<N>> for Rot3<N> {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn rotation(&self) -> Vec3<N> {
|
fn rotation(&self) -> Vec3<N> {
|
||||||
|
@ -245,7 +245,7 @@ Rotation<Vec3<N>> for Rot3<N> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<N: Clone + Rand + Float + Num + Float>
|
impl<N: Clone + Rand + FloatMath>
|
||||||
Rand for Rot3<N> {
|
Rand for Rot3<N> {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn rand<R: Rng>(rng: &mut R) -> Rot3<N> {
|
fn rand<R: Rng>(rng: &mut R) -> Rot3<N> {
|
||||||
|
@ -309,7 +309,7 @@ impl<N: Signed> AbsoluteRotate<Vec4<N>> for Rot4<N> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<N: Float + Num + Clone>
|
impl<N: Float + Clone>
|
||||||
Rotation<Vec4<N>> for Rot4<N> {
|
Rotation<Vec4<N>> for Rot4<N> {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn rotation(&self) -> Vec4<N> {
|
fn rotation(&self) -> Vec4<N> {
|
||||||
|
|
|
@ -56,7 +56,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> + Float + Float + Num + Clone>
|
impl<N: Cast<f32> + FloatMath + Clone>
|
||||||
RotationMatrix<$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> {
|
||||||
|
|
|
@ -25,6 +25,11 @@ impl<N> Indexable<uint, N> for vec::Vec0<N> {
|
||||||
fn set(&mut self, _: uint, _: N) {
|
fn set(&mut self, _: uint, _: N) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn shape(&self) -> uint {
|
||||||
|
0
|
||||||
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn swap(&mut self, _: uint, _: uint) {
|
fn swap(&mut self, _: uint, _: uint) {
|
||||||
}
|
}
|
||||||
|
@ -159,7 +164,7 @@ impl<N: Clone + Add<N, N> + Neg<N>> Translation<vec::Vec0<N>> for vec::Vec0<N> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<N: Num + Float> Norm<N> for vec::Vec0<N> {
|
impl<N: Float> Norm<N> for vec::Vec0<N> {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn sqnorm(_: &vec::Vec0<N>) -> N {
|
fn sqnorm(_: &vec::Vec0<N>) -> N {
|
||||||
Zero::zero()
|
Zero::zero()
|
||||||
|
|
|
@ -38,7 +38,7 @@ macro_rules! at_fast_impl(
|
||||||
// However, f32/f64 does not implement TotalOrd…
|
// However, f32/f64 does not implement TotalOrd…
|
||||||
macro_rules! ord_impl(
|
macro_rules! ord_impl(
|
||||||
($t: ident, $comp0: ident $(,$compN: ident)*) => (
|
($t: ident, $comp0: ident $(,$compN: ident)*) => (
|
||||||
impl<N: Float + Eq + Clone> PartialOrd for $t<N> {
|
impl<N: FloatMath + Eq + Clone> PartialOrd for $t<N> {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn inf(a: &$t<N>, b: &$t<N>) -> $t<N> {
|
fn inf(a: &$t<N>, b: &$t<N>) -> $t<N> {
|
||||||
$t::new(a.$comp0.min(b.$comp0.clone())
|
$t::new(a.$comp0.min(b.$comp0.clone())
|
||||||
|
@ -165,6 +165,11 @@ macro_rules! indexable_impl(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn shape(&self) -> uint {
|
||||||
|
$dim
|
||||||
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn swap(&mut self, i1: uint, i2: uint) {
|
fn swap(&mut self, i1: uint, i2: uint) {
|
||||||
unsafe {
|
unsafe {
|
||||||
|
@ -250,7 +255,7 @@ macro_rules! container_impl(
|
||||||
|
|
||||||
macro_rules! basis_impl(
|
macro_rules! basis_impl(
|
||||||
($t: ident, $trhs: ident, $dim: expr) => (
|
($t: ident, $trhs: ident, $dim: expr) => (
|
||||||
impl<N: Clone + Num + Float + ApproxEq<N> + $trhs<N, $t<N>>> Basis for $t<N> {
|
impl<N: Clone + Float + ApproxEq<N> + $trhs<N, $t<N>>> Basis for $t<N> {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn canonical_basis(f: |$t<N>| -> bool) {
|
fn canonical_basis(f: |$t<N>| -> bool) {
|
||||||
for i in range(0u, $dim) {
|
for i in range(0u, $dim) {
|
||||||
|
@ -460,7 +465,7 @@ macro_rules! translation_impl(
|
||||||
|
|
||||||
macro_rules! norm_impl(
|
macro_rules! norm_impl(
|
||||||
($t: ident, $comp0: ident $(,$compN: ident)*) => (
|
($t: ident, $comp0: ident $(,$compN: ident)*) => (
|
||||||
impl<N: Clone + Num + Float> Norm<N> for $t<N> {
|
impl<N: Clone + Float> Norm<N> for $t<N> {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn sqnorm(v: &$t<N>) -> N {
|
fn sqnorm(v: &$t<N>) -> N {
|
||||||
Dot::dot(v, v)
|
Dot::dot(v, v)
|
||||||
|
|
|
@ -3,6 +3,7 @@ use rand::random;
|
||||||
use na::{Vec1, Vec3, Mat1, Mat2, Mat3, Mat4, Mat5, Mat6, Rot3, DMat, DVec, Indexable};
|
use na::{Vec1, Vec3, Mat1, Mat2, Mat3, Mat4, Mat5, Mat6, Rot3, DMat, DVec, Indexable};
|
||||||
use na;
|
use na;
|
||||||
use na::decomp_qr;
|
use na::decomp_qr;
|
||||||
|
use std::cmp::{min, max};
|
||||||
|
|
||||||
macro_rules! test_inv_mat_impl(
|
macro_rules! test_inv_mat_impl(
|
||||||
($t: ty) => (
|
($t: ty) => (
|
||||||
|
@ -24,6 +25,19 @@ macro_rules! test_transpose_mat_impl(
|
||||||
);
|
);
|
||||||
)
|
)
|
||||||
|
|
||||||
|
macro_rules! test_decomp_qr_impl(
|
||||||
|
($t: ty) => (
|
||||||
|
for _ in range(0, 10000) {
|
||||||
|
let randmat : $t = random();
|
||||||
|
|
||||||
|
let (q, r) = decomp_qr(&randmat);
|
||||||
|
let recomp = q * r;
|
||||||
|
|
||||||
|
assert!(na::approx_eq(&randmat, &recomp));
|
||||||
|
}
|
||||||
|
);
|
||||||
|
)
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_transpose_mat1() {
|
fn test_transpose_mat1() {
|
||||||
test_transpose_mat_impl!(Mat1<f64>);
|
test_transpose_mat_impl!(Mat1<f64>);
|
||||||
|
@ -210,20 +224,45 @@ fn test_dmat_from_vec() {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_decomp_qr() {
|
fn test_decomp_qr() {
|
||||||
let mat = DMat::from_row_vec(
|
for _ in range(0, 10) {
|
||||||
5,
|
let dim1: uint = random();
|
||||||
3,
|
let dim2: uint = random();
|
||||||
[
|
let rows = min(40, max(dim1, dim2));
|
||||||
4.0, 2.0, 0.60,
|
let cols = min(40, min(dim1, dim2));
|
||||||
4.2, 2.1, 0.59,
|
let randmat: DMat<f64> = DMat::new_random(rows, cols);
|
||||||
3.9, 2.0, 0.58,
|
let (q, r) = decomp_qr(&randmat);
|
||||||
4.3, 2.1, 0.62,
|
let recomp = q * r;
|
||||||
4.1, 2.2, 0.63
|
|
||||||
]
|
|
||||||
);
|
|
||||||
|
|
||||||
let (q, r) = decomp_qr(&mat);
|
assert!(na::approx_eq(&randmat, &recomp));
|
||||||
let mat_ = q * r;
|
}
|
||||||
|
}
|
||||||
assert!(na::approx_eq(&mat_, &mat));
|
|
||||||
|
#[test]
|
||||||
|
fn test_decomp_qr_mat1() {
|
||||||
|
test_decomp_qr_impl!(Mat1<f64>);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_decomp_qr_mat2() {
|
||||||
|
test_decomp_qr_impl!(Mat2<f64>);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_decomp_qr_mat3() {
|
||||||
|
test_decomp_qr_impl!(Mat3<f64>);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_decomp_qr_mat4() {
|
||||||
|
test_decomp_qr_impl!(Mat4<f64>);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_decomp_qr_mat5() {
|
||||||
|
test_decomp_qr_impl!(Mat5<f64>);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_decomp_qr_mat6() {
|
||||||
|
test_decomp_qr_impl!(Mat6<f64>);
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,7 +6,7 @@ pub use self::geometry::{AbsoluteRotate, Cross, CrossMatrix, Dot, FromHomogeneou
|
||||||
|
|
||||||
pub use self::structure::{FloatVec, FloatVecExt, Basis, Cast, Col, Dim, Indexable,
|
pub use self::structure::{FloatVec, FloatVecExt, Basis, Cast, Col, Dim, Indexable,
|
||||||
Iterable, IterableMut, Mat, Row, AnyVec, VecExt,
|
Iterable, IterableMut, Mat, Row, AnyVec, VecExt,
|
||||||
ColSlice, RowSlice};
|
ColSlice, RowSlice, Eye};
|
||||||
|
|
||||||
pub use self::operations::{Absolute, ApproxEq, Cov, Inv, LMul, Mean, Outer, PartialOrd, RMul,
|
pub use self::operations::{Absolute, ApproxEq, Cov, Inv, LMul, Mean, Outer, PartialOrd, RMul,
|
||||||
ScalarAdd, ScalarSub, Transpose};
|
ScalarAdd, ScalarSub, Transpose};
|
||||||
|
|
|
@ -19,6 +19,12 @@ pub trait Mat<R, C> : Row<R> + Col<C> + RMul<R> + LMul<C> { }
|
||||||
impl<M: Row<R> + Col<C> + RMul<R> + LMul<C>, R, C> Mat<R, C> for M {
|
impl<M: Row<R> + Col<C> + RMul<R> + LMul<C>, R, C> Mat<R, C> for M {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Trait for constructing the identity matrix
|
||||||
|
pub trait Eye {
|
||||||
|
/// Return the identity matrix of specified dimension
|
||||||
|
fn new_identity(dim: uint) -> Self;
|
||||||
|
}
|
||||||
|
|
||||||
// XXX: we keep ScalarAdd and ScalarSub here to avoid trait impl conflict (overriding) between the
|
// XXX: we keep ScalarAdd and ScalarSub here to avoid trait impl conflict (overriding) between the
|
||||||
// different Add/Sub traits. This is _so_ unfortunate…
|
// different Add/Sub traits. This is _so_ unfortunate…
|
||||||
|
|
||||||
|
@ -126,6 +132,9 @@ pub trait Indexable<Index, Res> {
|
||||||
/// Swaps the `i`-th element of `self` with its `j`-th element.
|
/// Swaps the `i`-th element of `self` with its `j`-th element.
|
||||||
fn swap(&mut self, i: Index, j: Index);
|
fn swap(&mut self, i: Index, j: Index);
|
||||||
|
|
||||||
|
/// Returns the shape of the iterable range
|
||||||
|
fn shape(&self) -> Index;
|
||||||
|
|
||||||
/// Reads the `i`-th element of `self`.
|
/// Reads the `i`-th element of `self`.
|
||||||
///
|
///
|
||||||
/// `i` is not checked.
|
/// `i` is not checked.
|
||||||
|
|
Loading…
Reference in New Issue