"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).
This commit is contained in:
Sébastien Crozet 2013-09-15 10:48:18 +02:00
parent 514bf74efe
commit 6dc8139794
14 changed files with 393 additions and 205 deletions

View File

@ -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_).

View File

@ -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<M> {
priv submat: M
}
/// Trait of object `o` which can be multiplied by a `Rotmat` `r`: `r * o`.
pub trait RotmatMulRhs<M, Res> {
/// Multiplies a rotation matrix by `Self`.
fn binop(left: &Rotmat<M>, right: &Self) -> Res;
}
impl<M, Rhs: RotmatMulRhs<M, Res>, Res> Mul<Rhs, Res> for Rotmat<M> {
#[inline(always)]
fn mul(&self, other: &Rhs) -> Res {
RotmatMulRhs::binop(self, other)
}
}
impl<M: Clone> Rotmat<M> {
/// Gets a copy of the internal representation of the rotation.
pub fn submat(&self) -> M {
@ -229,19 +244,19 @@ impl<N: Clone + Rand + Trigonometric + Neg<N>> Rand for Rotmat<Mat2<N>> {
}
}
impl<M: RMul<V> + LMul<V>, V> Rotate<V> for Rotmat<M> {
impl<M, V: RotmatMulRhs<M, V> + Mul<Rotmat<M>, V>> Rotate<V> for Rotmat<M> {
#[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<M: RMul<V> + LMul<V>, V> Transform<V> for Rotmat<M> {
impl<M, V: RotmatMulRhs<M, V> + Mul<Rotmat<M>, V>> Transform<V> for Rotmat<M> {
#[inline]
fn transform(&self, v: &V) -> V {
self.rotate(v)
@ -275,24 +290,41 @@ impl<M: One + Zero> One for Rotmat<M> {
}
}
impl<M: Mul<M, M>> Mul<Rotmat<M>, Rotmat<M>> for Rotmat<M> {
impl<M: Mul<M, M>> RotmatMulRhs<M, Rotmat<M>> for Rotmat<M> {
#[inline]
fn mul(&self, other: &Rotmat<M>) -> Rotmat<M> {
Rotmat { submat: self.submat.mul(&other.submat) }
fn binop(left: &Rotmat<M>, right: &Rotmat<M>) -> Rotmat<M> {
Rotmat { submat: left.submat * right.submat }
}
}
impl<V, M: RMul<V>> RMul<V> for Rotmat<M> {
/*
* Right/Left multiplication implementation for Vec3 and Vec2.
*/
impl<M: Mul<Vec3<N>, Vec3<N>>, N> RotmatMulRhs<M, Vec3<N>> for Vec3<N> {
#[inline]
fn rmul(&self, other: &V) -> V {
self.submat.rmul(other)
fn binop(left: &Rotmat<M>, right: &Vec3<N>) -> Vec3<N> {
left.submat * *right
}
}
impl<V, M: LMul<V>> LMul<V> for Rotmat<M> {
impl<M: Mul<Vec2<N>, Vec2<N>>, N> RotmatMulRhs<M, Vec2<N>> for Vec2<N> {
#[inline]
fn lmul(&self, other: &V) -> V {
self.submat.lmul(other)
fn binop(left: &Rotmat<M>, right: &Vec2<N>) -> Vec2<N> {
left.submat * *right
}
}
impl<N, M: Vec3MulRhs<N, Vec3<N>>> Vec3MulRhs<N, Vec3<N>> for Rotmat<M> {
#[inline]
fn binop(left: &Vec3<N>, right: &Rotmat<M>) -> Vec3<N> {
*left * right.submat
}
}
impl<N, M: Vec2MulRhs<N, Vec2<N>>> Vec2MulRhs<N, Vec2<N>> for Rotmat<M> {
#[inline]
fn binop(left: &Vec2<N>, right: &Rotmat<M>) -> Vec2<N> {
*left * right.submat
}
}

View File

@ -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<V, M> Transform<V, M> {
}
}
/// Trait of object `o` which can be multiplied by a `Transform` `t`: `t * o`.
pub trait TransformMulRhs<V, M, Res> {
/// Multiplies a transformation matrix by `Self`.
fn binop(left: &Transform<V, M>, right: &Self) -> Res;
}
impl<V, M, Rhs: TransformMulRhs<V, M, Res>, Res> Mul<Rhs, Res> for Transform<V, M> {
#[inline(always)]
fn mul(&self, other: &Rhs) -> Res {
TransformMulRhs::binop(self, other)
}
}
impl<V: Clone, M: Clone> Transform<V, M> {
/// Gets a copy of the internal matrix.
#[inline]
@ -125,28 +138,45 @@ impl<M: Zero, V: Zero> Zero for Transform<V, M> {
}
}
impl<M: RMul<V> + Mul<M, M>, V: Add<V, V>>
Mul<Transform<V, M>, Transform<V, M>> for Transform<V, M> {
impl<M: RMul<V> + Mul<M, M>, V: Add<V, V>> TransformMulRhs<V, M, Transform<V, M>> for Transform<V, M> {
#[inline]
fn mul(&self, other: &Transform<V, M>) -> Transform<V, M> {
fn binop(left: &Transform<V, M>, right: &Transform<V, M>) -> Transform<V, M> {
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<M: RMul<V>, V: Add<V, V>> RMul<V> for Transform<V, M> {
impl<N: Clone + Add<N, N>, M: Mul<Vec2<N>, Vec2<N>>>
TransformMulRhs<Vec2<N>, M, Vec2<N>> for Vec2<N> {
#[inline]
fn rmul(&self, other: &V) -> V {
self.submat.rmul(other) + self.subtrans
fn binop(left: &Transform<Vec2<N>, M>, right: &Vec2<N>) -> Vec2<N> {
left.subtrans + left.submat * *right
}
}
impl<M: LMul<V>, V: Add<V, V>> LMul<V> for Transform<V, M> {
impl<N: Clone + Add<N, N>, M: Mul<Vec3<N>, Vec3<N>>>
TransformMulRhs<Vec3<N>, M, Vec3<N>> for Vec3<N> {
#[inline]
fn lmul(&self, other: &V) -> V {
self.submat.lmul(other) + self.subtrans
fn binop(left: &Transform<Vec3<N>, M>, right: &Vec3<N>) -> Vec3<N> {
left.subtrans + left.submat * *right
}
}
impl<N: Clone + Add<N, N>, M: Vec2MulRhs<N, Vec2<N>>>
Vec2MulRhs<N, Vec2<N>> for Transform<Vec2<N>, M> {
#[inline]
fn binop(left: &Vec2<N>, right: &Transform<Vec2<N>, M>) -> Vec2<N> {
(left + right.subtrans) * right.submat
}
}
impl<N: Clone + Add<N, N>, M: Vec3MulRhs<N, Vec3<N>>>
Vec3MulRhs<N, Vec3<N>> for Transform<Vec3<N>, M> {
#[inline]
fn binop(left: &Vec3<N>, right: &Transform<Vec3<N>, M>) -> Vec3<N> {
(left + right.subtrans) * right.submat
}
}

View File

@ -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
}
}
}

View File

@ -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<N> {
priv mij: ~[N]
}
/// Trait of object `o` which can be multiplied by a `DMat` `d`: `d * o`.
pub trait DMatMulRhs<N, Res> {
/// Multiplies a `DMat` by `Self`.
fn binop(left: &DMat<N>, right: &Self) -> Res;
}
impl<N, Rhs: DMatMulRhs<N, Res>, Res> Mul<Rhs, Res> for DMat<N> {
#[inline(always)]
fn mul(&self, other: &Rhs) -> Res {
DMatMulRhs::binop(self, other)
}
}
impl<N> DMat<N> {
/// Creates an uninitialized matrix.
#[inline]
@ -160,19 +172,19 @@ impl<N: Clone> DMat<N> {
}
}
impl<N: Clone + Mul<N, N> + Add<N, N> + Zero> Mul<DMat<N>, DMat<N>> for DMat<N> {
fn mul(&self, other: &DMat<N>) -> DMat<N> {
assert!(self.ncols == other.nrows);
impl<N: Clone + Mul<N, N> + Add<N, N> + Zero> DMatMulRhs<N, DMat<N>> for DMat<N> {
fn binop(left: &DMat<N>, right: &DMat<N>) -> DMat<N> {
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<N: Clone + Mul<N, N> + Add<N, N> + Zero> Mul<DMat<N>, DMat<N>> for DMat<N>
}
impl<N: Clone + Add<N, N> + Mul<N, N> + Zero>
RMul<DVec<N>> for DMat<N> {
fn rmul(&self, other: &DVec<N>) -> DVec<N> {
assert!(self.ncols == other.at.len());
DMatMulRhs<N, DVec<N>> for DVec<N> {
fn binop(left: &DMat<N>, right: &DVec<N>) -> DVec<N> {
assert!(left.ncols == right.at.len());
let mut res : DVec<N> = unsafe { DVec::new_uninitialized(self.nrows) };
let mut res : DVec<N> = 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<DVec<N>> for DMat<N> {
}
}
impl<N: Clone + Add<N, N> + Mul<N, N> + Zero>
LMul<DVec<N>> for DMat<N> {
fn lmul(&self, other: &DVec<N>) -> DVec<N> {
assert!(self.nrows == other.at.len());
DVecMulRhs<N, DVec<N>> for DMat<N> {
fn binop(left: &DVec<N>, right: &DMat<N>) -> DVec<N> {
assert!(right.nrows == left.at.len());
let mut res : DVec<N> = unsafe { DVec::new_uninitialized(self.ncols) };
let mut res : DVec<N> = 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);
}
}

View File

@ -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<N> {
@ -17,6 +21,16 @@ pub struct DVec<N> {
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<N: Zero + Clone> DVec<N> {
/// Builds a vector filled with zeros.
///
@ -123,7 +137,7 @@ impl<N> FromIterator<N> for DVec<N> {
}
}
impl<N: Clone + Num + Algebraic + ApproxEq<N>> DVec<N> {
impl<N: Clone + Num + Algebraic + ApproxEq<N> + DVecMulRhs<N, DVec<N>>> DVec<N> {
/// 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<N: Clone + Num + Algebraic + ApproxEq<N>> DVec<N> {
}
}
impl<N: Add<N,N>> Add<DVec<N>, DVec<N>> for DVec<N> {
impl<N: Add<N, N>> DVecAddRhs<N, DVec<N>> for DVec<N> {
#[inline]
fn add(&self, other: &DVec<N>) -> DVec<N> {
assert!(self.at.len() == other.at.len());
fn binop(left: &DVec<N>, right: &DVec<N>) -> DVec<N> {
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<N: Sub<N,N>> Sub<DVec<N>, DVec<N>> for DVec<N> {
impl<N: Sub<N, N>> DVecSubRhs<N, DVec<N>> for DVec<N> {
#[inline]
fn sub(&self, other: &DVec<N>) -> DVec<N> {
assert!(self.at.len() == other.at.len());
fn binop(left: &DVec<N>, right: &DVec<N>) -> DVec<N> {
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<N: Num> Dot<N> for DVec<N> {
}
}
impl<N: Mul<N, N>> Mul<N, DVec<N>> for DVec<N> {
#[inline]
fn mul(&self, s: &N) -> DVec<N> {
DVec { at: self.at.iter().map(|a| a * *s).collect() }
}
}
impl<N: Div<N, N>> Div<N, DVec<N>> for DVec<N> {
#[inline]
fn div(&self, s: &N) -> DVec<N> {
DVec { at: self.at.iter().map(|a| a / *s).collect() }
}
}
impl<N: Add<N, N> + Neg<N> + Clone> Translation<DVec<N>> for DVec<N> {
#[inline]
fn translation(&self) -> DVec<N> {
@ -331,3 +330,103 @@ impl<N: ApproxEq<N>> ApproxEq<N> for DVec<N> {
}
}
}
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)

View File

@ -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<M: Clone> RMul<M> for mat::Identity {
fn rmul(&self, m: &M) -> M {
m.clone()
}
}
impl<M: Clone> LMul<M> for mat::Identity {
fn lmul(&self, m: &M) -> M {
m.clone()
}
}
impl<M: Clone> Mul<M, M> for mat::Identity {
impl<T: Clone> Mul<T, T> for mat::Identity {
#[inline]
fn mul(&self, other: &M) -> M {
fn mul(&self, other: &T) -> T {
other.clone()
}
}

View File

@ -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)

View File

@ -47,8 +47,8 @@ macro_rules! add_impl(
($t: ident, $trhs: ident, $comp0: ident $(,$compN: ident)*) => (
impl<N: Clone + Add<N, N>> $trhs<N, $t<N>> for $t<N> {
#[inline]
fn $trhs(&self, other: &$t<N>) -> $t<N> {
$t::new(self.$comp0 + other.$comp0 $(, self.$compN + other.$compN)*)
fn binop(left: &$t<N>, right: &$t<N>) -> $t<N> {
$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<N: Clone + Sub<N, N>> $trhs<N, $t<N>> for $t<N> {
#[inline]
fn $trhs(&self, other: &$t<N>) -> $t<N> {
$t::new(other.$comp0 - self.$comp0 $(, other.$compN - self.$compN)*)
fn binop(left: &$t<N>, right: &$t<N>) -> $t<N> {
$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<N: Clone + Num> $trhs<N, $t<N>> for $t<N> {
#[inline]
fn $trhs(&self, other: &$t<N>) -> $t<N> {
fn binop(left: &$t<N>, right: &$t<N>) -> $t<N> {
// careful! we need to comute other * self here (self is the rhs).
let mut res: $t<N> = 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<N: Clone + Num> RMul<$v<N>> for $t<N> {
macro_rules! vec_mul_mat_impl(
($t: ident, $v: ident, $trhs: ident, $dim: expr) => (
impl<N: Clone + Num> $trhs<N, $v<N>> for $t<N> {
#[inline]
fn rmul(&self, other: &$v<N>) -> $v<N> {
fn binop(left: &$v<N>, right: &$t<N>) -> $v<N> {
let mut res : $v<N> = 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<N: Clone + Num> $trhs<N, $v<N>> for $v<N> {
#[inline]
fn $trhs(&self, other: &$t<N>) -> $v<N> {
fn binop(left: &$t<N>, right: &$v<N>) -> $v<N> {
let mut res : $v<N> = 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)
}
}

View File

@ -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<N: Clone> Col<Vec3<N>> for Mat3<N> {
impl<N: Mul<N, N> + Add<N, N>> Mat3MulRhs<N, Mat3<N>> for Mat3<N> {
#[inline]
fn Mat3MulRhs(&self, other: &Mat3<N>) -> Mat3<N> {
fn binop(left: &Mat3<N>, right: &Mat3<N>) -> Mat3<N> {
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<N: Mul<N, N> + Add<N, N>> Mat2MulRhs<N, Mat2<N>> for Mat2<N> {
#[inline(always)]
fn Mat2MulRhs(&self, other: &Mat2<N>) -> Mat2<N> {
fn binop(left: &Mat2<N>, right: &Mat2<N>) -> Mat2<N> {
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<N: Mul<N, N> + Add<N, N>> RMul<Vec3<N>> for Mat3<N> {
impl<N: Mul<N, N> + Add<N, N>> Mat3MulRhs<N, Vec3<N>> for Vec3<N> {
#[inline(always)]
fn rmul(&self, v: &Vec3<N>) -> Vec3<N> {
fn binop(left: &Mat3<N>, right: &Vec3<N>) -> Vec3<N> {
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<N: Mul<N, N> + Add<N, N>> LMul<Vec3<N>> for Mat3<N> {
impl<N: Mul<N, N> + Add<N, N>> Vec3MulRhs<N, Vec3<N>> for Mat3<N> {
#[inline(always)]
fn lmul(&self, v: &Vec3<N>) -> Vec3<N> {
fn binop(left: &Vec3<N>, right: &Mat3<N>) -> Vec3<N> {
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<N: Mul<N, N> + Add<N, N>> RMul<Vec2<N>> for Mat2<N> {
impl<N: Mul<N, N> + Add<N, N>> Vec2MulRhs<N, Vec2<N>> for Mat2<N> {
#[inline(always)]
fn rmul(&self, v: &Vec2<N>) -> Vec2<N> {
fn binop(left: &Vec2<N>, right: &Mat2<N>) -> Vec2<N> {
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<N: Mul<N, N> + Add<N, N>> LMul<Vec2<N>> for Mat2<N> {
impl<N: Mul<N, N> + Add<N, N>> Mat2MulRhs<N, Vec2<N>> for Vec2<N> {
#[inline(always)]
fn lmul(&self, v: &Vec2<N>) -> Vec2<N> {
fn binop(left: &Mat2<N>, right: &Vec2<N>) -> Vec2<N> {
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
)
}
}

View File

@ -8,55 +8,55 @@
macro_rules! double_dispatch_binop_decl_trait(
($t: ident, $trhs: ident) => (
pub trait $trhs<N, Res> {
fn $trhs(&self, other: &$t<N>) -> Res;
fn binop(left: &$t<N>, 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<N, Rhs: $trhs<N, Res>, Res> Mul<Rhs, Res> for $t<N> {
#[inline(always)]
fn mul(&self, other: &Rhs) -> Res {
other.$trhs(self)
($t: ident, $trhs: ident) => (
impl<N, Rhs: $trhs<N, Res>, Res> Mul<Rhs, Res> for $t<N> {
#[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<N, Rhs: $trhs<N, Res>, Res> Div<Rhs, Res> for $t<N> {
#[inline(always)]
fn div(&self, other: &Rhs) -> Res {
other.$trhs(self)
($t: ident, $trhs: ident) => (
impl<N, Rhs: $trhs<N, Res>, Res> Div<Rhs, Res> for $t<N> {
#[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<N, Rhs: $trhs<N, Res>, Res> Add<Rhs, Res> for $t<N> {
#[inline(always)]
fn add(&self, other: &Rhs) -> Res {
other.$trhs(self)
($t: ident, $trhs: ident) => (
impl<N, Rhs: $trhs<N, Res>, Res> Add<Rhs, Res> for $t<N> {
#[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<N, Rhs: $trhs<N, Res>, Res> Sub<Rhs, Res> for $t<N> {
#[inline(always)]
fn sub(&self, other: &Rhs) -> Res {
other.$trhs(self)
($t: ident, $trhs: ident) => (
impl<N, Rhs: $trhs<N, Res>, Res> Sub<Rhs, Res> for $t<N> {
#[inline(always)]
fn sub(&self, other: &Rhs) -> Res {
$trhs::binop(self, other)
}
}
}
)
)
)

View File

@ -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<T: Add<N, V> + Add<V, V>)
// 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<V> {
fn rmul(&self, v: &V) -> V;
}
impl<M: Mul<T, T>, T> RMul<T> 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<V> {
/// Computes v * self
fn lmul(&self, &V) -> V;
}
impl<T: Mul<M, T>, M> LMul<T> for M {
fn lmul(&self, v: &T) -> T {
v * *self
}
}

View File

@ -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.

View File

@ -269,8 +269,8 @@ macro_rules! add_impl(
($t: ident, $trhs: ident, $comp0: ident $(,$compN: ident)*) => (
impl<N: Clone + Add<N, N>> $trhs<N, $t<N>> for $t<N> {
#[inline]
fn $trhs(&self, other: &$t<N>) -> $t<N> {
$t::new(self.$comp0 + other.$comp0 $(, self.$compN + other.$compN)*)
fn binop(left: &$t<N>, right: &$t<N>) -> $t<N> {
$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<N: Clone + Sub<N, N>> $trhs<N, $t<N>> for $t<N> {
#[inline]
fn $trhs(&self, other: &$t<N>) -> $t<N> {
$t::new(other.$comp0 - self.$comp0 $(, other.$compN - self.$compN)*)
fn binop(left: &$t<N>, right: &$t<N>) -> $t<N> {
$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)*)
}
}
)