diff --git a/src/mat.rs b/src/mat.rs index cb66d189..075fc313 100644 --- a/src/mat.rs +++ b/src/mat.rs @@ -13,6 +13,7 @@ use traits::transformation::Transform; use traits::homogeneous::{FromHomogeneous, ToHomogeneous}; use traits::indexable::Indexable; use traits::column::Column; +use traits::row::Row; use traits::iterable::{Iterable, IterableMut}; use traits::outer::Outer; use traits::scalar_op::{ScalarAdd, ScalarSub}; @@ -70,7 +71,8 @@ transform_impl!(Mat1, Vec1) // (specialized) inv_impl!(Mat1, 1) transpose_impl!(Mat1, 1) 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) from_homogeneous_impl!(Mat1, Mat2, 1, 2) outer_impl!(Vec1, Mat1) @@ -111,7 +113,8 @@ transform_impl!(Mat2, Vec2) // (specialized) inv_impl!(Mat2, 2) transpose_impl!(Mat2, 2) 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) from_homogeneous_impl!(Mat2, Mat3, 2, 3) outer_impl!(Vec2, Mat2) @@ -162,7 +165,8 @@ transform_impl!(Mat3, Vec3) // (specialized) inv_impl!(Mat3, 3) transpose_impl!(Mat3, 3) 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) from_homogeneous_impl!(Mat3, Mat4, 3, 4) outer_impl!(Vec3, Mat3) @@ -239,7 +243,8 @@ transform_impl!(Mat4, Vec4) inv_impl!(Mat4, 4) transpose_impl!(Mat4, 4) 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) from_homogeneous_impl!(Mat4, Mat5, 4, 5) outer_impl!(Vec4, Mat4) @@ -328,7 +333,8 @@ transform_impl!(Mat5, Vec5) inv_impl!(Mat5, 5) transpose_impl!(Mat5, 5) 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) from_homogeneous_impl!(Mat5, Mat6, 5, 6) outer_impl!(Vec5, Mat5) @@ -427,5 +433,6 @@ transform_impl!(Mat6, Vec6) inv_impl!(Mat6, 6) transpose_impl!(Mat6, 6) approx_eq_impl!(Mat6) -column_impl!(Mat6, 6) +column_impl!(Mat6, Vec6, 6) +row_impl!(Mat6, Vec6, 6) outer_impl!(Vec6, Mat6) diff --git a/src/mat_macros.rs b/src/mat_macros.rs index e58d5d1c..814911ca 100644 --- a/src/mat_macros.rs +++ b/src/mat_macros.rs @@ -183,28 +183,20 @@ macro_rules! indexable_impl( ) macro_rules! column_impl( - ($t: ident, $dim: expr) => ( - impl + IterableMut> Column for $t { + ($t: ident, $tv: ident, $dim: expr) => ( + impl Column<$tv> for $t { #[inline] - fn set_column(&mut self, col: uint, v: V) { + fn set_column(&mut self, col: uint, v: $tv) { for (i, e) in v.iter().enumerate() { - if i == Dim::dim::<$t>() { - break - } - self.set((i, col), e.clone()); } } #[inline] - fn column(&self, col: uint) -> V { - let mut res = Zero::zero::(); + fn column(&self, col: uint) -> $tv { + let mut res = Zero::zero::<$tv>(); for (i, e) in res.mut_iter().enumerate() { - if i >= Dim::dim::<$t>() { - break - } - *e = self.at((i, col)); } @@ -214,6 +206,30 @@ macro_rules! column_impl( ) ) +macro_rules! row_impl( + ($t: ident, $tv: ident, $dim: expr) => ( + impl Row<$tv> for $t { + #[inline] + fn set_row(&mut self, row: uint, v: $tv) { + for (i, e) in v.iter().enumerate() { + self.set((row, i), e.clone()); + } + } + + #[inline] + fn row(&self, row: uint) -> $tv { + let mut res = Zero::zero::<$tv>(); + + for (i, e) in res.mut_iter().enumerate() { + *e = self.at((row, i)); + } + + res + } + } + ) +) + macro_rules! mul_impl( ($t: ident, $dim: expr) => ( impl Mul<$t, $t> for $t { diff --git a/src/mat_spec.rs b/src/mat_spec.rs index ae1748e9..a3e7453a 100644 --- a/src/mat_spec.rs +++ b/src/mat_spec.rs @@ -1,6 +1,8 @@ use std::num::{Zero, One}; +use vec::Vec3; use mat::{Mat1, Mat2, Mat3}; use traits::inv::Inv; +use traits::row::Row; // some specializations: impl @@ -106,3 +108,38 @@ Inv for Mat3 { } } } + +impl Row> for Mat3 { + #[inline] + fn row(&self, i: uint) -> Vec3 { + 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) { + 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.") + + } + } +} diff --git a/src/nalgebra.rc b/src/nalgebra.rc index 1e0adecf..3b0dfe64 100644 --- a/src/nalgebra.rc +++ b/src/nalgebra.rc @@ -52,6 +52,7 @@ pub mod traits pub mod sample; pub mod indexable; pub mod column; + pub mod row; pub mod iterable; pub mod outer; pub mod cross; diff --git a/src/traits/cross.rs b/src/traits/cross.rs index 2e76b5c0..af61e6a6 100644 --- a/src/traits/cross.rs +++ b/src/traits/cross.rs @@ -1,8 +1,16 @@ /** * Trait of elements having a cross product. */ -pub trait Cross -{ +pub trait Cross { /// 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 { + /// 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; } diff --git a/src/traits/row.rs b/src/traits/row.rs new file mode 100644 index 00000000..8e84250e --- /dev/null +++ b/src/traits/row.rs @@ -0,0 +1,7 @@ +/// Traits to access rows of a matrix or vector. +pub trait Row { + /// 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); +} diff --git a/src/vec_spec.rs b/src/vec_spec.rs index a35c1b4e..e2995857 100644 --- a/src/vec_spec.rs +++ b/src/vec_spec.rs @@ -1,10 +1,12 @@ use std::num::{Zero, One}; use traits::basis::Basis; -use traits::cross::Cross; +use traits::cross::{Cross, CrossMatrix}; use traits::sample::UniformSphereSample; use traits::vec_cast::VecCast; use traits::vector::{AlgebraicVec}; +use traits::row::Row; use vec::{Vec1, Vec2, Vec3}; +use mat::Mat3; impl + Sub> Cross> for Vec2 { #[inline] @@ -13,6 +15,14 @@ impl + Sub> Cross> for Vec2 { } } +// FIXME: instead of returning a Vec2, define a Mat2x1 matrix? +impl + Clone> CrossMatrix> for Vec2 { + #[inline] + fn cross_matrix(&self) -> Vec2 { + Vec2::new(-self.y, self.x.clone()) + } +} + impl + Sub> Cross> for Vec3 { #[inline] fn cross(&self, other : &Vec3) -> Vec3 { @@ -24,6 +34,39 @@ impl + Sub> Cross> for Vec3 { } } +impl + Zero + Clone> CrossMatrix> for Vec3 { + #[inline] + fn cross_matrix(&self) -> Mat3 { + 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 Row> for Vec2 { + #[inline] + fn row(&self, i: uint) -> Vec1 { + 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) { + 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 Basis for Vec1 { #[inline(always)] fn canonical_basis(f: &fn(Vec1) -> bool) {