diff --git a/src/mat.rs b/src/mat.rs index 20b7449c..d6fb63e2 100644 --- a/src/mat.rs +++ b/src/mat.rs @@ -54,6 +54,7 @@ pub struct Mat1 { m11: N } +double_dispatch_binop_decl_trait!(Mat1, Mat1MulRhs) mat_impl!(Mat1, m11) mat_cast_impl!(Mat1, m11) add_impl!(Mat1, m11) @@ -69,7 +70,8 @@ iterable_mut_impl!(Mat1, 1) at_fast_impl!(Mat1, 1) dim_impl!(Mat1, 1) indexable_impl!(Mat1, 1) -mul_impl!(Mat1, 1) +mul_redispatch_impl!(Mat1, Mat1MulRhs) +mat_mul_mat_impl!(Mat1, Mat1MulRhs, 1) rmul_impl!(Mat1, Vec1, 1) lmul_impl!(Mat1, Vec1, 1) transform_impl!(Mat1, Vec1) @@ -195,6 +197,7 @@ pub struct Mat4 { m41: N, m42: N, m43: N, m44: N } +double_dispatch_binop_decl_trait!(Mat4, Mat4MulRhs) mat_impl!(Mat4, m11, m12, m13, m14, m21, m22, m23, m24, @@ -258,7 +261,8 @@ iterable_mut_impl!(Mat4, 4) dim_impl!(Mat4, 4) indexable_impl!(Mat4, 4) at_fast_impl!(Mat4, 4) -mul_impl!(Mat4, 4) +mul_redispatch_impl!(Mat4, Mat4MulRhs) +mat_mul_mat_impl!(Mat4, Mat4MulRhs, 4) rmul_impl!(Mat4, Vec4, 4) lmul_impl!(Mat4, Vec4, 4) transform_impl!(Mat4, Vec4) @@ -282,6 +286,7 @@ pub struct Mat5 { m51: N, m52: N, m53: N, m54: N, m55: N } +double_dispatch_binop_decl_trait!(Mat5, Mat5MulRhs) mat_impl!(Mat5, m11, m12, m13, m14, m15, m21, m22, m23, m24, m25, @@ -357,7 +362,8 @@ iterable_mut_impl!(Mat5, 5) dim_impl!(Mat5, 5) indexable_impl!(Mat5, 5) at_fast_impl!(Mat5, 5) -mul_impl!(Mat5, 5) +mul_redispatch_impl!(Mat5, Mat5MulRhs) +mat_mul_mat_impl!(Mat5, Mat5MulRhs, 5) rmul_impl!(Mat5, Vec5, 5) lmul_impl!(Mat5, Vec5, 5) transform_impl!(Mat5, Vec5) @@ -382,6 +388,7 @@ pub struct Mat6 { m61: N, m62: N, m63: N, m64: N, m65: N, m66: N } +double_dispatch_binop_decl_trait!(Mat6, Mat6MulRhs) mat_impl!(Mat6, m11, m12, m13, m14, m15, m16, m21, m22, m23, m24, m25, m26, @@ -467,7 +474,8 @@ iterable_mut_impl!(Mat6, 6) dim_impl!(Mat6, 6) indexable_impl!(Mat6, 6) at_fast_impl!(Mat6, 6) -mul_impl!(Mat6, 6) +mul_redispatch_impl!(Mat6, Mat6MulRhs) +mat_mul_mat_impl!(Mat6, Mat6MulRhs, 6) rmul_impl!(Mat6, Vec6, 6) lmul_impl!(Mat6, Vec6, 6) transform_impl!(Mat6, Vec6) diff --git a/src/mat_macros.rs b/src/mat_macros.rs index 70538667..0ceb6f62 100644 --- a/src/mat_macros.rs +++ b/src/mat_macros.rs @@ -292,11 +292,34 @@ macro_rules! col_impl( ) ) -macro_rules! mul_impl( - ($t: ident, $dim: expr) => ( - impl Mul<$t, $t> for $t { +// Create the traits needed to do fancy operator oveloading. +// This is a meta version of +// http://smallcultfollowing.com/babysteps/blog/2012/10/04/refining-traits-slash-impls/ +macro_rules! double_dispatch_binop_decl_trait( + ($t: ident, $trhs: ident) => ( + pub trait $trhs { + fn $trhs(&self, other: &$t) -> Res; + } + ) +) + +macro_rules! mul_redispatch_impl( + ($t: ident, $trhs: ident) => ( + impl, Res> Mul for $t { #[inline] - fn mul(&self, other: &$t) -> $t { + fn mul(&self, other: &Rhs) -> Res { + other.$trhs(self) + } + } + ) +) + +macro_rules! mat_mul_mat_impl( + ($t: ident, $trhs: ident, $dim: expr) => ( + impl $trhs> for $t { + #[inline] + fn $trhs(&self, other: &$t) -> $t { + // careful! we need to comute other * self here (self is the rhs). let mut res: $t = Zero::zero(); for i in range(0u, $dim) { @@ -305,7 +328,7 @@ macro_rules! mul_impl( unsafe { for k in range(0u, $dim) { - acc = acc + self.at_fast((i, k)) * other.at_fast((k, j)); + acc = acc + other.at_fast((i, k)) * self.at_fast((k, j)); } res.set_fast((i, j), acc);