'Array' is a better mathematical name for Indexable

This commit is contained in:
Brendan Zabarauskas 2013-08-28 12:03:43 +10:00
parent ba8c6ac7d0
commit 2976de3ff4
11 changed files with 186 additions and 169 deletions

View file

@ -15,8 +15,7 @@
#[macro_escape];
/// Types that can be accessed via an unsigned index.
pub trait Indexable<T, Slice> {
pub trait Array<T, Slice> {
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<T, Slice> {
fn build(builder: &fn(i: uint) -> T) -> Self;
#[inline]
fn map<U, SliceU, UU: Indexable<U, SliceU>>(&self, f: &fn(&T) -> U) -> UU {
Indexable::build(|i| f(self.i(i)))
fn map<U, SliceU, UU: Array<U, SliceU>>(&self, f: &fn(&T) -> U) -> UU {
Array::build(|i| f(self.i(i)))
}
#[inline]
@ -38,13 +37,13 @@ pub trait Indexable<T, Slice> {
}
#[inline]
fn bimap<U, SliceU, UU: Indexable<U, SliceU>,
V, SliceV, VV: Indexable<V, SliceV>>(&self, other: &UU, f: &fn(&T, &U) -> V) -> VV {
Indexable::build(|i| f(self.i(i), other.i(i)))
fn bimap<U, SliceU, UU: Array<U, SliceU>,
V, SliceV, VV: Array<V, SliceV>>(&self, other: &UU, f: &fn(&T, &U) -> V) -> VV {
Array::build(|i| f(self.i(i), other.i(i)))
}
#[inline]
fn bimap_mut<U, SliceU, UU: Indexable<U, Slice>>(&mut self, other: &UU, f: &fn(&mut T, &U)) {
fn bimap_mut<U, SliceU, UU: Array<U, Slice>>(&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<T, Slice> {
}
}
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::<uint>(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<T: Clone, Slice>: Array<T, Slice> {
/// 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;
}
}

View file

@ -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<S, Slice>
+ Swappable<S, Slice>
{
}
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));
)

View file

@ -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<S> + Coordinate<S, RVSlice>, RVSlice, RSlice,
CV: Clone + VectorSpace<S> + Coordinate<S, CVSlice>, CVSlice, CSlice,
RV: Clone + VectorSpace<S> + ClonableArray<S, RVSlice>, RVSlice, RSlice,
CV: Clone + VectorSpace<S> + ClonableArray<S, CVSlice>, CVSlice, CSlice,
MT//: Matrix<S, CV, CSlice, RV, RSlice, Self>
>
: Ring<S>
+ Indexable<CV, RSlice>
+ ClonableArray<CV, RSlice>
{
#[inline]
fn c<'a>(&'a self, c: uint) -> &'a CV { self.i(c) }

View file

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

View file

@ -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<S>
+ Indexable<S, Slice>
+ Array<S, Slice>
{
#[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)) }

View file

@ -34,12 +34,3 @@ pub mod alg;
/// use lmath::traits::ext::*;
/// ~~~
pub mod ext;
/// TODO
///
/// # Example
///
/// ~~~rust
/// use lmath::traits::util::*;
/// ~~~
pub mod util;

View file

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

View file

@ -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<T: Clone, Slice>: Indexable<T, Slice> {
/// 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;
}
}

View file

@ -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<S> { x: Vec2<S>, y: Vec2<S> }
@ -75,13 +74,13 @@ impl<S: Field> Mat4<S> {
// Trait impls
indexable!(impl<S> Mat2<S> -> [Vec2<S>, ..2])
indexable!(impl<S> Mat3<S> -> [Vec3<S>, ..3])
indexable!(impl<S> Mat4<S> -> [Vec4<S>, ..4])
array!(impl<S> Mat2<S> -> [Vec2<S>, ..2])
array!(impl<S> Mat3<S> -> [Vec3<S>, ..3])
array!(impl<S> Mat4<S> -> [Vec4<S>, ..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<S: Clone + Field> ClonableArray<Vec2<S>, [Vec2<S>, ..2]> for Mat2<S>;
impl<S: Clone + Field> ClonableArray<Vec3<S>, [Vec3<S>, ..3]> for Mat3<S>;
impl<S: Clone + Field> ClonableArray<Vec4<S>, [Vec4<S>, ..4]> for Mat4<S>;
scalar_op!(impl Mat2<S> * S -> Mat2<S>)
scalar_op!(impl Mat3<S> * S -> Mat3<S>)
@ -97,15 +96,15 @@ impl<S: Field> ScalarMul<S> for Mat2<S>;
impl<S: Field> ScalarMul<S> for Mat3<S>;
impl<S: Field> ScalarMul<S> for Mat4<S>;
coordinate_op!(impl<S> Mat2<S> + Mat2<S> -> Mat2<S>)
coordinate_op!(impl<S> Mat3<S> + Mat3<S> -> Mat3<S>)
coordinate_op!(impl<S> Mat4<S> + Mat4<S> -> Mat4<S>)
coordinate_op!(impl<S> Mat2<S> - Mat2<S> -> Mat2<S>)
coordinate_op!(impl<S> Mat3<S> - Mat3<S> -> Mat3<S>)
coordinate_op!(impl<S> Mat4<S> - Mat4<S> -> Mat4<S>)
coordinate_op!(impl<S> -Mat2<S> -> Mat2<S>)
coordinate_op!(impl<S> -Mat3<S> -> Mat3<S>)
coordinate_op!(impl<S> -Mat4<S> -> Mat4<S>)
array_op!(impl<S> Mat2<S> + Mat2<S> -> Mat2<S>)
array_op!(impl<S> Mat3<S> + Mat3<S> -> Mat3<S>)
array_op!(impl<S> Mat4<S> + Mat4<S> -> Mat4<S>)
array_op!(impl<S> Mat2<S> - Mat2<S> -> Mat2<S>)
array_op!(impl<S> Mat3<S> - Mat3<S> -> Mat3<S>)
array_op!(impl<S> Mat4<S> - Mat4<S> -> Mat4<S>)
array_op!(impl<S> -Mat2<S> -> Mat2<S>)
array_op!(impl<S> -Mat3<S> -> Mat3<S>)
array_op!(impl<S> -Mat4<S> -> Mat4<S>)
impl<S: Field> Module<S> for Mat2<S>;
impl<S: Field> Module<S> for Mat3<S>;
@ -213,3 +212,105 @@ for Mat4<S>
self.cr(0, 3).clone(), self.cr(1, 3).clone(), self.cr(2, 3).clone(), self.cr(3, 3).clone())
}
}
impl<S: Clone + Field>
SquareMatrix<S, Vec2<S>, [S, ..2], [Vec2<S>, ..2]>
for Mat2<S>
{
#[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<Mat2<S>> { fail!() }
fn invert_self(&mut self) -> Mat2<S> { fail!() }
fn is_invertable(&self) -> bool { fail!() }
}
impl<S: Clone + Field>
SquareMatrix<S, Vec3<S>, [S, ..3], [Vec3<S>, ..3]>
for Mat3<S>
{
#[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<Mat3<S>> { fail!() }
fn invert_self(&mut self) -> Mat3<S> { fail!() }
fn is_invertable(&self) -> bool { fail!() }
}
impl<S: Clone + Field>
SquareMatrix<S, Vec4<S>, [S, ..4], [Vec4<S>, ..4]>
for Mat4<S>
{
#[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<Mat4<S>> { fail!() }
fn invert_self(&mut self) -> Mat4<S> { fail!() }
fn is_invertable(&self) -> bool { fail!() }
}

View file

@ -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<S: Field> Point3<S> {
}
}
indexable!(impl<S> Point2<S> -> [S, ..2])
indexable!(impl<S> Point3<S> -> [S, ..3])
array!(impl<S> Point2<S> -> [S, ..2])
array!(impl<S> Point3<S> -> [S, ..3])
impl<S: Clone + Field> Swappable<S, [S, ..2]> for Point2<S>;
impl<S: Clone + Field> Swappable<S, [S, ..3]> for Point3<S>;
impl<S: Clone + Field> Coordinate<S, [S, ..2]> for Point2<S>;
impl<S: Clone + Field> Coordinate<S, [S, ..3]> for Point3<S>;
impl<S: Clone + Field> ClonableArray<S, [S, ..2]> for Point2<S>;
impl<S: Clone + Field> ClonableArray<S, [S, ..3]> for Point3<S>;
scalar_op!(impl Point2<S> * S -> Point2<S>)
scalar_op!(impl Point3<S> * S -> Point3<S>)
@ -60,10 +56,10 @@ scalar_op!(impl Point3<S> % S -> Point3<S>)
impl<S: Field> ScalarMul<S> for Point2<S>;
impl<S: Field> ScalarMul<S> for Point3<S>;
coordinate_op!(impl<S> Point2<S> + Vec2<S> -> Point2<S>)
coordinate_op!(impl<S> Point3<S> + Vec3<S> -> Point3<S>)
coordinate_op!(impl<S> Point2<S> - Point2<S> -> Vec2<S>)
coordinate_op!(impl<S> Point3<S> - Point3<S> -> Vec3<S>)
array_op!(impl<S> Point2<S> + Vec2<S> -> Point2<S>)
array_op!(impl<S> Point3<S> + Vec3<S> -> Point3<S>)
array_op!(impl<S> Point2<S> - Point2<S> -> Vec2<S>)
array_op!(impl<S> Point3<S> - Point3<S> -> Vec3<S>)
impl<S: Field> AffineSpace<S, Vec2<S>> for Point2<S>;
impl<S: Field> AffineSpace<S, Vec3<S>> for Point3<S>;

View file

@ -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<S> { x: S }
#[deriving(Eq, Zero, Clone)] pub struct Vec2<S> { 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;