diff --git a/src/traits/alg/coordinate.rs b/src/traits/alg/coordinate.rs index f813bbb..fc14d2e 100644 --- a/src/traits/alg/coordinate.rs +++ b/src/traits/alg/coordinate.rs @@ -13,6 +13,8 @@ // See the License for the specific language governing permissions and // limitations under the License. +#[macro_escape]; + use traits::alg::Field; use traits::util::Indexable; use traits::util::Swappable; @@ -26,3 +28,25 @@ pub trait Coordinate + Swappable { } + +macro_rules! impl_coordinate_binop( + ($Self:ty, $Other:ty, $Result:ty, $Op:ident, $op:ident) => ( + impl $Op<$Other, $Result> for $Self { + #[inline(always)] + fn $op(&self, other: &$Other) -> $Result { + self.bimap(other, |a, b| a.$op(b)) + } + } + ) +) + +macro_rules! impl_coordinate_op( + ($Self:ty, $Result:ty, $Op:ident, $op:ident) => ( + impl $Op<$Result> for $Self { + #[inline(always)] + fn $op(&self) -> $Result { + self.map(|a| a.$op()) + } + } + ) +) diff --git a/src/traits/alg/field.rs b/src/traits/alg/field.rs index a1fcaa7..6d09b1e 100644 --- a/src/traits/alg/field.rs +++ b/src/traits/alg/field.rs @@ -17,7 +17,7 @@ use traits::alg::Ring; /// A commutative ring that contains a multiplicative inverse. pub trait Field -: Ring +: Ring + Div + Rem { diff --git a/src/traits/alg/matrix.rs b/src/traits/alg/matrix.rs index 3865536..988a729 100644 --- a/src/traits/alg/matrix.rs +++ b/src/traits/alg/matrix.rs @@ -13,18 +13,61 @@ // See the License for the specific language governing permissions and // limitations under the License. +use traits::alg::Coordinate; use traits::alg::Field; use traits::alg::Ring; use traits::alg::VectorSpace; +use traits::util::Indexable; pub trait Matrix < - S: Field, - RV: VectorSpace, - CV: VectorSpace, - MT//: Matrix + S: Field + Clone, + RV: Clone + VectorSpace + Coordinate, RVSlice, RSlice, + CV: Clone + VectorSpace + Coordinate, CVSlice, CSlice, + MT//: Matrix > -: Ring +: Ring ++ Indexable { + #[inline] + fn c<'a>(&'a self, c: uint) -> &'a CV { self.i(c) } + + #[inline] + fn mut_c<'a>(&'a mut self, c: uint) -> &'a mut CV { self.mut_i(c) } + + #[inline] + fn swap_c(&mut self, a: uint, b: uint) { + let tmp = self.c(a).clone(); + *self.mut_c(a) = self.c(b).clone(); + *self.mut_c(b) = tmp; + } + + fn r(&self, r: uint) -> RV; + + fn swap_r(&mut self, a: uint, b: uint); + + #[inline] + fn cr<'a>(&'a self, c: uint, r: uint) -> &'a S { self.i(c).i(r) } + + #[inline] + fn mut_cr<'a>(&'a mut self, c: uint, r: uint) -> &'a mut S { + self.mut_i(c).mut_i(r) + } + + #[inline] + fn swap_cr(&mut self, a: (uint, uint), b: (uint, uint)) { + let (ca, ra) = a; + let (cb, rb) = b; + let tmp = self.cr(ca, ra).clone(); + *self.mut_cr(ca, ra) = self.cr(cb, rb).clone(); + *self.mut_cr(cb, rb) = tmp; + } + + // fn swap_cr(&mut self, (ca, ra): (uint, uint), (cb, rb): (uint, uint)) { + // let tmp = self.cr(ca, ra).clone(); + // *self.mut_cr(ca, ra) = self.cr(cb, rb).clone(); + // *self.mut_cr(cb, rb) = tmp; + // } + fn transpose(&self) -> MT; -} \ No newline at end of file +} diff --git a/src/traits/alg/mod.rs b/src/traits/alg/mod.rs index c6d891b..23c810a 100644 --- a/src/traits/alg/mod.rs +++ b/src/traits/alg/mod.rs @@ -13,6 +13,8 @@ // See the License for the specific language governing permissions and // limitations under the License. +#[macro_escape]; + pub use self::affine_space::AffineSpace; pub use self::coordinate::Coordinate; pub use self::euclidean_space::EuclideanSpace; diff --git a/src/traits/alg/ordered_ring.rs b/src/traits/alg/ordered_ring.rs index 4507d5a..3d0a817 100644 --- a/src/traits/alg/ordered_ring.rs +++ b/src/traits/alg/ordered_ring.rs @@ -17,23 +17,26 @@ use traits::alg::Ring; /// A ring that can also be ordered. pub trait OrderedRing -: Ring +< + S +> +: Ring + Orderable { } // impls for concrete types -impl OrderedRing for u8; -impl OrderedRing for u16; -impl OrderedRing for u32; -impl OrderedRing for u64; -impl OrderedRing for uint; -impl OrderedRing for i8; -impl OrderedRing for i16; -impl OrderedRing for i32; -impl OrderedRing for i64; -impl OrderedRing for int; -impl OrderedRing for f32; -impl OrderedRing for f64; -impl OrderedRing for float; +impl OrderedRing for u8; +impl OrderedRing for u16; +impl OrderedRing for u32; +impl OrderedRing for u64; +impl OrderedRing for uint; +impl OrderedRing for i8; +impl OrderedRing for i16; +impl OrderedRing for i32; +impl OrderedRing for i64; +impl OrderedRing for int; +impl OrderedRing for f32; +impl OrderedRing for f64; +impl OrderedRing for float; diff --git a/src/traits/alg/ring.rs b/src/traits/alg/ring.rs index ba1de55..2f3445b 100644 --- a/src/traits/alg/ring.rs +++ b/src/traits/alg/ring.rs @@ -20,7 +20,10 @@ use traits::alg::Module; /// A module that also requires the additive inverse operation (subtraction) /// and the additive inverse. pub trait Ring -: Module +< + S +> +: Module + Neg + Sub + One @@ -29,16 +32,16 @@ pub trait Ring // impls for concrete types -impl Ring for u8; -impl Ring for u16; -impl Ring for u32; -impl Ring for u64; -impl Ring for uint; -impl Ring for i8; -impl Ring for i16; -impl Ring for i32; -impl Ring for i64; -impl Ring for int; -impl Ring for f32; -impl Ring for f64; -impl Ring for float; +impl Ring for u8; +impl Ring for u16; +impl Ring for u32; +impl Ring for u64; +impl Ring for uint; +impl Ring for i8; +impl Ring for i16; +impl Ring for i32; +impl Ring for i64; +impl Ring for int; +impl Ring for f32; +impl Ring for f64; +impl Ring for float; diff --git a/src/traits/alg/scalar_mul.rs b/src/traits/alg/scalar_mul.rs index 8dd3c08..790aed9 100644 --- a/src/traits/alg/scalar_mul.rs +++ b/src/traits/alg/scalar_mul.rs @@ -13,6 +13,8 @@ // See the License for the specific language governing permissions and // limitations under the License. +#[macro_escape]; + // use traits::alg::Field; /// Enforces the multiplication of an type by a scalar. @@ -41,3 +43,12 @@ impl ScalarMul for int; impl ScalarMul for f32; impl ScalarMul for f64; impl ScalarMul for float; + +macro_rules! impl_scalar_binop( + ($Self:ty, $Op:ident, $op:ident) => ( + impl $Op for $Self { + #[inline(always)] + fn $op(&self, s: &S) -> $Self { self.map(|x| x.$op(s)) } + } + ) +) diff --git a/src/traits/alg/square_matrix.rs b/src/traits/alg/square_matrix.rs index 263059c..3c84620 100644 --- a/src/traits/alg/square_matrix.rs +++ b/src/traits/alg/square_matrix.rs @@ -20,9 +20,10 @@ use traits::alg::VectorSpace; pub trait SquareMatrix < S: Field, - V: VectorSpace + V: VectorSpace, + VVSlice, VSlice > -: Matrix +: Matrix { fn transpose_self(&mut self); fn trace(&self) -> S; diff --git a/src/traits/util/indexable.rs b/src/traits/util/indexable.rs index e40dc42..287604f 100644 --- a/src/traits/util/indexable.rs +++ b/src/traits/util/indexable.rs @@ -61,8 +61,8 @@ pub trait Indexable { } macro_rules! impl_indexable( - ($Self:ty, [$T:ident, ..$n:expr]) => ( - impl<$T> Indexable<$T, [$T,..$n]> for $Self { + ($Self:ty, [$T:ty, ..$n:expr]) => ( + impl Indexable<$T, [$T,..$n]> for $Self { #[inline] fn len(&self) -> uint { $n } diff --git a/src/types/matrix.rs b/src/types/matrix.rs index e815306..d82b1d3 100644 --- a/src/types/matrix.rs +++ b/src/types/matrix.rs @@ -13,8 +13,228 @@ // See the License for the specific language governing permissions and // limitations under the License. -use types::vector::{Vec2, Vec3, Vec4}; +use std::num::{One, one, zero}; -#[deriving(Clone, Eq)] pub struct Mat2 { x: Vec2, y: Vec2 } -#[deriving(Clone, Eq)] pub struct Mat3 { x: Vec3, y: Vec3, z: Vec3 } -#[deriving(Clone, Eq)] pub struct Mat4 { x: Vec4, y: Vec4, z: Vec4, w: Vec4 } +use traits::alg::*; +use traits::util::*; +use types::vector::*; + +#[deriving(Clone, Eq, Zero)] pub struct Mat2 { x: Vec2, y: Vec2 } +#[deriving(Clone, Eq, Zero)] pub struct Mat3 { x: Vec3, y: Vec3, z: Vec3 } +#[deriving(Clone, Eq, Zero)] pub struct Mat4 { x: Vec4, y: Vec4, z: Vec4, w: Vec4 } + +// Constructors + +impl Mat2 { + #[inline] + pub fn new(c0r0: S, c0r1: S, + c1r0: S, c1r1: S) -> Mat2 { + Mat2::from_cols(Vec2::new(c0r0, c0r1), + Vec2::new(c1r0, c1r1)) + } + + #[inline] + pub fn from_cols(c0: Vec2, c1: Vec2) -> Mat2 { + Mat2 { x: c0, y: c1 } + } +} + +impl Mat3 { + #[inline] + pub fn new(c0r0:S, c0r1:S, c0r2:S, + c1r0:S, c1r1:S, c1r2:S, + c2r0:S, c2r1:S, c2r2:S) -> Mat3 { + Mat3::from_cols(Vec3::new(c0r0, c0r1, c0r2), + Vec3::new(c1r0, c1r1, c1r2), + Vec3::new(c2r0, c2r1, c2r2)) + } + + #[inline] + pub fn from_cols(c0: Vec3, c1: Vec3, c2: Vec3) -> Mat3 { + Mat3 { x: c0, y: c1, z: c2 } + } +} + +impl Mat4 { + #[inline] + pub fn new(c0r0: S, c0r1: S, c0r2: S, c0r3: S, + c1r0: S, c1r1: S, c1r2: S, c1r3: S, + c2r0: S, c2r1: S, c2r2: S, c2r3: S, + c3r0: S, c3r1: S, c3r2: S, c3r3: S) -> Mat4 { + Mat4::from_cols(Vec4::new(c0r0, c0r1, c0r2, c0r3), + Vec4::new(c1r0, c1r1, c1r2, c1r3), + Vec4::new(c2r0, c2r1, c2r2, c2r3), + Vec4::new(c3r0, c3r1, c3r2, c3r3)) + } + + #[inline] + pub fn from_cols(c0: Vec4, c1: Vec4, c2: Vec4, c3: Vec4) -> Mat4 { + Mat4 { x: c0, y: c1, z: c2, w: c3 } + } +} + +// Trait impls + +impl_indexable!(Mat2, [Vec2, ..2]) +impl_indexable!(Mat3, [Vec3, ..3]) +impl_indexable!(Mat4, [Vec4, ..4]) + +impl Swappable, [Vec2, ..2]> for Mat2; +impl Swappable, [Vec3, ..3]> for Mat3; +impl Swappable, [Vec4, ..4]> for Mat4; + +impl_scalar_binop!(Mat2, Mul, mul) +impl_scalar_binop!(Mat3, Mul, mul) +impl_scalar_binop!(Mat4, Mul, mul) + +impl_scalar_binop!(Mat2, Div, div) +impl_scalar_binop!(Mat3, Div, div) +impl_scalar_binop!(Mat4, Div, div) + +impl_scalar_binop!(Mat2, Rem, rem) +impl_scalar_binop!(Mat3, Rem, rem) +impl_scalar_binop!(Mat4, Rem, rem) + +impl ScalarMul for Mat2; +impl ScalarMul for Mat3; +impl ScalarMul for Mat4; + +impl_coordinate_binop!(Mat2, Mat2, Mat2, Add, add) +impl_coordinate_binop!(Mat3, Mat3, Mat3, Add, add) +impl_coordinate_binop!(Mat4, Mat4, Mat4, Add, add) + +impl_coordinate_binop!(Mat2, Mat2, Mat2, Sub, sub) +impl_coordinate_binop!(Mat3, Mat3, Mat3, Sub, sub) +impl_coordinate_binop!(Mat4, Mat4, Mat4, Sub, sub) + +impl_coordinate_op!(Mat2, Mat2, Neg, neg) +impl_coordinate_op!(Mat3, Mat3, Neg, neg) +impl_coordinate_op!(Mat4, Mat4, Neg, neg) + +impl Module for Mat2; +impl Module for Mat3; +impl Module for Mat4; + +impl One for Mat2 { + fn one() -> Mat2 { + Mat2::new(one(), zero(), + zero(), one()) + } +} + +impl One for Mat3 { + fn one() -> Mat3 { + Mat3::new(one(), zero(), zero(), + zero(), one(), zero(), + zero(), zero(), one()) + } +} + +impl One for Mat4 { + fn one() -> Mat4 { + Mat4::new(one(), zero(), zero(), zero(), + zero(), one(), zero(), zero(), + zero(), zero(), one(), zero(), + zero(), zero(), zero(), one()) + } +} + +impl Ring for Mat2; +impl Ring for Mat3; +impl Ring for Mat4; + +impl + +Matrix +< + S, + Vec2, [S, ..2], [Vec2, ..2], + Vec2, [S, ..2], [Vec2, ..2], + Mat2 +> +for Mat2 +{ + #[inline] + fn r(&self, r: uint) -> Vec2 { + Vec2::new(self.i(0).i(r).clone(), + self.i(1).i(r).clone()) + } + + #[inline] + fn swap_r(&mut self, a: uint, b: uint) { + self.mut_c(0).swap(a, b); + self.mut_c(1).swap(a, b); + } + + fn transpose(&self) -> Mat2 { + Mat2::new(self.cr(0, 0).clone(), self.cr(1, 0).clone(), + self.cr(0, 1).clone(), self.cr(1, 1).clone()) + } +} + +impl + +Matrix +< + S, + Vec3, [S, ..3], [Vec3, ..3], + Vec3, [S, ..3], [Vec3, ..3], + Mat3 +> +for Mat3 +{ + #[inline] + fn r(&self, r: uint) -> Vec3 { + Vec3::new(self.i(0).i(r).clone(), + self.i(1).i(r).clone(), + self.i(2).i(r).clone()) + } + + #[inline] + fn swap_r(&mut self, a: uint, b: uint) { + self.mut_c(0).swap(a, b); + self.mut_c(1).swap(a, b); + self.mut_c(2).swap(a, b); + } + + fn transpose(&self) -> Mat3 { + Mat3::new(self.cr(0, 0).clone(), self.cr(1, 0).clone(), self.cr(2, 0).clone(), + self.cr(0, 1).clone(), self.cr(1, 1).clone(), self.cr(2, 1).clone(), + self.cr(0, 2).clone(), self.cr(1, 2).clone(), self.cr(2, 2).clone()) + } +} + +impl + +Matrix +< + S, + Vec4, [S, ..4], [Vec4, ..4], + Vec4, [S, ..4], [Vec4, ..4], + Mat4 +> +for Mat4 +{ + #[inline] + fn r(&self, r: uint) -> Vec4 { + Vec4::new(self.i(0).i(r).clone(), + self.i(1).i(r).clone(), + self.i(2).i(r).clone(), + self.i(2).i(r).clone()) + } + + #[inline] + fn swap_r(&mut self, a: uint, b: uint) { + self.mut_c(0).swap(a, b); + self.mut_c(1).swap(a, b); + self.mut_c(2).swap(a, b); + self.mut_c(3).swap(a, b); + } + + fn transpose(&self) -> Mat4 { + Mat4::new(self.cr(0, 0).clone(), self.cr(1, 0).clone(), self.cr(2, 0).clone(), self.cr(3, 0).clone(), + self.cr(0, 1).clone(), self.cr(1, 1).clone(), self.cr(2, 1).clone(), self.cr(3, 1).clone(), + self.cr(0, 2).clone(), self.cr(1, 2).clone(), self.cr(2, 2).clone(), self.cr(3, 2).clone(), + self.cr(0, 3).clone(), self.cr(1, 3).clone(), self.cr(2, 3).clone(), self.cr(3, 3).clone()) + } +} diff --git a/src/types/vector.rs b/src/types/vector.rs index 6ff925d..39d7329 100644 --- a/src/types/vector.rs +++ b/src/types/vector.rs @@ -35,6 +35,10 @@ macro_rules! impl_vec( pub fn new($($field: $S),+) -> $Self<$S> { $Self { $($field: $field),+ } } + + /// The additive identity of the vector. + #[inline] + pub fn zero() -> $Self<$S> { zero() } } ) ) @@ -65,23 +69,6 @@ impl_vec_clonable!(Vec4) impl_vec_clonable!(Vec5) impl_vec_clonable!(Vec6) -macro_rules! impl_vec_ring( - ($Self:ident <$S:ident>) => ( - impl<$S:Field> $Self<$S> { - /// The additive identity of the vector. - #[inline] - pub fn zero() -> $Self<$S> { zero() } - } - ) -) - -impl_vec_ring!(Vec1) -impl_vec_ring!(Vec2) -impl_vec_ring!(Vec3) -impl_vec_ring!(Vec4) -impl_vec_ring!(Vec5) -impl_vec_ring!(Vec6) - // Operator impls macro_rules! impl_vec_ops( @@ -90,35 +77,12 @@ macro_rules! impl_vec_ops( use super::*; use super::super::super::traits::alg::*; - impl<$S:Field> Mul<$S, $Self<$S>> for $Self<$S> { - #[inline(always)] - fn mul(&self, s: &$S) -> $Self<$S> { self.map(|x| x.mul(s)) } - } - - impl<$S:Field> Div<$S, $Self<$S>> for $Self<$S> { - #[inline(always)] - fn div(&self, s: &$S) -> $Self<$S> { self.map(|x| x.div(s)) } - } - - impl<$S:Field> Rem<$S, $Self<$S>> for $Self<$S> { - #[inline(always)] - fn rem(&self, s: &$S) -> $Self<$S> { self.map(|x| x.rem(s)) } - } - - impl<$S:Field> Add<$Self<$S>, $Self<$S>> for $Self<$S> { - #[inline(always)] - fn add(&self, other: &$Self<$S>) -> $Self<$S> { self.bimap(other, |a, b| a.add(b)) } - } - - impl<$S:Field> Sub<$Self<$S>, $Self<$S>> for $Self<$S> { - #[inline(always)] - fn sub(&self, other: &$Self<$S>) -> $Self<$S> { self.bimap(other, |a, b| a.sub(b)) } - } - - impl<$S:Field> Neg<$Self<$S>> for $Self<$S> { - #[inline(always)] - fn neg(&self) -> $Self<$S> { self.map(|x| x.neg()) } - } + impl_scalar_binop!($Self<$S>, Mul, mul) + impl_scalar_binop!($Self<$S>, Div, div) + impl_scalar_binop!($Self<$S>, Rem, rem) + impl_coordinate_binop!($Self<$S>, $Self<$S>, $Self<$S>, Add, add) + impl_coordinate_binop!($Self<$S>, $Self<$S>, $Self<$S>, Sub, sub) + impl_coordinate_op!($Self<$S>, $Self<$S>, Neg, neg) } ) ) @@ -150,12 +114,12 @@ impl Vec3 { // Trait impls -impl_indexable!(Vec1, [S, ..1]) -impl_indexable!(Vec2, [S, ..2]) -impl_indexable!(Vec3, [S, ..3]) -impl_indexable!(Vec4, [S, ..4]) -impl_indexable!(Vec5, [S, ..5]) -impl_indexable!(Vec6, [S, ..6]) +impl_indexable!(Vec1, [T, ..1]) +impl_indexable!(Vec2, [T, ..2]) +impl_indexable!(Vec3, [T, ..3]) +impl_indexable!(Vec4, [T, ..4]) +impl_indexable!(Vec5, [T, ..5]) +impl_indexable!(Vec6, [T, ..6]) impl Swappable for Vec1; impl Swappable for Vec2;