From 6dc81397942c99785332ce7c00a3f8611dbfde54 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Crozet?= Date: Sun, 15 Sep 2013 10:48:18 +0200 Subject: [PATCH] "Remove" the RMul and LMul trait. Use the regular Mul trait. Those traits are not really removed since they are useful on generic code (to work around curret limitations of rust traits system). --- README.md | 9 ++- src/adaptors/rotmat.rs | 62 ++++++++++++---- src/adaptors/transform.rs | 56 +++++++++++---- src/bench/mat.rs | 4 +- src/dmat.rs | 61 +++++++++------- src/dvec.rs | 147 +++++++++++++++++++++++++++++++------- src/identity_spec.rs | 17 +---- src/mat.rs | 20 +++--- src/mat_macros.rs | 44 ++++++------ src/mat_spec.rs | 70 +++++++++--------- src/metal.rs | 62 ++++++++-------- src/traits/rlmul.rs | 20 ++++++ src/traits/scalar_op.rs | 2 +- src/vec_macros.rs | 24 +++---- 14 files changed, 393 insertions(+), 205 deletions(-) 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)*) } } )