From 2976de3ff4e9e30a8ab3a41a5fe72aecf18c7e2f Mon Sep 17 00:00:00 2001 From: Brendan Zabarauskas Date: Wed, 28 Aug 2013 12:03:43 +1000 Subject: [PATCH] 'Array' is a better mathematical name for Indexable --- .../{util/indexable.rs => alg/array.rs} | 57 ++++++-- src/cgmath/traits/alg/coordinate.rs | 55 -------- src/cgmath/traits/alg/matrix.rs | 10 +- src/cgmath/traits/alg/mod.rs | 4 +- src/cgmath/traits/ext/vector_ext.rs | 4 +- src/cgmath/traits/mod.rs | 9 -- src/cgmath/traits/util/mod.rs | 22 --- src/cgmath/traits/util/swappable.rs | 26 ---- src/cgmath/types/matrix.rs | 133 +++++++++++++++--- src/cgmath/types/point.rs | 20 ++- src/cgmath/types/vector.rs | 15 +- 11 files changed, 186 insertions(+), 169 deletions(-) rename src/cgmath/traits/{util/indexable.rs => alg/array.rs} (55%) delete mode 100644 src/cgmath/traits/alg/coordinate.rs delete mode 100644 src/cgmath/traits/util/mod.rs delete mode 100644 src/cgmath/traits/util/swappable.rs diff --git a/src/cgmath/traits/util/indexable.rs b/src/cgmath/traits/alg/array.rs similarity index 55% rename from src/cgmath/traits/util/indexable.rs rename to src/cgmath/traits/alg/array.rs index cefa748..83f2c15 100644 --- a/src/cgmath/traits/util/indexable.rs +++ b/src/cgmath/traits/alg/array.rs @@ -15,8 +15,7 @@ #[macro_escape]; -/// Types that can be accessed via an unsigned index. -pub trait Indexable { +pub trait Array { fn len(&self) -> uint; fn i<'a>(&'a self, i: uint) -> &'a T; fn mut_i<'a>(&'a mut self, i: uint) -> &'a mut T; @@ -26,8 +25,8 @@ pub trait Indexable { fn build(builder: &fn(i: uint) -> T) -> Self; #[inline] - fn map>(&self, f: &fn(&T) -> U) -> UU { - Indexable::build(|i| f(self.i(i))) + fn map>(&self, f: &fn(&T) -> U) -> UU { + Array::build(|i| f(self.i(i))) } #[inline] @@ -38,13 +37,13 @@ pub trait Indexable { } #[inline] - fn bimap, - V, SliceV, VV: Indexable>(&self, other: &UU, f: &fn(&T, &U) -> V) -> VV { - Indexable::build(|i| f(self.i(i), other.i(i))) + fn bimap, + V, SliceV, VV: Array>(&self, other: &UU, f: &fn(&T, &U) -> V) -> VV { + Array::build(|i| f(self.i(i), other.i(i))) } #[inline] - fn bimap_mut>(&mut self, other: &UU, f: &fn(&mut T, &U)) { + fn bimap_mut>(&mut self, other: &UU, f: &fn(&mut T, &U)) { for i in range(0, self.len()) { f(self.mut_i(i), other.i(i)); } @@ -60,9 +59,9 @@ pub trait Indexable { } } -macro_rules! indexable( +macro_rules! array( (impl<$S:ident> $Self:ty -> [$T:ty, ..$n:expr]) => ( - impl<$S> Indexable<$T, [$T,..$n]> for $Self { + impl<$S> Array<$T, [$T,..$n]> for $Self { #[inline] fn len(&self) -> uint { $n } @@ -98,8 +97,44 @@ macro_rules! indexable( for i in range::(0, $n) { s[i] = builder(i); } - Indexable::from_slice(s) + Array::from_slice(s) } } ) ) + +macro_rules! array_op( + (impl<$S:ident> ($Op:ident, $op:ident) for ($Self:ty, $Other:ty) -> $Result:ty) => ( + impl<$S: Field> $Op<$Other, $Result> for $Self { + #[inline(always)] + fn $op(&self, other: &$Other) -> $Result { + self.bimap(other, |a, b| a.$op(b)) + } + } + ); + (impl<$S:ident> ($Op:ident, $op:ident) for $Self:ty -> $Result:ty) => ( + impl<$S: Field> $Op<$Result> for $Self { + #[inline(always)] + fn $op(&self) -> $Result { + self.map(|a| a.$op()) + } + } + ); + (impl<$S:ident> -$Self:ty -> $Result:ty) => (array_op!(impl<$S> (Neg, neg) for $Self -> $Result)); + (impl<$S:ident> $Self:ty + $Other:ty -> $Result:ty) => (array_op!(impl<$S> (Add, add) for ($Self, $Other) -> $Result)); + (impl<$S:ident> $Self:ty - $Other:ty -> $Result:ty) => (array_op!(impl<$S> (Sub, sub) for ($Self, $Other) -> $Result)); + (impl<$S:ident> $Self:ty * $Other:ty -> $Result:ty) => (array_op!(impl<$S> (Mul, mul) for ($Self, $Other) -> $Result)); + (impl<$S:ident> $Self:ty / $Other:ty -> $Result:ty) => (array_op!(impl<$S> (Div, div) for ($Self, $Other) -> $Result)); + (impl<$S:ident> $Self:ty % $Other:ty -> $Result:ty) => (array_op!(impl<$S> (Rem, rem) for ($Self, $Other) -> $Result)); +) + +/// An `Array` whose elements can be cloned +pub trait ClonableArray: Array { + /// Swap two elements of the type in place. + #[inline] + fn swap(&mut self, a: uint, b: uint) { + let tmp = self.i(a).clone(); + *self.mut_i(a) = self.i(b).clone(); + *self.mut_i(b) = tmp; + } +} diff --git a/src/cgmath/traits/alg/coordinate.rs b/src/cgmath/traits/alg/coordinate.rs deleted file mode 100644 index f5c28c7..0000000 --- a/src/cgmath/traits/alg/coordinate.rs +++ /dev/null @@ -1,55 +0,0 @@ -// Copyright 2013 The CGMath Developers. For a full listing of the authors, -// refer to the AUTHORS file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// 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; - -pub trait Coordinate -< - S: Field, - Slice -> -: Indexable -+ Swappable -{ -} - -macro_rules! coordinate_op( - (impl<$S:ident> ($Op:ident, $op:ident) for ($Self:ty, $Other:ty) -> $Result:ty) => ( - impl<$S: Field> $Op<$Other, $Result> for $Self { - #[inline(always)] - fn $op(&self, other: &$Other) -> $Result { - self.bimap(other, |a, b| a.$op(b)) - } - } - ); - (impl<$S:ident> ($Op:ident, $op:ident) for $Self:ty -> $Result:ty) => ( - impl<$S: Field> $Op<$Result> for $Self { - #[inline(always)] - fn $op(&self) -> $Result { - self.map(|a| a.$op()) - } - } - ); - (impl<$S:ident> -$Self:ty -> $Result:ty) => (coordinate_op!(impl<$S> (Neg, neg) for $Self -> $Result)); - (impl<$S:ident> $Self:ty + $Other:ty -> $Result:ty) => (coordinate_op!(impl<$S> (Add, add) for ($Self, $Other) -> $Result)); - (impl<$S:ident> $Self:ty - $Other:ty -> $Result:ty) => (coordinate_op!(impl<$S> (Sub, sub) for ($Self, $Other) -> $Result)); - (impl<$S:ident> $Self:ty * $Other:ty -> $Result:ty) => (coordinate_op!(impl<$S> (Mul, mul) for ($Self, $Other) -> $Result)); - (impl<$S:ident> $Self:ty / $Other:ty -> $Result:ty) => (coordinate_op!(impl<$S> (Div, div) for ($Self, $Other) -> $Result)); - (impl<$S:ident> $Self:ty % $Other:ty -> $Result:ty) => (coordinate_op!(impl<$S> (Rem, rem) for ($Self, $Other) -> $Result)); -) diff --git a/src/cgmath/traits/alg/matrix.rs b/src/cgmath/traits/alg/matrix.rs index df23e55..7f201e2 100644 --- a/src/cgmath/traits/alg/matrix.rs +++ b/src/cgmath/traits/alg/matrix.rs @@ -13,21 +13,21 @@ // See the License for the specific language governing permissions and // limitations under the License. -use traits::alg::Coordinate; +use traits::alg::Array; +use traits::alg::ClonableArray; use traits::alg::Field; use traits::alg::Ring; use traits::alg::VectorSpace; -use traits::util::Indexable; pub trait Matrix < S: Field + Clone, - RV: Clone + VectorSpace + Coordinate, RVSlice, RSlice, - CV: Clone + VectorSpace + Coordinate, CVSlice, CSlice, + RV: Clone + VectorSpace + ClonableArray, RVSlice, RSlice, + CV: Clone + VectorSpace + ClonableArray, CVSlice, CSlice, MT//: Matrix > : Ring -+ Indexable ++ ClonableArray { #[inline] fn c<'a>(&'a self, c: uint) -> &'a CV { self.i(c) } diff --git a/src/cgmath/traits/alg/mod.rs b/src/cgmath/traits/alg/mod.rs index 23c810a..aae24bb 100644 --- a/src/cgmath/traits/alg/mod.rs +++ b/src/cgmath/traits/alg/mod.rs @@ -16,7 +16,7 @@ #[macro_escape]; pub use self::affine_space::AffineSpace; -pub use self::coordinate::Coordinate; +pub use self::array::{Array, ClonableArray}; pub use self::euclidean_space::EuclideanSpace; pub use self::field::Field; pub use self::inner_product_space::InnerProductSpace; @@ -29,7 +29,7 @@ pub use self::square_matrix::SquareMatrix; pub use self::vector_space::VectorSpace; pub mod affine_space; -pub mod coordinate; +pub mod array; pub mod euclidean_space; pub mod field; pub mod inner_product_space; diff --git a/src/cgmath/traits/ext/vector_ext.rs b/src/cgmath/traits/ext/vector_ext.rs index cee534e..afeba38 100644 --- a/src/cgmath/traits/ext/vector_ext.rs +++ b/src/cgmath/traits/ext/vector_ext.rs @@ -15,7 +15,7 @@ use traits::alg::Field; use traits::alg::VectorSpace; -use traits::util::Indexable; +use traits::alg::Array; pub trait VectorExt < @@ -23,7 +23,7 @@ pub trait VectorExt Slice > : VectorSpace -+ Indexable ++ Array { #[inline] fn add_s(&self, s: S) -> Self { self.map(|x| x.add(&s)) } #[inline] fn sub_s(&self, s: S) -> Self { self.map(|x| x.sub(&s)) } diff --git a/src/cgmath/traits/mod.rs b/src/cgmath/traits/mod.rs index 67675ce..c767862 100644 --- a/src/cgmath/traits/mod.rs +++ b/src/cgmath/traits/mod.rs @@ -34,12 +34,3 @@ pub mod alg; /// use lmath::traits::ext::*; /// ~~~ pub mod ext; - -/// TODO -/// -/// # Example -/// -/// ~~~rust -/// use lmath::traits::util::*; -/// ~~~ -pub mod util; diff --git a/src/cgmath/traits/util/mod.rs b/src/cgmath/traits/util/mod.rs deleted file mode 100644 index ead05d2..0000000 --- a/src/cgmath/traits/util/mod.rs +++ /dev/null @@ -1,22 +0,0 @@ -// Copyright 2013 The OMath Developers. For a full listing of the authors, -// refer to the AUTHORS file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#[macro_escape]; - -pub use self::indexable::Indexable; -pub use self::swappable::Swappable; - -pub mod indexable; -pub mod swappable; diff --git a/src/cgmath/traits/util/swappable.rs b/src/cgmath/traits/util/swappable.rs deleted file mode 100644 index 8b0d62c..0000000 --- a/src/cgmath/traits/util/swappable.rs +++ /dev/null @@ -1,26 +0,0 @@ -// Copyright 2013 The OMath Developers. For a full listing of the authors, -// refer to the AUTHORS file at the top-level directory of this distribution. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -use traits::util::Indexable; - -pub trait Swappable: Indexable { - /// Swap two elements of the type in place. - #[inline] - fn swap(&mut self, a: uint, b: uint) { - let tmp = self.i(a).clone(); - *self.mut_i(a) = self.i(b).clone(); - *self.mut_i(b) = tmp; - } -} diff --git a/src/cgmath/types/matrix.rs b/src/cgmath/types/matrix.rs index 5a3d428..dd6e1b4 100644 --- a/src/cgmath/types/matrix.rs +++ b/src/cgmath/types/matrix.rs @@ -16,7 +16,6 @@ use std::num::{One, one, zero}; use traits::alg::*; -use traits::util::*; use types::vector::*; #[deriving(Clone, Eq, Zero)] pub struct Mat2 { x: Vec2, y: Vec2 } @@ -75,13 +74,13 @@ impl Mat4 { // Trait impls -indexable!(impl Mat2 -> [Vec2, ..2]) -indexable!(impl Mat3 -> [Vec3, ..3]) -indexable!(impl Mat4 -> [Vec4, ..4]) +array!(impl Mat2 -> [Vec2, ..2]) +array!(impl Mat3 -> [Vec3, ..3]) +array!(impl Mat4 -> [Vec4, ..4]) -impl Swappable, [Vec2, ..2]> for Mat2; -impl Swappable, [Vec3, ..3]> for Mat3; -impl Swappable, [Vec4, ..4]> for Mat4; +impl ClonableArray, [Vec2, ..2]> for Mat2; +impl ClonableArray, [Vec3, ..3]> for Mat3; +impl ClonableArray, [Vec4, ..4]> for Mat4; scalar_op!(impl Mat2 * S -> Mat2) scalar_op!(impl Mat3 * S -> Mat3) @@ -97,15 +96,15 @@ impl ScalarMul for Mat2; impl ScalarMul for Mat3; impl ScalarMul for Mat4; -coordinate_op!(impl Mat2 + Mat2 -> Mat2) -coordinate_op!(impl Mat3 + Mat3 -> Mat3) -coordinate_op!(impl Mat4 + Mat4 -> Mat4) -coordinate_op!(impl Mat2 - Mat2 -> Mat2) -coordinate_op!(impl Mat3 - Mat3 -> Mat3) -coordinate_op!(impl Mat4 - Mat4 -> Mat4) -coordinate_op!(impl -Mat2 -> Mat2) -coordinate_op!(impl -Mat3 -> Mat3) -coordinate_op!(impl -Mat4 -> Mat4) +array_op!(impl Mat2 + Mat2 -> Mat2) +array_op!(impl Mat3 + Mat3 -> Mat3) +array_op!(impl Mat4 + Mat4 -> Mat4) +array_op!(impl Mat2 - Mat2 -> Mat2) +array_op!(impl Mat3 - Mat3 -> Mat3) +array_op!(impl Mat4 - Mat4 -> Mat4) +array_op!(impl -Mat2 -> Mat2) +array_op!(impl -Mat3 -> Mat3) +array_op!(impl -Mat4 -> Mat4) impl Module for Mat2; impl Module for Mat3; @@ -213,3 +212,105 @@ for Mat4 self.cr(0, 3).clone(), self.cr(1, 3).clone(), self.cr(2, 3).clone(), self.cr(3, 3).clone()) } } + +impl +SquareMatrix, [S, ..2], [Vec2, ..2]> +for Mat2 +{ + #[inline] + fn transpose_self(&mut self) { + self.swap_cr((0, 1), (1, 0)); + } + + #[inline] + fn trace(&self) -> S { + *self.cr(0, 0) + *self.cr(1, 1) + } + + #[inline] + fn det(&self) -> S { + *self.cr(0, 0) * *self.cr(1, 1) - *self.cr(1, 0) * *self.cr(0, 1) + } + + fn invert(&self) -> Option> { fail!() } + + fn invert_self(&mut self) -> Mat2 { fail!() } + + fn is_invertable(&self) -> bool { fail!() } +} + +impl +SquareMatrix, [S, ..3], [Vec3, ..3]> +for Mat3 +{ + #[inline] + fn transpose_self(&mut self) { + self.swap_cr((0, 1), (1, 0)); + self.swap_cr((0, 2), (2, 0)); + self.swap_cr((1, 2), (2, 1)); + } + + #[inline] + fn trace(&self) -> S { + *self.cr(0, 0) + *self.cr(1, 1) + *self.cr(2, 2) + } + + fn det(&self) -> S { + *self.cr(0, 0) * (*self.cr(1, 1) * *self.cr(2, 2) - *self.cr(2, 1) * *self.cr(1, 2)) - + *self.cr(1, 0) * (*self.cr(0, 1) * *self.cr(2, 2) - *self.cr(2, 1) * *self.cr(0, 2)) + + *self.cr(2, 0) * (*self.cr(0, 1) * *self.cr(1, 2) - *self.cr(1, 1) * *self.cr(0, 2)) + } + + fn invert(&self) -> Option> { fail!() } + + fn invert_self(&mut self) -> Mat3 { fail!() } + + fn is_invertable(&self) -> bool { fail!() } +} + +impl +SquareMatrix, [S, ..4], [Vec4, ..4]> +for Mat4 +{ + #[inline] + fn transpose_self(&mut self) { + self.swap_cr((0, 1), (1, 0)); + self.swap_cr((0, 2), (2, 0)); + self.swap_cr((0, 3), (3, 0)); + self.swap_cr((1, 2), (2, 1)); + self.swap_cr((1, 3), (3, 1)); + self.swap_cr((2, 3), (3, 2)); + } + + #[inline] + fn trace(&self) -> S { + *self.cr(0, 0) + *self.cr(1, 1) + *self.cr(2, 2) + *self.cr(3, 3) + } + + fn det(&self) -> S { + let m0 = Mat3::new(self.cr(1, 1).clone(), self.cr(2, 1).clone(), self.cr(3, 1).clone(), + self.cr(1, 2).clone(), self.cr(2, 2).clone(), self.cr(3, 2).clone(), + self.cr(1, 3).clone(), self.cr(2, 3).clone(), self.cr(3, 3).clone()); + let m1 = Mat3::new(self.cr(0, 1).clone(), self.cr(2, 1).clone(), self.cr(3, 1).clone(), + self.cr(0, 2).clone(), self.cr(2, 2).clone(), self.cr(3, 2).clone(), + self.cr(0, 3).clone(), self.cr(2, 3).clone(), self.cr(3, 3).clone()); + let m2 = Mat3::new(self.cr(0, 1).clone(), self.cr(1, 1).clone(), self.cr(3, 1).clone(), + self.cr(0, 2).clone(), self.cr(1, 2).clone(), self.cr(3, 2).clone(), + self.cr(0, 3).clone(), self.cr(1, 3).clone(), self.cr(3, 3).clone()); + let m3 = Mat3::new(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(), + self.cr(0, 3).clone(), self.cr(1, 3).clone(), self.cr(2, 3).clone()); + + self.cr(0, 0) * m0.det() - + self.cr(1, 0) * m1.det() + + self.cr(2, 0) * m2.det() - + self.cr(3, 0) * m3.det() + } + + fn invert(&self) -> Option> { fail!() } + + fn invert_self(&mut self) -> Mat4 { fail!() } + + fn is_invertable(&self) -> bool { fail!() } +} + diff --git a/src/cgmath/types/point.rs b/src/cgmath/types/point.rs index 76fc601..4aff737 100644 --- a/src/cgmath/types/point.rs +++ b/src/cgmath/types/point.rs @@ -18,7 +18,6 @@ //! not have a fixed position. use traits::alg::*; -use traits::util::*; use types::vector::{Vec2, Vec3}; #[deriving(Eq, Zero, Clone)] @@ -41,14 +40,11 @@ impl Point3 { } } -indexable!(impl Point2 -> [S, ..2]) -indexable!(impl Point3 -> [S, ..3]) +array!(impl Point2 -> [S, ..2]) +array!(impl Point3 -> [S, ..3]) -impl Swappable for Point2; -impl Swappable for Point3; - -impl Coordinate for Point2; -impl Coordinate for Point3; +impl ClonableArray for Point2; +impl ClonableArray for Point3; scalar_op!(impl Point2 * S -> Point2) scalar_op!(impl Point3 * S -> Point3) @@ -60,10 +56,10 @@ scalar_op!(impl Point3 % S -> Point3) impl ScalarMul for Point2; impl ScalarMul for Point3; -coordinate_op!(impl Point2 + Vec2 -> Point2) -coordinate_op!(impl Point3 + Vec3 -> Point3) -coordinate_op!(impl Point2 - Point2 -> Vec2) -coordinate_op!(impl Point3 - Point3 -> Vec3) +array_op!(impl Point2 + Vec2 -> Point2) +array_op!(impl Point3 + Vec3 -> Point3) +array_op!(impl Point2 - Point2 -> Vec2) +array_op!(impl Point3 - Point3 -> Vec3) impl AffineSpace> for Point2; impl AffineSpace> for Point3; diff --git a/src/cgmath/types/vector.rs b/src/cgmath/types/vector.rs index b3118ba..3454006 100644 --- a/src/cgmath/types/vector.rs +++ b/src/cgmath/types/vector.rs @@ -18,7 +18,6 @@ use std::num::{Zero, zero}; use std::num::{sqrt, atan2}; use traits::alg::*; -use traits::util::*; #[deriving(Eq, Zero, Clone)] pub struct Vec1 { x: S } #[deriving(Eq, Zero, Clone)] pub struct Vec2 { x: S, y: S } @@ -55,7 +54,7 @@ macro_rules! impl_vec_clonable( /// Construct a vector from a single value. #[inline] pub fn from_value(value: $S) -> $Self<$S> { - Indexable::build(|_| value.clone()) + Array::build(|_| value.clone()) } } ) @@ -74,18 +73,16 @@ macro_rules! impl_vec_common( use super::*; use traits::alg::*; use traits::ext::*; - use traits::util::*; - indexable!(impl<$S> $Self -> [$S, ..$n]) - impl<$S: Clone + Field> Swappable<$S, [$S, ..$n]> for $Self; - impl<$S: Clone + Field> Coordinate<$S, [$S, ..$n]> for $Self; + array!(impl<$S> $Self -> [$S, ..$n]) + impl<$S: Clone + Field> ClonableArray<$S, [$S, ..$n]> for $Self; scalar_op!(impl $Self * $S -> $Self) scalar_op!(impl $Self / $S -> $Self) scalar_op!(impl $Self % $S -> $Self) - coordinate_op!(impl<$S> $Self + $Self -> $Self) - coordinate_op!(impl<$S> $Self - $Self -> $Self) - coordinate_op!(impl<$S> -$Self -> $Self) + array_op!(impl<$S> $Self + $Self -> $Self) + array_op!(impl<$S> $Self - $Self -> $Self) + array_op!(impl<$S> -$Self -> $Self) impl<$S: Field> ScalarMul<$S> for $Self; impl<$S: Field> Module<$S> for $Self;