Add some matrix impls, add operator macros

This commit is contained in:
Brendan Zabarauskas 2013-08-27 16:11:05 +10:00
parent b67b31b633
commit 9064b9d5c0
11 changed files with 366 additions and 95 deletions

View file

@ -13,6 +13,8 @@
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
#[macro_escape];
use traits::alg::Field; use traits::alg::Field;
use traits::util::Indexable; use traits::util::Indexable;
use traits::util::Swappable; use traits::util::Swappable;
@ -26,3 +28,25 @@ pub trait Coordinate
+ Swappable<S, Slice> + Swappable<S, Slice>
{ {
} }
macro_rules! impl_coordinate_binop(
($Self:ty, $Other:ty, $Result:ty, $Op:ident, $op:ident) => (
impl<S: Field> $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<S: Field> $Op<$Result> for $Self {
#[inline(always)]
fn $op(&self) -> $Result {
self.map(|a| a.$op())
}
}
)
)

View file

@ -17,7 +17,7 @@ use traits::alg::Ring;
/// A commutative ring that contains a multiplicative inverse. /// A commutative ring that contains a multiplicative inverse.
pub trait Field pub trait Field
: Ring : Ring<Self>
+ Div<Self,Self> + Div<Self,Self>
+ Rem<Self,Self> + Rem<Self,Self>
{ {

View file

@ -13,18 +13,61 @@
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
use traits::alg::Coordinate;
use traits::alg::Field; use traits::alg::Field;
use traits::alg::Ring; use traits::alg::Ring;
use traits::alg::VectorSpace; use traits::alg::VectorSpace;
use traits::util::Indexable;
pub trait Matrix pub trait Matrix
< <
S: Field, S: Field + Clone,
RV: VectorSpace<S>, RV: Clone + VectorSpace<S> + Coordinate<S, RVSlice>, RVSlice, RSlice,
CV: VectorSpace<S>, CV: Clone + VectorSpace<S> + Coordinate<S, CVSlice>, CVSlice, CSlice,
MT//: Matrix<S, CV, RV, Self> MT//: Matrix<S, CV, CSlice, RV, RSlice, Self>
> >
: Ring : Ring<S>
+ Indexable<CV, RSlice>
{ {
#[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; fn transpose(&self) -> MT;
} }

View file

@ -13,6 +13,8 @@
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
#[macro_escape];
pub use self::affine_space::AffineSpace; pub use self::affine_space::AffineSpace;
pub use self::coordinate::Coordinate; pub use self::coordinate::Coordinate;
pub use self::euclidean_space::EuclideanSpace; pub use self::euclidean_space::EuclideanSpace;

View file

@ -17,23 +17,26 @@ use traits::alg::Ring;
/// A ring that can also be ordered. /// A ring that can also be ordered.
pub trait OrderedRing pub trait OrderedRing
: Ring <
S
>
: Ring<S>
+ Orderable + Orderable
{ {
} }
// impls for concrete types // impls for concrete types
impl OrderedRing for u8; impl OrderedRing<u8> for u8;
impl OrderedRing for u16; impl OrderedRing<u16> for u16;
impl OrderedRing for u32; impl OrderedRing<u32> for u32;
impl OrderedRing for u64; impl OrderedRing<u64> for u64;
impl OrderedRing for uint; impl OrderedRing<uint> for uint;
impl OrderedRing for i8; impl OrderedRing<i8> for i8;
impl OrderedRing for i16; impl OrderedRing<i16> for i16;
impl OrderedRing for i32; impl OrderedRing<i32> for i32;
impl OrderedRing for i64; impl OrderedRing<i64> for i64;
impl OrderedRing for int; impl OrderedRing<int> for int;
impl OrderedRing for f32; impl OrderedRing<f32> for f32;
impl OrderedRing for f64; impl OrderedRing<f64> for f64;
impl OrderedRing for float; impl OrderedRing<float> for float;

View file

@ -20,7 +20,10 @@ use traits::alg::Module;
/// A module that also requires the additive inverse operation (subtraction) /// A module that also requires the additive inverse operation (subtraction)
/// and the additive inverse. /// and the additive inverse.
pub trait Ring pub trait Ring
: Module<Self> <
S
>
: Module<S>
+ Neg<Self> + Neg<Self>
+ Sub<Self,Self> + Sub<Self,Self>
+ One + One
@ -29,16 +32,16 @@ pub trait Ring
// impls for concrete types // impls for concrete types
impl Ring for u8; impl Ring<u8> for u8;
impl Ring for u16; impl Ring<u16> for u16;
impl Ring for u32; impl Ring<u32> for u32;
impl Ring for u64; impl Ring<u64> for u64;
impl Ring for uint; impl Ring<uint> for uint;
impl Ring for i8; impl Ring<i8> for i8;
impl Ring for i16; impl Ring<i16> for i16;
impl Ring for i32; impl Ring<i32> for i32;
impl Ring for i64; impl Ring<i64> for i64;
impl Ring for int; impl Ring<int> for int;
impl Ring for f32; impl Ring<f32> for f32;
impl Ring for f64; impl Ring<f64> for f64;
impl Ring for float; impl Ring<float> for float;

View file

@ -13,6 +13,8 @@
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
#[macro_escape];
// use traits::alg::Field; // use traits::alg::Field;
/// Enforces the multiplication of an type by a scalar. /// Enforces the multiplication of an type by a scalar.
@ -41,3 +43,12 @@ impl ScalarMul<int> for int;
impl ScalarMul<f32> for f32; impl ScalarMul<f32> for f32;
impl ScalarMul<f64> for f64; impl ScalarMul<f64> for f64;
impl ScalarMul<float> for float; impl ScalarMul<float> for float;
macro_rules! impl_scalar_binop(
($Self:ty, $Op:ident, $op:ident) => (
impl<S: Field> $Op<S, $Self> for $Self {
#[inline(always)]
fn $op(&self, s: &S) -> $Self { self.map(|x| x.$op(s)) }
}
)
)

View file

@ -20,9 +20,10 @@ use traits::alg::VectorSpace;
pub trait SquareMatrix pub trait SquareMatrix
< <
S: Field, S: Field,
V: VectorSpace<S> V: VectorSpace<S>,
VVSlice, VSlice
> >
: Matrix<S, V, V, Self> : Matrix<S, V, VVSlice, VSlice, V, VVSlice, VSlice, Self>
{ {
fn transpose_self(&mut self); fn transpose_self(&mut self);
fn trace(&self) -> S; fn trace(&self) -> S;

View file

@ -61,8 +61,8 @@ pub trait Indexable<T, Slice> {
} }
macro_rules! impl_indexable( macro_rules! impl_indexable(
($Self:ty, [$T:ident, ..$n:expr]) => ( ($Self:ty, [$T:ty, ..$n:expr]) => (
impl<$T> Indexable<$T, [$T,..$n]> for $Self { impl<T> Indexable<$T, [$T,..$n]> for $Self {
#[inline] #[inline]
fn len(&self) -> uint { $n } fn len(&self) -> uint { $n }

View file

@ -13,8 +13,228 @@
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
use types::vector::{Vec2, Vec3, Vec4}; use std::num::{One, one, zero};
#[deriving(Clone, Eq)] pub struct Mat2<T> { x: Vec2<T>, y: Vec2<T> } use traits::alg::*;
#[deriving(Clone, Eq)] pub struct Mat3<T> { x: Vec3<T>, y: Vec3<T>, z: Vec3<T> } use traits::util::*;
#[deriving(Clone, Eq)] pub struct Mat4<T> { x: Vec4<T>, y: Vec4<T>, z: Vec4<T>, w: Vec4<T> } use types::vector::*;
#[deriving(Clone, Eq, Zero)] pub struct Mat2<S> { x: Vec2<S>, y: Vec2<S> }
#[deriving(Clone, Eq, Zero)] pub struct Mat3<S> { x: Vec3<S>, y: Vec3<S>, z: Vec3<S> }
#[deriving(Clone, Eq, Zero)] pub struct Mat4<S> { x: Vec4<S>, y: Vec4<S>, z: Vec4<S>, w: Vec4<S> }
// Constructors
impl<S: Field> Mat2<S> {
#[inline]
pub fn new(c0r0: S, c0r1: S,
c1r0: S, c1r1: S) -> Mat2<S> {
Mat2::from_cols(Vec2::new(c0r0, c0r1),
Vec2::new(c1r0, c1r1))
}
#[inline]
pub fn from_cols(c0: Vec2<S>, c1: Vec2<S>) -> Mat2<S> {
Mat2 { x: c0, y: c1 }
}
}
impl<S: Field> Mat3<S> {
#[inline]
pub fn new(c0r0:S, c0r1:S, c0r2:S,
c1r0:S, c1r1:S, c1r2:S,
c2r0:S, c2r1:S, c2r2:S) -> Mat3<S> {
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<S>, c1: Vec3<S>, c2: Vec3<S>) -> Mat3<S> {
Mat3 { x: c0, y: c1, z: c2 }
}
}
impl<S: Field> Mat4<S> {
#[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<S> {
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<S>, c1: Vec4<S>, c2: Vec4<S>, c3: Vec4<S>) -> Mat4<S> {
Mat4 { x: c0, y: c1, z: c2, w: c3 }
}
}
// Trait impls
impl_indexable!(Mat2<T>, [Vec2<T>, ..2])
impl_indexable!(Mat3<T>, [Vec3<T>, ..3])
impl_indexable!(Mat4<T>, [Vec4<T>, ..4])
impl<S: Clone + Field> Swappable<Vec2<S>, [Vec2<S>, ..2]> for Mat2<S>;
impl<S: Clone + Field> Swappable<Vec3<S>, [Vec3<S>, ..3]> for Mat3<S>;
impl<S: Clone + Field> Swappable<Vec4<S>, [Vec4<S>, ..4]> for Mat4<S>;
impl_scalar_binop!(Mat2<S>, Mul, mul)
impl_scalar_binop!(Mat3<S>, Mul, mul)
impl_scalar_binop!(Mat4<S>, Mul, mul)
impl_scalar_binop!(Mat2<S>, Div, div)
impl_scalar_binop!(Mat3<S>, Div, div)
impl_scalar_binop!(Mat4<S>, Div, div)
impl_scalar_binop!(Mat2<S>, Rem, rem)
impl_scalar_binop!(Mat3<S>, Rem, rem)
impl_scalar_binop!(Mat4<S>, Rem, rem)
impl<S: Field> ScalarMul<S> for Mat2<S>;
impl<S: Field> ScalarMul<S> for Mat3<S>;
impl<S: Field> ScalarMul<S> for Mat4<S>;
impl_coordinate_binop!(Mat2<S>, Mat2<S>, Mat2<S>, Add, add)
impl_coordinate_binop!(Mat3<S>, Mat3<S>, Mat3<S>, Add, add)
impl_coordinate_binop!(Mat4<S>, Mat4<S>, Mat4<S>, Add, add)
impl_coordinate_binop!(Mat2<S>, Mat2<S>, Mat2<S>, Sub, sub)
impl_coordinate_binop!(Mat3<S>, Mat3<S>, Mat3<S>, Sub, sub)
impl_coordinate_binop!(Mat4<S>, Mat4<S>, Mat4<S>, Sub, sub)
impl_coordinate_op!(Mat2<S>, Mat2<S>, Neg, neg)
impl_coordinate_op!(Mat3<S>, Mat3<S>, Neg, neg)
impl_coordinate_op!(Mat4<S>, Mat4<S>, Neg, neg)
impl<S: Field> Module<S> for Mat2<S>;
impl<S: Field> Module<S> for Mat3<S>;
impl<S: Field> Module<S> for Mat4<S>;
impl<S: Field> One for Mat2<S> {
fn one() -> Mat2<S> {
Mat2::new(one(), zero(),
zero(), one())
}
}
impl<S: Field> One for Mat3<S> {
fn one() -> Mat3<S> {
Mat3::new(one(), zero(), zero(),
zero(), one(), zero(),
zero(), zero(), one())
}
}
impl<S: Field> One for Mat4<S> {
fn one() -> Mat4<S> {
Mat4::new(one(), zero(), zero(), zero(),
zero(), one(), zero(), zero(),
zero(), zero(), one(), zero(),
zero(), zero(), zero(), one())
}
}
impl<S: Field> Ring<S> for Mat2<S>;
impl<S: Field> Ring<S> for Mat3<S>;
impl<S: Field> Ring<S> for Mat4<S>;
impl
<S: Clone + Field>
Matrix
<
S,
Vec2<S>, [S, ..2], [Vec2<S>, ..2],
Vec2<S>, [S, ..2], [Vec2<S>, ..2],
Mat2<S>
>
for Mat2<S>
{
#[inline]
fn r(&self, r: uint) -> Vec2<S> {
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<S> {
Mat2::new(self.cr(0, 0).clone(), self.cr(1, 0).clone(),
self.cr(0, 1).clone(), self.cr(1, 1).clone())
}
}
impl
<S: Clone + Field>
Matrix
<
S,
Vec3<S>, [S, ..3], [Vec3<S>, ..3],
Vec3<S>, [S, ..3], [Vec3<S>, ..3],
Mat3<S>
>
for Mat3<S>
{
#[inline]
fn r(&self, r: uint) -> Vec3<S> {
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<S> {
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
<S: Clone + Field>
Matrix
<
S,
Vec4<S>, [S, ..4], [Vec4<S>, ..4],
Vec4<S>, [S, ..4], [Vec4<S>, ..4],
Mat4<S>
>
for Mat4<S>
{
#[inline]
fn r(&self, r: uint) -> Vec4<S> {
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<S> {
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())
}
}

View file

@ -35,6 +35,10 @@ macro_rules! impl_vec(
pub fn new($($field: $S),+) -> $Self<$S> { pub fn new($($field: $S),+) -> $Self<$S> {
$Self { $($field: $field),+ } $Self { $($field: $field),+ }
} }
/// The additive identity of the vector.
#[inline]
pub fn zero() -> $Self<$S> { zero() }
} }
) )
) )
@ -65,23 +69,6 @@ impl_vec_clonable!(Vec4<S>)
impl_vec_clonable!(Vec5<S>) impl_vec_clonable!(Vec5<S>)
impl_vec_clonable!(Vec6<S>) impl_vec_clonable!(Vec6<S>)
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<S>)
impl_vec_ring!(Vec2<S>)
impl_vec_ring!(Vec3<S>)
impl_vec_ring!(Vec4<S>)
impl_vec_ring!(Vec5<S>)
impl_vec_ring!(Vec6<S>)
// Operator impls // Operator impls
macro_rules! impl_vec_ops( macro_rules! impl_vec_ops(
@ -90,35 +77,12 @@ macro_rules! impl_vec_ops(
use super::*; use super::*;
use super::super::super::traits::alg::*; use super::super::super::traits::alg::*;
impl<$S:Field> Mul<$S, $Self<$S>> for $Self<$S> { impl_scalar_binop!($Self<$S>, Mul, mul)
#[inline(always)] impl_scalar_binop!($Self<$S>, Div, div)
fn mul(&self, s: &$S) -> $Self<$S> { self.map(|x| x.mul(s)) } 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<$S:Field> Div<$S, $Self<$S>> for $Self<$S> { impl_coordinate_op!($Self<$S>, $Self<$S>, Neg, neg)
#[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()) }
}
} }
) )
) )
@ -150,12 +114,12 @@ impl<S: Field> Vec3<S> {
// Trait impls // Trait impls
impl_indexable!(Vec1<S>, [S, ..1]) impl_indexable!(Vec1<T>, [T, ..1])
impl_indexable!(Vec2<S>, [S, ..2]) impl_indexable!(Vec2<T>, [T, ..2])
impl_indexable!(Vec3<S>, [S, ..3]) impl_indexable!(Vec3<T>, [T, ..3])
impl_indexable!(Vec4<S>, [S, ..4]) impl_indexable!(Vec4<T>, [T, ..4])
impl_indexable!(Vec5<S>, [S, ..5]) impl_indexable!(Vec5<T>, [T, ..5])
impl_indexable!(Vec6<S>, [S, ..6]) impl_indexable!(Vec6<T>, [T, ..6])
impl<S: Clone + Field> Swappable<S, [S, ..1]> for Vec1<S>; impl<S: Clone + Field> Swappable<S, [S, ..1]> for Vec1<S>;
impl<S: Clone + Field> Swappable<S, [S, ..2]> for Vec2<S>; impl<S: Clone + Field> Swappable<S, [S, ..2]> for Vec2<S>;