diff --git a/README.md b/README.md index 22aa58ee..b2fb2cc4 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ nalgebra ======== -**nalgebra** is a n-dimensional linear algebra library written with the rust +**nalgebra** is a _n_-dimensional linear algebra library written with the rust programming language. @@ -15,3 +15,10 @@ If you encounter problems, make sure you have the last version before creating a git clone git://github.com/sebcrozet/nalgebra.git cd nalgebra make + +## Design note +**nalgebra** is mostly written with non-idiomatic rust code. This is mostly because of limitations +of the trait system not allowing (easy) multiple overloading. Those overloading problems ares +worked around by this +[hack](http://smallcultfollowing.com/babysteps/blog/2012/10/04/refining-traits-slash-impls/) +(section _What if I want overloading_). diff --git a/src/adaptors/rotmat.rs b/src/adaptors/rotmat.rs index 4a00766a..a93435a5 100644 --- a/src/adaptors/rotmat.rs +++ b/src/adaptors/rotmat.rs @@ -1,7 +1,6 @@ use std::num::{One, Zero}; use std::rand::{Rand, Rng, RngUtil}; use std::cmp::ApproxEq; -use traits::rlmul::{RMul, LMul}; use traits::cross::Cross; use traits::dim::Dim; use traits::inv::Inv; @@ -15,9 +14,12 @@ use traits::homogeneous::ToHomogeneous; use traits::indexable::Indexable; use traits::norm::Norm; use traits::comp::absolute_rotate::AbsoluteRotate; -use vec::{Vec1, Vec2, Vec3}; +use vec::{Vec1, Vec2, Vec3, Vec2MulRhs, Vec3MulRhs}; use mat::{Mat2, Mat3}; +#[path = "../metal.rs"] +mod metal; + /// Matrix wrapper representing rotation matrix. It is built uppon another matrix and ensures (at /// the type-level) that it will always represent a rotation. Rotation matrices have some /// properties useful for performances, like the fact that the inversion is simply a transposition. @@ -26,6 +28,19 @@ pub struct Rotmat { priv submat: M } +/// Trait of object `o` which can be multiplied by a `Rotmat` `r`: `r * o`. +pub trait RotmatMulRhs { + /// Multiplies a rotation matrix by `Self`. + fn binop(left: &Rotmat, right: &Self) -> Res; +} + +impl, Res> Mul for Rotmat { + #[inline(always)] + fn mul(&self, other: &Rhs) -> Res { + RotmatMulRhs::binop(self, other) + } +} + impl Rotmat { /// Gets a copy of the internal representation of the rotation. pub fn submat(&self) -> M { @@ -229,19 +244,19 @@ impl> Rand for Rotmat> { } } -impl + LMul, V> Rotate for Rotmat { +impl + Mul, V>> Rotate for Rotmat { #[inline] fn rotate(&self, v: &V) -> V { - self.rmul(v) + self * *v } #[inline] fn inv_rotate(&self, v: &V) -> V { - self.lmul(v) + v * *self } } -impl + LMul, V> Transform for Rotmat { +impl + Mul, V>> Transform for Rotmat { #[inline] fn transform(&self, v: &V) -> V { self.rotate(v) @@ -275,24 +290,41 @@ impl One for Rotmat { } } -impl> Mul, Rotmat> for Rotmat { +impl> RotmatMulRhs> for Rotmat { #[inline] - fn mul(&self, other: &Rotmat) -> Rotmat { - Rotmat { submat: self.submat.mul(&other.submat) } + fn binop(left: &Rotmat, right: &Rotmat) -> Rotmat { + Rotmat { submat: left.submat * right.submat } } } -impl> RMul for Rotmat { +/* + * Right/Left multiplication implementation for Vec3 and Vec2. + */ +impl, Vec3>, N> RotmatMulRhs> for Vec3 { #[inline] - fn rmul(&self, other: &V) -> V { - self.submat.rmul(other) + fn binop(left: &Rotmat, right: &Vec3) -> Vec3 { + left.submat * *right } } -impl> LMul for Rotmat { +impl, Vec2>, N> RotmatMulRhs> for Vec2 { #[inline] - fn lmul(&self, other: &V) -> V { - self.submat.lmul(other) + fn binop(left: &Rotmat, right: &Vec2) -> Vec2 { + left.submat * *right + } +} + +impl>> Vec3MulRhs> for Rotmat { + #[inline] + fn binop(left: &Vec3, right: &Rotmat) -> Vec3 { + *left * right.submat + } +} + +impl>> Vec2MulRhs> for Rotmat { + #[inline] + fn binop(left: &Vec2, right: &Rotmat) -> Vec2 { + *left * right.submat } } diff --git a/src/adaptors/transform.rs b/src/adaptors/transform.rs index ec31f7ef..da445c2a 100644 --- a/src/adaptors/transform.rs +++ b/src/adaptors/transform.rs @@ -9,12 +9,12 @@ use traits::rotation::{Rotation, Rotate, RotationMatrix}; use traits::translation::{Translation, Translate}; use Ts = traits::transformation::Transform; use traits::transformation::{Transformation}; -use traits::rlmul::{RMul, LMul}; +use traits::rlmul::RMul; use traits::homogeneous::{ToHomogeneous, FromHomogeneous}; use traits::column::Column; use traits::comp::absolute_rotate::AbsoluteRotate; use adaptors::rotmat::Rotmat; -use vec::Vec3; +use vec::{Vec2, Vec3, Vec2MulRhs, Vec3MulRhs}; use mat::Mat3; /// Matrix-Vector wrapper used to represent a matrix multiplication followed by a translation. @@ -42,6 +42,19 @@ impl Transform { } } +/// Trait of object `o` which can be multiplied by a `Transform` `t`: `t * o`. +pub trait TransformMulRhs { + /// Multiplies a transformation matrix by `Self`. + fn binop(left: &Transform, right: &Self) -> Res; +} + +impl, Res> Mul for Transform { + #[inline(always)] + fn mul(&self, other: &Rhs) -> Res { + TransformMulRhs::binop(self, other) + } +} + impl Transform { /// Gets a copy of the internal matrix. #[inline] @@ -125,28 +138,45 @@ impl Zero for Transform { } } -impl + Mul, V: Add> -Mul, Transform> for Transform { +impl + Mul, V: Add> TransformMulRhs> for Transform { #[inline] - fn mul(&self, other: &Transform) -> Transform { + fn binop(left: &Transform, right: &Transform) -> Transform { Transform { - submat: self.submat * other.submat, - subtrans: self.subtrans + self.submat.rmul(&other.subtrans) + submat: left.submat * right.submat, + subtrans: left.subtrans + left.submat.rmul(&right.subtrans) } } } -impl, V: Add> RMul for Transform { +impl, M: Mul, Vec2>> +TransformMulRhs, M, Vec2> for Vec2 { #[inline] - fn rmul(&self, other: &V) -> V { - self.submat.rmul(other) + self.subtrans + fn binop(left: &Transform, M>, right: &Vec2) -> Vec2 { + left.subtrans + left.submat * *right } } -impl, V: Add> LMul for Transform { +impl, M: Mul, Vec3>> +TransformMulRhs, M, Vec3> for Vec3 { #[inline] - fn lmul(&self, other: &V) -> V { - self.submat.lmul(other) + self.subtrans + fn binop(left: &Transform, M>, right: &Vec3) -> Vec3 { + left.subtrans + left.submat * *right + } +} + +impl, M: Vec2MulRhs>> +Vec2MulRhs> for Transform, M> { + #[inline] + fn binop(left: &Vec2, right: &Transform, M>) -> Vec2 { + (left + right.subtrans) * right.submat + } +} + +impl, M: Vec3MulRhs>> +Vec3MulRhs> for Transform, M> { + #[inline] + fn binop(left: &Vec3, right: &Transform, M>) -> Vec3 { + (left + right.subtrans) * right.submat } } diff --git a/src/bench/mat.rs b/src/bench/mat.rs index e2ff6486..ac0b9e8c 100644 --- a/src/bench/mat.rs +++ b/src/bench/mat.rs @@ -91,7 +91,7 @@ macro_rules! bench_mul_mat_vec( do $bh.iter { do 1000.times { - v = m.rmul(&v) + v = m * v } } } @@ -131,7 +131,7 @@ macro_rules! bench_mul_dmat_dvec( do $bh.iter { do 1000.times { - v = m.rmul(&v) + v = m * v } } } diff --git a/src/dmat.rs b/src/dmat.rs index ae1edfd7..9d252b8a 100644 --- a/src/dmat.rs +++ b/src/dmat.rs @@ -4,10 +4,9 @@ use std::num::{One, Zero}; use std::vec; use std::cmp::ApproxEq; use std::util; +use dvec::{DVec, DVecMulRhs}; use traits::inv::Inv; use traits::transpose::Transpose; -use traits::rlmul::{RMul, LMul}; -use dvec::DVec; /// Matrix with dimensions unknown at compile-time. #[deriving(Eq, ToStr, Clone)] @@ -17,6 +16,19 @@ pub struct DMat { priv mij: ~[N] } +/// Trait of object `o` which can be multiplied by a `DMat` `d`: `d * o`. +pub trait DMatMulRhs { + /// Multiplies a `DMat` by `Self`. + fn binop(left: &DMat, right: &Self) -> Res; +} + +impl, Res> Mul for DMat { + #[inline(always)] + fn mul(&self, other: &Rhs) -> Res { + DMatMulRhs::binop(self, other) + } +} + impl DMat { /// Creates an uninitialized matrix. #[inline] @@ -160,19 +172,19 @@ impl DMat { } } -impl + Add + Zero> Mul, DMat> for DMat { - fn mul(&self, other: &DMat) -> DMat { - assert!(self.ncols == other.nrows); +impl + Add + Zero> DMatMulRhs> for DMat { + fn binop(left: &DMat, right: &DMat) -> DMat { + assert!(left.ncols == right.nrows); - let mut res = unsafe { DMat::new_uninitialized(self.nrows, other.ncols) }; + let mut res = unsafe { DMat::new_uninitialized(left.nrows, right.ncols) }; - for i in range(0u, self.nrows) { - for j in range(0u, other.ncols) { + for i in range(0u, left.nrows) { + for j in range(0u, right.ncols) { let mut acc: N = Zero::zero(); - for k in range(0u, self.ncols) { + for k in range(0u, left.ncols) { unsafe { - acc = acc + self.at_fast(i, k) * other.at_fast(k, j); + acc = acc + left.at_fast(i, k) * right.at_fast(k, j); } } @@ -185,18 +197,18 @@ impl + Add + Zero> Mul, DMat> for DMat } impl + Mul + Zero> -RMul> for DMat { - fn rmul(&self, other: &DVec) -> DVec { - assert!(self.ncols == other.at.len()); +DMatMulRhs> for DVec { + fn binop(left: &DMat, right: &DVec) -> DVec { + assert!(left.ncols == right.at.len()); - let mut res : DVec = unsafe { DVec::new_uninitialized(self.nrows) }; + let mut res : DVec = unsafe { DVec::new_uninitialized(left.nrows) }; - for i in range(0u, self.nrows) { + for i in range(0u, left.nrows) { let mut acc: N = Zero::zero(); - for j in range(0u, self.ncols) { + for j in range(0u, left.ncols) { unsafe { - acc = acc + other.at_fast(j) * self.at_fast(i, j); + acc = acc + left.at_fast(i, j) * right.at_fast(j); } } @@ -207,19 +219,20 @@ RMul> for DMat { } } + impl + Mul + Zero> -LMul> for DMat { - fn lmul(&self, other: &DVec) -> DVec { - assert!(self.nrows == other.at.len()); +DVecMulRhs> for DMat { + fn binop(left: &DVec, right: &DMat) -> DVec { + assert!(right.nrows == left.at.len()); - let mut res : DVec = unsafe { DVec::new_uninitialized(self.ncols) }; + let mut res : DVec = unsafe { DVec::new_uninitialized(right.ncols) }; - for i in range(0u, self.ncols) { + for i in range(0u, right.ncols) { let mut acc: N = Zero::zero(); - for j in range(0u, self.nrows) { + for j in range(0u, right.nrows) { unsafe { - acc = acc + other.at_fast(j) * self.at_fast(j, i); + acc = acc + left.at_fast(j) * right.at_fast(j, i); } } diff --git a/src/dvec.rs b/src/dvec.rs index c011fe05..d8dc7888 100644 --- a/src/dvec.rs +++ b/src/dvec.rs @@ -1,3 +1,5 @@ +#[doc(hidden)]; // we hide doc to not have to document the $trhs double dispatch trait. + use std::num::{Zero, One, Algebraic}; use std::rand::Rand; use std::rand; @@ -10,6 +12,8 @@ use traits::norm::Norm; use traits::iterable::{Iterable, IterableMut}; use traits::translation::Translation; +mod metal; + /// Vector with a dimension unknown at compile-time. #[deriving(Eq, ToStr, Clone)] pub struct DVec { @@ -17,6 +21,16 @@ pub struct DVec { at: ~[N] } +double_dispatch_binop_decl_trait!(DVec, DVecMulRhs) +double_dispatch_binop_decl_trait!(DVec, DVecDivRhs) +double_dispatch_binop_decl_trait!(DVec, DVecAddRhs) +double_dispatch_binop_decl_trait!(DVec, DVecSubRhs) + +mul_redispatch_impl!(DVec, DVecMulRhs) +div_redispatch_impl!(DVec, DVecDivRhs) +add_redispatch_impl!(DVec, DVecAddRhs) +sub_redispatch_impl!(DVec, DVecSubRhs) + impl DVec { /// Builds a vector filled with zeros. /// @@ -123,7 +137,7 @@ impl FromIterator for DVec { } } -impl> DVec { +impl + DVecMulRhs>> DVec { /// 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 exept one which is equal /// to 1.0. @@ -177,22 +191,22 @@ impl> DVec { } } -impl> Add, DVec> for DVec { +impl> DVecAddRhs> for DVec { #[inline] - fn add(&self, other: &DVec) -> DVec { - assert!(self.at.len() == other.at.len()); + fn binop(left: &DVec, right: &DVec) -> DVec { + assert!(left.at.len() == right.at.len()); DVec { - at: self.at.iter().zip(other.at.iter()).map(|(a, b)| *a + *b).collect() + at: left.at.iter().zip(right.at.iter()).map(|(a, b)| *a + *b).collect() } } } -impl> Sub, DVec> for DVec { +impl> DVecSubRhs> for DVec { #[inline] - fn sub(&self, other: &DVec) -> DVec { - assert!(self.at.len() == other.at.len()); + fn binop(left: &DVec, right: &DVec) -> DVec { + assert!(left.at.len() == right.at.len()); DVec { - at: self.at.iter().zip(other.at.iter()).map(|(a, b)| *a - *b).collect() + at: left.at.iter().zip(right.at.iter()).map(|(a, b)| *a - *b).collect() } } } @@ -230,21 +244,6 @@ impl Dot for DVec { } } -impl> Mul> for DVec { - #[inline] - fn mul(&self, s: &N) -> DVec { - DVec { at: self.at.iter().map(|a| a * *s).collect() } - } -} - - -impl> Div> for DVec { - #[inline] - fn div(&self, s: &N) -> DVec { - DVec { at: self.at.iter().map(|a| a / *s).collect() } - } -} - impl + Neg + Clone> Translation> for DVec { #[inline] fn translation(&self) -> DVec { @@ -331,3 +330,103 @@ impl> ApproxEq for DVec { } } } + +macro_rules! scalar_mul_impl ( + ($n: ident) => ( + impl DVecMulRhs<$n, DVec<$n>> for $n { + #[inline] + fn binop(left: &DVec<$n>, right: &$n) -> DVec<$n> { + DVec { at: left.at.iter().map(|a| a * *right).collect() } + } + } + ) +) + +macro_rules! scalar_div_impl ( + ($n: ident) => ( + impl DVecDivRhs<$n, DVec<$n>> for $n { + #[inline] + fn binop(left: &DVec<$n>, right: &$n) -> DVec<$n> { + DVec { at: left.at.iter().map(|a| a / *right).collect() } + } + } + ) +) + +macro_rules! scalar_add_impl ( + ($n: ident) => ( + impl DVecAddRhs<$n, DVec<$n>> for $n { + #[inline] + fn binop(left: &DVec<$n>, right: &$n) -> DVec<$n> { + DVec { at: left.at.iter().map(|a| a + *right).collect() } + } + } + ) +) + +macro_rules! scalar_sub_impl ( + ($n: ident) => ( + impl DVecSubRhs<$n, DVec<$n>> for $n { + #[inline] + fn binop(left: &DVec<$n>, right: &$n) -> DVec<$n> { + DVec { at: left.at.iter().map(|a| a - *right).collect() } + } + } + ) +) + +scalar_mul_impl!(f64) +scalar_mul_impl!(f32) +scalar_mul_impl!(u64) +scalar_mul_impl!(u32) +scalar_mul_impl!(u16) +scalar_mul_impl!(u8) +scalar_mul_impl!(i64) +scalar_mul_impl!(i32) +scalar_mul_impl!(i16) +scalar_mul_impl!(i8) +scalar_mul_impl!(float) +scalar_mul_impl!(uint) +scalar_mul_impl!(int) + +scalar_div_impl!(f64) +scalar_div_impl!(f32) +scalar_div_impl!(u64) +scalar_div_impl!(u32) +scalar_div_impl!(u16) +scalar_div_impl!(u8) +scalar_div_impl!(i64) +scalar_div_impl!(i32) +scalar_div_impl!(i16) +scalar_div_impl!(i8) +scalar_div_impl!(float) +scalar_div_impl!(uint) +scalar_div_impl!(int) + +scalar_add_impl!(f64) +scalar_add_impl!(f32) +scalar_add_impl!(u64) +scalar_add_impl!(u32) +scalar_add_impl!(u16) +scalar_add_impl!(u8) +scalar_add_impl!(i64) +scalar_add_impl!(i32) +scalar_add_impl!(i16) +scalar_add_impl!(i8) +scalar_add_impl!(float) +scalar_add_impl!(uint) +scalar_add_impl!(int) + +scalar_sub_impl!(f64) +scalar_sub_impl!(f32) +scalar_sub_impl!(u64) +scalar_sub_impl!(u32) +scalar_sub_impl!(u16) +scalar_sub_impl!(u8) +scalar_sub_impl!(i64) +scalar_sub_impl!(i32) +scalar_sub_impl!(i16) +scalar_sub_impl!(i8) +scalar_sub_impl!(float) +scalar_sub_impl!(uint) +scalar_sub_impl!(int) diff --git a/src/identity_spec.rs b/src/identity_spec.rs index e68a0bf9..6404614c 100644 --- a/src/identity_spec.rs +++ b/src/identity_spec.rs @@ -2,7 +2,6 @@ use std::num::{One, Zero}; use mat; use traits::inv::Inv; use traits::transpose::Transpose; -use traits::rlmul::{RMul, LMul}; use traits::translation::{Translation, Translate}; use traits::rotation::{Rotation, Rotate}; use traits::transformation::{Transformation, Transform}; @@ -24,21 +23,9 @@ impl Inv for mat::Identity { } } -impl RMul for mat::Identity { - fn rmul(&self, m: &M) -> M { - m.clone() - } -} - -impl LMul for mat::Identity { - fn lmul(&self, m: &M) -> M { - m.clone() - } -} - -impl Mul for mat::Identity { +impl Mul for mat::Identity { #[inline] - fn mul(&self, other: &M) -> M { + fn mul(&self, other: &T) -> T { other.clone() } } diff --git a/src/mat.rs b/src/mat.rs index 4e7abdd4..fbbc0953 100644 --- a/src/mat.rs +++ b/src/mat.rs @@ -4,7 +4,7 @@ use std::cast; use std::num::{One, Zero}; use std::cmp::ApproxEq; use std::vec::{VecIterator, VecMutIterator}; -use vec::{Vec1, Vec2, Vec3, Vec4, Vec5, Vec6, Outer}; +use vec::*; // traits pub use traits::mat::Mat; @@ -16,7 +16,7 @@ pub use traits::scalar_op::{ScalarSub, ScalarAdd}; pub use traits::mat_cast::MatCast; pub use traits::column::Column; pub use traits::inv::Inv; -pub use traits::rlmul::{RMul, LMul}; +pub use traits::rlmul::RMul; pub use traits::rotation::{Rotation, RotationMatrix, Rotate}; pub use traits::transformation::{Transformation, Transform}; pub use traits::translation::{Translation, Translate}; @@ -132,8 +132,8 @@ at_fast_impl!(Mat1, 1) dim_impl!(Mat1, 1) indexable_impl!(Mat1, 1) mat_mul_mat_impl!(Mat1, Mat1MulRhs, 1) -rmul_impl!(Mat1, Vec1, 1) -vec_mul_mat_impl!(Mat1, Vec1, Mat1MulRhs, 1) +mat_mul_vec_impl!(Mat1, Vec1, Mat1MulRhs, 1) +vec_mul_mat_impl!(Mat1, Vec1, Vec1MulRhs, 1) transform_impl!(Mat1, Vec1) // (specialized) inv_impl!(Mat1, 1) transpose_impl!(Mat1, 1) @@ -519,8 +519,8 @@ dim_impl!(Mat4, 4) indexable_impl!(Mat4, 4) at_fast_impl!(Mat4, 4) mat_mul_mat_impl!(Mat4, Mat4MulRhs, 4) -rmul_impl!(Mat4, Vec4, 4) -vec_mul_mat_impl!(Mat4, Vec4, Mat4MulRhs, 4) +mat_mul_vec_impl!(Mat4, Vec4, Mat4MulRhs, 4) +vec_mul_mat_impl!(Mat4, Vec4, Vec4MulRhs, 4) transform_impl!(Mat4, Vec4) inv_impl!(Mat4, 4) transpose_impl!(Mat4, 4) @@ -706,8 +706,8 @@ dim_impl!(Mat5, 5) indexable_impl!(Mat5, 5) at_fast_impl!(Mat5, 5) mat_mul_mat_impl!(Mat5, Mat5MulRhs, 5) -rmul_impl!(Mat5, Vec5, 5) -vec_mul_mat_impl!(Mat5, Vec5, Mat5MulRhs, 5) +mat_mul_vec_impl!(Mat5, Vec5, Mat5MulRhs, 5) +vec_mul_mat_impl!(Mat5, Vec5, Vec5MulRhs, 5) transform_impl!(Mat5, Vec5) inv_impl!(Mat5, 5) transpose_impl!(Mat5, 5) @@ -949,8 +949,8 @@ dim_impl!(Mat6, 6) indexable_impl!(Mat6, 6) at_fast_impl!(Mat6, 6) mat_mul_mat_impl!(Mat6, Mat6MulRhs, 6) -rmul_impl!(Mat6, Vec6, 6) -vec_mul_mat_impl!(Mat6, Vec6, Mat6MulRhs, 6) +mat_mul_vec_impl!(Mat6, Vec6, Mat6MulRhs, 6) +vec_mul_mat_impl!(Mat6, Vec6, Vec6MulRhs, 6) transform_impl!(Mat6, Vec6) inv_impl!(Mat6, 6) transpose_impl!(Mat6, 6) diff --git a/src/mat_macros.rs b/src/mat_macros.rs index b1dee487..022b444c 100644 --- a/src/mat_macros.rs +++ b/src/mat_macros.rs @@ -47,8 +47,8 @@ macro_rules! add_impl( ($t: ident, $trhs: ident, $comp0: ident $(,$compN: ident)*) => ( impl> $trhs> for $t { #[inline] - fn $trhs(&self, other: &$t) -> $t { - $t::new(self.$comp0 + other.$comp0 $(, self.$compN + other.$compN)*) + fn binop(left: &$t, right: &$t) -> $t { + $t::new(left.$comp0 + right.$comp0 $(, left.$compN + right.$compN)*) } } ) @@ -58,8 +58,8 @@ macro_rules! sub_impl( ($t: ident, $trhs: ident, $comp0: ident $(,$compN: ident)*) => ( impl> $trhs> for $t { #[inline] - fn $trhs(&self, other: &$t) -> $t { - $t::new(other.$comp0 - self.$comp0 $(, other.$compN - self.$compN)*) + fn binop(left: &$t, right: &$t) -> $t { + $t::new(left.$comp0 - right.$comp0 $(, left.$compN - right.$compN)*) } } ) @@ -69,8 +69,8 @@ macro_rules! scalar_mul_impl( ($t: ident, $n: ident, $trhs: ident, $comp0: ident $(,$compN: ident)*) => ( impl $trhs<$n, $t<$n>> for $n { #[inline] - fn $trhs(&self, s: &$t<$n>) -> $t<$n> { - $t::new(s.$comp0 * *self $(, s.$compN * *self)*) + fn binop(left: &$t<$n>, right: &$n) -> $t<$n> { + $t::new(left.$comp0 * *right $(, left.$compN * *right)*) } } ) @@ -80,8 +80,8 @@ macro_rules! scalar_div_impl( ($t: ident, $n: ident, $trhs: ident, $comp0: ident $(,$compN: ident)*) => ( impl $trhs<$n, $t<$n>> for $n { #[inline] - fn $trhs(&self, s: &$t<$n>) -> $t<$n> { - $t::new(s.$comp0 / *self $(, s.$compN / *self)*) + fn binop(left: &$t<$n>, right: &$n) -> $t<$n> { + $t::new(left.$comp0 / *right $(, left.$compN / *right)*) } } ) @@ -91,8 +91,8 @@ macro_rules! scalar_add_impl( ($t: ident, $n: ident, $trhs: ident, $comp0: ident $(,$compN: ident)*) => ( impl $trhs<$n, $t<$n>> for $n { #[inline] - fn $trhs(&self, s: &$t<$n>) -> $t<$n> { - $t::new(s.$comp0 + *self $(, s.$compN + *self)*) + fn binop(left: &$t<$n>, right: &$n) -> $t<$n> { + $t::new(left.$comp0 + *right $(, left.$compN + *right)*) } } ) @@ -102,8 +102,8 @@ macro_rules! scalar_sub_impl( ($t: ident, $n: ident, $trhs: ident, $comp0: ident $(,$compN: ident)*) => ( impl $trhs<$n, $t<$n>> for $n { #[inline] - fn $trhs(&self, s: &$t<$n>) -> $t<$n> { - $t::new(s.$comp0 - *self $(, s.$compN - *self)*) + fn binop(left: &$t<$n>, right: &$n) -> $t<$n> { + $t::new(left.$comp0 - *right $(, left.$compN - *right)*) } } ) @@ -282,7 +282,7 @@ macro_rules! mat_mul_mat_impl( ($t: ident, $trhs: ident, $dim: expr) => ( impl $trhs> for $t { #[inline] - fn $trhs(&self, other: &$t) -> $t { + fn binop(left: &$t, right: &$t) -> $t { // careful! we need to comute other * self here (self is the rhs). let mut res: $t = Zero::zero(); @@ -292,7 +292,7 @@ macro_rules! mat_mul_mat_impl( unsafe { for k in range(0u, $dim) { - acc = acc + other.at_fast((i, k)) * self.at_fast((k, j)); + acc = acc + left.at_fast((i, k)) * right.at_fast((k, j)); } res.set_fast((i, j), acc); @@ -306,17 +306,17 @@ macro_rules! mat_mul_mat_impl( ) ) -macro_rules! rmul_impl( - ($t: ident, $v: ident, $dim: expr) => ( - impl RMul<$v> for $t { +macro_rules! vec_mul_mat_impl( + ($t: ident, $v: ident, $trhs: ident, $dim: expr) => ( + impl $trhs> for $t { #[inline] - fn rmul(&self, other: &$v) -> $v { + fn binop(left: &$v, right: &$t) -> $v { let mut res : $v = Zero::zero(); for i in range(0u, $dim) { for j in range(0u, $dim) { unsafe { - let val = res.at_fast(i) + other.at_fast(j) * self.at_fast((i, j)); + let val = res.at_fast(i) + left.at_fast(j) * right.at_fast((j, i)); res.set_fast(i, val) } } @@ -328,17 +328,17 @@ macro_rules! rmul_impl( ) ) -macro_rules! vec_mul_mat_impl( +macro_rules! mat_mul_vec_impl( ($t: ident, $v: ident, $trhs: ident, $dim: expr) => ( impl $trhs> for $v { #[inline] - fn $trhs(&self, other: &$t) -> $v { + fn binop(left: &$t, right: &$v) -> $v { let mut res : $v = Zero::zero(); for i in range(0u, $dim) { for j in range(0u, $dim) { unsafe { - let val = self.at_fast(i) + self.at_fast(j) * other.at_fast((j, i)); + let val = res.at_fast(i) + left.at_fast((i, j)) * right.at_fast(j); res.set_fast(i, val) } } diff --git a/src/mat_spec.rs b/src/mat_spec.rs index 55872e06..dd05979e 100644 --- a/src/mat_spec.rs +++ b/src/mat_spec.rs @@ -1,6 +1,6 @@ use std::num::{Zero, One}; -use vec::{Vec2, Vec3}; -use mat::{Mat1, Mat2, Mat3, Inv, Row, Col, RMul, LMul, Mat3MulRhs, Mat2MulRhs}; +use vec::{Vec2, Vec3, Vec2MulRhs, Vec3MulRhs}; +use mat::{Mat1, Mat2, Mat3, Inv, Row, Col, Mat3MulRhs, Mat2MulRhs}; use mat; // some specializations: @@ -191,74 +191,74 @@ impl Col> for Mat3 { impl + Add> Mat3MulRhs> for Mat3 { #[inline] - fn Mat3MulRhs(&self, other: &Mat3) -> Mat3 { + fn binop(left: &Mat3, right: &Mat3) -> Mat3 { Mat3::new( - other.m11 * self.m11 + other.m12 * self.m21 + other.m13 * self.m31, - other.m11 * self.m12 + other.m12 * self.m22 + other.m13 * self.m32, - other.m11 * self.m13 + other.m12 * self.m23 + other.m13 * self.m33, + left.m11 * right.m11 + left.m12 * right.m21 + left.m13 * right.m31, + left.m11 * right.m12 + left.m12 * right.m22 + left.m13 * right.m32, + left.m11 * right.m13 + left.m12 * right.m23 + left.m13 * right.m33, - other.m21 * self.m11 + other.m22 * self.m21 + other.m23 * self.m31, - other.m21 * self.m12 + other.m22 * self.m22 + other.m23 * self.m32, - other.m21 * self.m13 + other.m22 * self.m23 + other.m23 * self.m33, + left.m21 * right.m11 + left.m22 * right.m21 + left.m23 * right.m31, + left.m21 * right.m12 + left.m22 * right.m22 + left.m23 * right.m32, + left.m21 * right.m13 + left.m22 * right.m23 + left.m23 * right.m33, - other.m31 * self.m11 + other.m32 * self.m21 + other.m33 * self.m31, - other.m31 * self.m12 + other.m32 * self.m22 + other.m33 * self.m32, - other.m31 * self.m13 + other.m32 * self.m23 + other.m33 * self.m33 + left.m31 * right.m11 + left.m32 * right.m21 + left.m33 * right.m31, + left.m31 * right.m12 + left.m32 * right.m22 + left.m33 * right.m32, + left.m31 * right.m13 + left.m32 * right.m23 + left.m33 * right.m33 ) } } impl + Add> Mat2MulRhs> for Mat2 { #[inline(always)] - fn Mat2MulRhs(&self, other: &Mat2) -> Mat2 { + fn binop(left: &Mat2, right: &Mat2) -> Mat2 { Mat2::new( - other.m11 * self.m11 + other.m12 * self.m21, - other.m11 * self.m12 + other.m12 * self.m22, + left.m11 * right.m11 + left.m12 * right.m21, + left.m11 * right.m12 + left.m12 * right.m22, - other.m21 * self.m11 + other.m22 * self.m21, - other.m21 * self.m12 + other.m22 * self.m22 + left.m21 * right.m11 + left.m22 * right.m21, + left.m21 * right.m12 + left.m22 * right.m22 ) } } -impl + Add> RMul> for Mat3 { +impl + Add> Mat3MulRhs> for Vec3 { #[inline(always)] - fn rmul(&self, v: &Vec3) -> Vec3 { + fn binop(left: &Mat3, right: &Vec3) -> Vec3 { Vec3::new( - self.m11 * v.x + self.m12 * v.y + self.m13 * v.z, - self.m21 * v.x + self.m22 * v.y + self.m23 * v.z, - self.m31 * v.x + self.m32 * v.y + self.m33 * v.z + left.m11 * right.x + left.m12 * right.y + left.m13 * right.z, + left.m21 * right.x + left.m22 * right.y + left.m23 * right.z, + left.m31 * right.x + left.m32 * right.y + left.m33 * right.z ) } } -impl + Add> LMul> for Mat3 { +impl + Add> Vec3MulRhs> for Mat3 { #[inline(always)] - fn lmul(&self, v: &Vec3) -> Vec3 { + fn binop(left: &Vec3, right: &Mat3) -> Vec3 { Vec3::new( - self.m11 * v.x + self.m21 * v.y + self.m31 * v.z, - self.m12 * v.x + self.m22 * v.y + self.m32 * v.z, - self.m13 * v.x + self.m23 * v.y + self.m33 * v.z + left.x * right.m11 + left.y * right.m21 + left.z * right.m31, + left.x * right.m12 + left.y * right.m22 + left.z * right.m32, + left.x * right.m13 + left.y * right.m23 + left.z * right.m33 ) } } -impl + Add> RMul> for Mat2 { +impl + Add> Vec2MulRhs> for Mat2 { #[inline(always)] - fn rmul(&self, v: &Vec2) -> Vec2 { + fn binop(left: &Vec2, right: &Mat2) -> Vec2 { Vec2::new( - self.m11 * v.x + self.m12 * v.y, - self.m21 * v.x + self.m22 * v.y + left.x * right.m11 + left.y * right.m21, + left.x * right.m12 + left.y * right.m22 ) } } -impl + Add> LMul> for Mat2 { +impl + Add> Mat2MulRhs> for Vec2 { #[inline(always)] - fn lmul(&self, v: &Vec2) -> Vec2 { + fn binop(left: &Mat2, right: &Vec2) -> Vec2 { Vec2::new( - self.m11 * v.x + self.m21 * v.y, - self.m12 * v.x + self.m22 * v.y + left.m11 * right.x + left.m21 * right.y, + left.m12 * right.x + left.m22 * right.y ) } } diff --git a/src/metal.rs b/src/metal.rs index a0de3436..3e179e39 100644 --- a/src/metal.rs +++ b/src/metal.rs @@ -8,55 +8,55 @@ macro_rules! double_dispatch_binop_decl_trait( ($t: ident, $trhs: ident) => ( pub trait $trhs { - fn $trhs(&self, other: &$t) -> Res; + fn binop(left: &$t, right: &Self) -> Res; } ) ) // Macro driving the `Mul` trait to use the related trait for double redispatch. macro_rules! mul_redispatch_impl( - ($t: ident, $trhs: ident) => ( - impl, Res> Mul for $t { - #[inline(always)] - fn mul(&self, other: &Rhs) -> Res { - other.$trhs(self) + ($t: ident, $trhs: ident) => ( + impl, Res> Mul for $t { + #[inline(always)] + fn mul(&self, other: &Rhs) -> Res { + $trhs::binop(self, other) + } } - } - ) + ) ) // Macro driving the `Div` trait to use the related trait for double redispatch. macro_rules! div_redispatch_impl( - ($t: ident, $trhs: ident) => ( - impl, Res> Div for $t { - #[inline(always)] - fn div(&self, other: &Rhs) -> Res { - other.$trhs(self) + ($t: ident, $trhs: ident) => ( + impl, Res> Div for $t { + #[inline(always)] + fn div(&self, other: &Rhs) -> Res { + $trhs::binop(self, other) + } } - } - ) + ) ) -// Macro driving the `Div` trait to use the related trait for double redispatch. +// Macro driving the `Add` trait to use the related trait for double redispatch. macro_rules! add_redispatch_impl( - ($t: ident, $trhs: ident) => ( - impl, Res> Add for $t { - #[inline(always)] - fn add(&self, other: &Rhs) -> Res { - other.$trhs(self) + ($t: ident, $trhs: ident) => ( + impl, Res> Add for $t { + #[inline(always)] + fn add(&self, other: &Rhs) -> Res { + $trhs::binop(self, other) + } } - } - ) + ) ) -// Macro driving the `Div` trait to use the related trait for double redispatch. +// Macro driving the `Sub` trait to use the related trait for double redispatch. macro_rules! sub_redispatch_impl( - ($t: ident, $trhs: ident) => ( - impl, Res> Sub for $t { - #[inline(always)] - fn sub(&self, other: &Rhs) -> Res { - other.$trhs(self) + ($t: ident, $trhs: ident) => ( + impl, Res> Sub for $t { + #[inline(always)] + fn sub(&self, other: &Rhs) -> Res { + $trhs::binop(self, other) + } } - } - ) + ) ) diff --git a/src/traits/rlmul.rs b/src/traits/rlmul.rs index a6685039..b666719d 100644 --- a/src/traits/rlmul.rs +++ b/src/traits/rlmul.rs @@ -1,3 +1,11 @@ +// XXX: those traits should not exist since there is generalized operator overloading of Add and +// Sub. +// However, using the same trait multiple time as a trait bound (ex: impl + Add) +// does not work properly, mainly because the way we are doing generalized operator overloading is +// verry hacky. +// +// Hopefully, this will be fixed on a future version of the language! + /** * Trait of objects having a right multiplication with another element. */ @@ -6,6 +14,12 @@ pub trait RMul { fn rmul(&self, v: &V) -> V; } +impl, T> RMul for M { + fn rmul(&self, v: &T) -> T { + self * *v + } +} + /** * Trait of objects having a left multiplication with another element. */ @@ -13,3 +27,9 @@ pub trait LMul { /// Computes v * self fn lmul(&self, &V) -> V; } + +impl, M> LMul for M { + fn lmul(&self, v: &T) -> T { + v * *self + } +} diff --git a/src/traits/scalar_op.rs b/src/traits/scalar_op.rs index e6e15506..bb4dca5d 100644 --- a/src/traits/scalar_op.rs +++ b/src/traits/scalar_op.rs @@ -4,7 +4,7 @@ // does not work properly, mainly because the way we are doing generalized operator overloading is // verry hacky. // -// Hopefull, this will be fixed on the future. +// Hopefully, this will be fixed on a future version of the language! /** * Trait of objects having an addition with a scalar. diff --git a/src/vec_macros.rs b/src/vec_macros.rs index 62333f01..9caea5c7 100644 --- a/src/vec_macros.rs +++ b/src/vec_macros.rs @@ -269,8 +269,8 @@ macro_rules! add_impl( ($t: ident, $trhs: ident, $comp0: ident $(,$compN: ident)*) => ( impl> $trhs> for $t { #[inline] - fn $trhs(&self, other: &$t) -> $t { - $t::new(self.$comp0 + other.$comp0 $(, self.$compN + other.$compN)*) + fn binop(left: &$t, right: &$t) -> $t { + $t::new(left.$comp0 + right.$comp0 $(, left.$compN + right.$compN)*) } } ) @@ -280,8 +280,8 @@ macro_rules! sub_impl( ($t: ident, $trhs: ident, $comp0: ident $(,$compN: ident)*) => ( impl> $trhs> for $t { #[inline] - fn $trhs(&self, other: &$t) -> $t { - $t::new(other.$comp0 - self.$comp0 $(, other.$compN - self.$compN)*) + fn binop(left: &$t, right: &$t) -> $t { + $t::new(left.$comp0 - right.$comp0 $(, left.$compN - right.$compN)*) } } ) @@ -318,8 +318,8 @@ macro_rules! scalar_mul_impl( ($t: ident, $n: ident, $trhs: ident, $comp0: ident $(,$compN: ident)*) => ( impl $trhs<$n, $t<$n>> for $n { #[inline] - fn $trhs(&self, s: &$t<$n>) -> $t<$n> { - $t::new(s.$comp0 * *self $(, s.$compN * *self)*) + fn binop(left: &$t<$n>, right: &$n) -> $t<$n> { + $t::new(left.$comp0 * *right $(, left.$compN * *right)*) } } ) @@ -329,8 +329,8 @@ macro_rules! scalar_div_impl( ($t: ident, $n: ident, $trhs: ident, $comp0: ident $(,$compN: ident)*) => ( impl $trhs<$n, $t<$n>> for $n { #[inline] - fn $trhs(&self, s: &$t<$n>) -> $t<$n> { - $t::new(s.$comp0 / *self $(, s.$compN / *self)*) + fn binop(left: &$t<$n>, right: &$n) -> $t<$n> { + $t::new(left.$comp0 / *right $(, left.$compN / *right)*) } } ) @@ -340,8 +340,8 @@ macro_rules! scalar_add_impl( ($t: ident, $n: ident, $trhs: ident, $comp0: ident $(,$compN: ident)*) => ( impl $trhs<$n, $t<$n>> for $n { #[inline] - fn $trhs(&self, s: &$t<$n>) -> $t<$n> { - $t::new(s.$comp0 + *self $(, s.$compN + *self)*) + fn binop(left: &$t<$n>, right: &$n) -> $t<$n> { + $t::new(left.$comp0 + *right $(, left.$compN + *right)*) } } ) @@ -351,8 +351,8 @@ macro_rules! scalar_sub_impl( ($t: ident, $n: ident, $trhs: ident, $comp0: ident $(,$compN: ident)*) => ( impl $trhs<$n, $t<$n>> for $n { #[inline] - fn $trhs(&self, s: &$t<$n>) -> $t<$n> { - $t::new(s.$comp0 - *self $(, s.$compN - *self)*) + fn binop(left: &$t<$n>, right: &$n) -> $t<$n> { + $t::new(left.$comp0 - *right $(, left.$compN - *right)*) } } )