Add two traits: `CrossMatrix` and `Row`.

CrossMatrix is a trait for vectors having a cross product representable as a matrix.
Row is a trait for Matrixces and Vectors, to access (by index) their rows.
This commit is contained in:
Sébastien Crozet 2013-08-25 23:01:44 +02:00
parent 4635d6ebac
commit 7052aa88ee
7 changed files with 142 additions and 23 deletions

View File

@ -13,6 +13,7 @@ use traits::transformation::Transform;
use traits::homogeneous::{FromHomogeneous, ToHomogeneous}; use traits::homogeneous::{FromHomogeneous, ToHomogeneous};
use traits::indexable::Indexable; use traits::indexable::Indexable;
use traits::column::Column; use traits::column::Column;
use traits::row::Row;
use traits::iterable::{Iterable, IterableMut}; use traits::iterable::{Iterable, IterableMut};
use traits::outer::Outer; use traits::outer::Outer;
use traits::scalar_op::{ScalarAdd, ScalarSub}; use traits::scalar_op::{ScalarAdd, ScalarSub};
@ -70,7 +71,8 @@ transform_impl!(Mat1, Vec1)
// (specialized) inv_impl!(Mat1, 1) // (specialized) inv_impl!(Mat1, 1)
transpose_impl!(Mat1, 1) transpose_impl!(Mat1, 1)
approx_eq_impl!(Mat1) approx_eq_impl!(Mat1)
column_impl!(Mat1, 1) column_impl!(Mat1, Vec1, 1)
row_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)
@ -111,7 +113,8 @@ transform_impl!(Mat2, Vec2)
// (specialized) inv_impl!(Mat2, 2) // (specialized) inv_impl!(Mat2, 2)
transpose_impl!(Mat2, 2) transpose_impl!(Mat2, 2)
approx_eq_impl!(Mat2) approx_eq_impl!(Mat2)
column_impl!(Mat2, 2) column_impl!(Mat2, Vec2, 2)
row_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)
@ -162,7 +165,8 @@ transform_impl!(Mat3, Vec3)
// (specialized) inv_impl!(Mat3, 3) // (specialized) inv_impl!(Mat3, 3)
transpose_impl!(Mat3, 3) transpose_impl!(Mat3, 3)
approx_eq_impl!(Mat3) approx_eq_impl!(Mat3)
column_impl!(Mat3, 3) column_impl!(Mat3, Vec3, 3)
// (specialized) row_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)
@ -239,7 +243,8 @@ transform_impl!(Mat4, Vec4)
inv_impl!(Mat4, 4) inv_impl!(Mat4, 4)
transpose_impl!(Mat4, 4) transpose_impl!(Mat4, 4)
approx_eq_impl!(Mat4) approx_eq_impl!(Mat4)
column_impl!(Mat4, 4) column_impl!(Mat4, Vec4, 4)
row_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)
@ -328,7 +333,8 @@ transform_impl!(Mat5, Vec5)
inv_impl!(Mat5, 5) inv_impl!(Mat5, 5)
transpose_impl!(Mat5, 5) transpose_impl!(Mat5, 5)
approx_eq_impl!(Mat5) approx_eq_impl!(Mat5)
column_impl!(Mat5, 5) column_impl!(Mat5, Vec5, 5)
row_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)
@ -427,5 +433,6 @@ transform_impl!(Mat6, Vec6)
inv_impl!(Mat6, 6) inv_impl!(Mat6, 6)
transpose_impl!(Mat6, 6) transpose_impl!(Mat6, 6)
approx_eq_impl!(Mat6) approx_eq_impl!(Mat6)
column_impl!(Mat6, 6) column_impl!(Mat6, Vec6, 6)
row_impl!(Mat6, Vec6, 6)
outer_impl!(Vec6, Mat6) outer_impl!(Vec6, Mat6)

View File

@ -183,29 +183,45 @@ macro_rules! indexable_impl(
) )
macro_rules! column_impl( macro_rules! column_impl(
($t: ident, $dim: expr) => ( ($t: ident, $tv: ident, $dim: expr) => (
impl<N: Clone, V: Zero + Iterable<N> + IterableMut<N>> Column<V> for $t<N> { impl<N: Clone + Zero> Column<$tv<N>> for $t<N> {
#[inline] #[inline]
fn set_column(&mut self, col: uint, v: V) { fn set_column(&mut self, col: uint, v: $tv<N>) {
for (i, e) in v.iter().enumerate() { for (i, e) in v.iter().enumerate() {
if i == Dim::dim::<$t<N>>() {
break
}
self.set((i, col), e.clone()); self.set((i, col), e.clone());
} }
} }
#[inline] #[inline]
fn column(&self, col: uint) -> V { fn column(&self, col: uint) -> $tv<N> {
let mut res = Zero::zero::<V>(); let mut res = Zero::zero::<$tv<N>>();
for (i, e) in res.mut_iter().enumerate() { for (i, e) in res.mut_iter().enumerate() {
if i >= Dim::dim::<$t<N>>() { *e = self.at((i, col));
break
} }
*e = self.at((i, col)); res
}
}
)
)
macro_rules! row_impl(
($t: ident, $tv: ident, $dim: expr) => (
impl<N: Clone + Zero> Row<$tv<N>> for $t<N> {
#[inline]
fn set_row(&mut self, row: uint, v: $tv<N>) {
for (i, e) in v.iter().enumerate() {
self.set((row, i), e.clone());
}
}
#[inline]
fn row(&self, row: uint) -> $tv<N> {
let mut res = Zero::zero::<$tv<N>>();
for (i, e) in res.mut_iter().enumerate() {
*e = self.at((row, i));
} }
res res

View File

@ -1,6 +1,8 @@
use std::num::{Zero, One}; use std::num::{Zero, One};
use vec::Vec3;
use mat::{Mat1, Mat2, Mat3}; use mat::{Mat1, Mat2, Mat3};
use traits::inv::Inv; use traits::inv::Inv;
use traits::row::Row;
// some specializations: // some specializations:
impl<N: Num + Clone> impl<N: Num + Clone>
@ -106,3 +108,38 @@ Inv for Mat3<N> {
} }
} }
} }
impl<N: Clone> Row<Vec3<N>> for Mat3<N> {
#[inline]
fn row(&self, i: uint) -> Vec3<N> {
match i {
0 => Vec3::new(self.m11.clone(), self.m12.clone(), self.m13.clone()),
1 => Vec3::new(self.m21.clone(), self.m22.clone(), self.m23.clone()),
2 => Vec3::new(self.m31.clone(), self.m32.clone(), self.m33.clone()),
_ => fail!("Index out of range: 3d matrices do not have " + i.to_str() + " rows.")
}
}
#[inline]
fn set_row(&mut self, i: uint, r: Vec3<N>) {
match i {
0 => {
self.m11 = r.x.clone();
self.m12 = r.y.clone();
self.m13 = r.z;
},
1 => {
self.m21 = r.x.clone();
self.m22 = r.y.clone();
self.m23 = r.z;
},
2 => {
self.m31 = r.x.clone();
self.m32 = r.y.clone();
self.m33 = r.z;
},
_ => fail!("Index out of range: 3d matrices do not have " + i.to_str() + " rows.")
}
}
}

View File

@ -52,6 +52,7 @@ pub mod traits
pub mod sample; pub mod sample;
pub mod indexable; pub mod indexable;
pub mod column; pub mod column;
pub mod row;
pub mod iterable; pub mod iterable;
pub mod outer; pub mod outer;
pub mod cross; pub mod cross;

View File

@ -1,8 +1,16 @@
/** /**
* Trait of elements having a cross product. * Trait of elements having a cross product.
*/ */
pub trait Cross<Result> pub trait Cross<V> {
{
/// Computes the cross product between two elements (usually vectors). /// Computes the cross product between two elements (usually vectors).
fn cross(&self, other : &Self) -> Result; fn cross(&self, other: &Self) -> V;
}
/**
* Trait of elements having a cross product operation which can be expressed as a matrix.
*/
pub trait CrossMatrix<M> {
/// The matrix associated to any cross product with this vector. I.e. `v.cross(anything)` =
/// `v.cross_matrix().rmul(anything)`.
fn cross_matrix(&self) -> M;
} }

7
src/traits/row.rs Normal file
View File

@ -0,0 +1,7 @@
/// Traits to access rows of a matrix or vector.
pub trait Row<R> {
/// Reads the `i`-th row of `self`.
fn row(&self, i: uint) -> R;
/// Writes the `i`-th row of `self`.
fn set_row(&mut self, i: uint, R);
}

View File

@ -1,10 +1,12 @@
use std::num::{Zero, One}; use std::num::{Zero, One};
use traits::basis::Basis; use traits::basis::Basis;
use traits::cross::Cross; use traits::cross::{Cross, CrossMatrix};
use traits::sample::UniformSphereSample; use traits::sample::UniformSphereSample;
use traits::vec_cast::VecCast; use traits::vec_cast::VecCast;
use traits::vector::{AlgebraicVec}; use traits::vector::{AlgebraicVec};
use traits::row::Row;
use vec::{Vec1, Vec2, Vec3}; use vec::{Vec1, Vec2, Vec3};
use mat::Mat3;
impl<N: Mul<N, N> + Sub<N, N>> Cross<Vec1<N>> for Vec2<N> { impl<N: Mul<N, N> + Sub<N, N>> Cross<Vec1<N>> for Vec2<N> {
#[inline] #[inline]
@ -13,6 +15,14 @@ impl<N: Mul<N, N> + Sub<N, N>> Cross<Vec1<N>> for Vec2<N> {
} }
} }
// FIXME: instead of returning a Vec2, define a Mat2x1 matrix?
impl<N: Neg<N> + Clone> CrossMatrix<Vec2<N>> for Vec2<N> {
#[inline]
fn cross_matrix(&self) -> Vec2<N> {
Vec2::new(-self.y, self.x.clone())
}
}
impl<N: Mul<N, N> + Sub<N, N>> Cross<Vec3<N>> for Vec3<N> { impl<N: Mul<N, N> + Sub<N, N>> Cross<Vec3<N>> for Vec3<N> {
#[inline] #[inline]
fn cross(&self, other : &Vec3<N>) -> Vec3<N> { fn cross(&self, other : &Vec3<N>) -> Vec3<N> {
@ -24,6 +34,39 @@ impl<N: Mul<N, N> + Sub<N, N>> Cross<Vec3<N>> for Vec3<N> {
} }
} }
impl<N: Neg<N> + Zero + Clone> CrossMatrix<Mat3<N>> for Vec3<N> {
#[inline]
fn cross_matrix(&self) -> Mat3<N> {
Mat3::new(
Zero::zero() , -self.z, self.y.clone(),
self.z.clone(), Zero::zero(), -self.x,
-self.y , self.x.clone(), Zero::zero()
)
}
}
// FIXME: iplement this for all other vectors
impl<N: Clone> Row<Vec1<N>> for Vec2<N> {
#[inline]
fn row(&self, i: uint) -> Vec1<N> {
match i {
0 => Vec1::new(self.x.clone()),
1 => Vec1::new(self.y.clone()),
_ => fail!("Index out of range: 2d vectors do not have " + i.to_str() + " rows.")
}
}
#[inline]
fn set_row(&mut self, i: uint, r: Vec1<N>) {
match i {
0 => self.x = r.x,
1 => self.y = r.x,
_ => fail!("Index out of range: 2d vectors do not have " + i.to_str() + " rows.")
}
}
}
impl<N: One> Basis for Vec1<N> { impl<N: One> Basis for Vec1<N> {
#[inline(always)] #[inline(always)]
fn canonical_basis(f: &fn(Vec1<N>) -> bool) { fn canonical_basis(f: &fn(Vec1<N>) -> bool) {