diff --git a/src/lib.rs b/src/lib.rs index bf12512b..5a052a29 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -151,6 +151,7 @@ pub use traits::{ Row, ScalarAdd, ScalarSub, ScalarMul, ScalarDiv, + Shape, ToHomogeneous, Transform, Transformation, Translate, Translation, @@ -932,6 +933,12 @@ pub fn dim() -> uint { Dim::dim(None::) } +/// Gets the indexable range of an object. +#[inline(always)] +pub fn shape, I, N>(v: &V) -> I { + v.shape() +} + /* * Cast */ diff --git a/src/structs/dmat.rs b/src/structs/dmat.rs index 8eda7f61..f3d0f979 100644 --- a/src/structs/dmat.rs +++ b/src/structs/dmat.rs @@ -10,7 +10,7 @@ use traits::operations::ApproxEq; use std::mem; use structs::dvec::{DVec, DVecMulRhs}; use traits::operations::{Inv, Transpose, Mean, Cov}; -use traits::structure::{Cast, ColSlice, RowSlice, Diag, Eye, Indexable}; +use traits::structure::{Cast, ColSlice, RowSlice, Diag, Eye, Indexable, Shape}; use std::fmt::{Show, Formatter, Result}; @@ -261,10 +261,13 @@ impl Indexable<(uint, uint), N> for DMat { self.mij.as_mut_slice().swap(offset1, offset2); } +} + +impl Shape<(uint, uint), N> for DMat { + #[inline] fn shape(&self) -> (uint, uint) { (self.nrows, self.ncols) } - } impl Index<(uint, uint), N> for DMat { diff --git a/src/structs/dvec.rs b/src/structs/dvec.rs index c300a3d6..b8d9b2b1 100644 --- a/src/structs/dvec.rs +++ b/src/structs/dvec.rs @@ -9,7 +9,7 @@ use std::slice::{Items, MutItems}; use traits::operations::ApproxEq; use std::iter::FromIterator; use traits::geometry::{Dot, Norm}; -use traits::structure::{Iterable, IterableMut, Indexable}; +use traits::structure::{Iterable, IterableMut, Indexable, Shape}; /// Heap allocated, dynamically sized vector. #[deriving(Eq, PartialEq, Show, Clone)] diff --git a/src/structs/dvec_macros.rs b/src/structs/dvec_macros.rs index 0d7cfe4e..c54c98e0 100644 --- a/src/structs/dvec_macros.rs +++ b/src/structs/dvec_macros.rs @@ -44,6 +44,13 @@ macro_rules! dvec_impl( } } + impl Shape for $dvec { + #[inline] + fn shape(&self) -> uint { + self.len() + } + } + impl Indexable for $dvec { #[inline] fn at(&self, i: uint) -> N { @@ -68,11 +75,6 @@ macro_rules! dvec_impl( self.as_mut_slice().swap(i, j); } - #[inline] - fn shape(&self) -> uint { - self.len() - } - #[inline] unsafe fn unsafe_at(&self, i: uint) -> N { (*self.at.as_slice().unsafe_get(i)).clone() diff --git a/src/structs/mat.rs b/src/structs/mat.rs index 9d6b78ba..e7edb3d7 100644 --- a/src/structs/mat.rs +++ b/src/structs/mat.rs @@ -12,7 +12,7 @@ use structs::pnt::{Pnt1, Pnt4, Pnt5, Pnt6, Pnt1MulRhs, Pnt4MulRhs, Pnt5MulRhs, P use structs::dvec::{DVec1, DVec2, DVec3, DVec4, DVec5, DVec6}; use traits::structure::{Cast, Row, Col, Iterable, IterableMut, Dim, Indexable, - Eye, ColSlice, RowSlice, Diag}; + Eye, ColSlice, RowSlice, Diag, Shape}; use traits::operations::{Absolute, Transpose, Inv, Outer}; use traits::geometry::{ToHomogeneous, FromHomogeneous, Orig}; diff --git a/src/structs/mat_macros.rs b/src/structs/mat_macros.rs index 5a5e40f9..c842a45e 100644 --- a/src/structs/mat_macros.rs +++ b/src/structs/mat_macros.rs @@ -184,6 +184,13 @@ macro_rules! dim_impl( macro_rules! indexable_impl( ($t: ident, $dim: expr) => ( + impl Shape<(uint, uint), N> for $t { + #[inline] + fn shape(&self) -> (uint, uint) { + ($dim, $dim) + } + } + impl Indexable<(uint, uint), N> for $t { #[inline] fn at(&self, (i, j): (uint, uint)) -> N { @@ -207,11 +214,6 @@ macro_rules! indexable_impl( } } - #[inline] - fn shape(&self) -> (uint, uint) { - ($dim, $dim) - } - #[inline] unsafe fn unsafe_at(&self, (i, j): (uint, uint)) -> N { (*mem::transmute::<&$t, &[N, ..$dim * $dim]>(self).unsafe_get(i + j * $dim)).clone() diff --git a/src/structs/pnt.rs b/src/structs/pnt.rs index 7e0b1f3c..3fd79c7f 100644 --- a/src/structs/pnt.rs +++ b/src/structs/pnt.rs @@ -8,7 +8,7 @@ use std::slice::{Items, MutItems}; use std::iter::{Iterator, FromIterator}; use traits::operations::{ApproxEq, POrd, POrdering, PartialLess, PartialEqual, PartialGreater, NotComparable, Axpy}; -use traits::structure::{Cast, Dim, Indexable, Iterable, IterableMut, PntAsVec}; +use traits::structure::{Cast, Dim, Indexable, Iterable, IterableMut, PntAsVec, Shape}; use traits::geometry::{Orig, FromHomogeneous, ToHomogeneous}; use structs::vec::{Vec1, Vec2, Vec3, Vec4, Vec5, Vec6}; diff --git a/src/structs/quat.rs b/src/structs/quat.rs index 268d4674..a34a098c 100644 --- a/src/structs/quat.rs +++ b/src/structs/quat.rs @@ -10,7 +10,7 @@ use std::slice::{Items, MutItems}; use structs::{Vec3, Pnt3, Rot3, Mat3, Vec3MulRhs, Pnt3MulRhs}; use traits::operations::{ApproxEq, Inv, POrd, POrdering, NotComparable, PartialLess, PartialGreater, PartialEqual, Axpy}; -use traits::structure::{Cast, Indexable, Iterable, IterableMut, Dim}; +use traits::structure::{Cast, Indexable, Iterable, IterableMut, Dim, Shape}; use traits::geometry::{Norm, Cross, Rotation, Rotate, Transform}; /// A quaternion. diff --git a/src/structs/spec/vec0.rs b/src/structs/spec/vec0.rs index 84ae6d47..c4796f68 100644 --- a/src/structs/spec/vec0.rs +++ b/src/structs/spec/vec0.rs @@ -3,10 +3,31 @@ use std::num::{Zero, One, Float, Bounded}; use std::slice::{Items, MutItems}; use std::iter::{Iterator, FromIterator}; use traits::operations::ApproxEq; -use traits::structure::{Iterable, IterableMut, Indexable, Basis, Dim}; +use traits::structure::{Iterable, IterableMut, Indexable, Basis, Dim, Shape}; use traits::geometry::{Translation, Dot, Norm}; use structs::vec; +impl Index for vec::Vec0 { + #[inline] + fn index(&self, _: &uint) -> &N { + panic!("Canot index a Vec0.") + } +} + +impl IndexMut for vec::Vec0 { + #[inline] + fn index_mut(&mut self, _: &uint) -> &mut N { + panic!("Canot index a Vec0.") + } +} + +impl Shape for vec::Vec0 { + #[inline] + fn shape(&self) -> uint { + 0 + } +} + impl Indexable for vec::Vec0 { #[inline] fn at(&self, _: uint) -> N { @@ -17,11 +38,6 @@ impl Indexable for vec::Vec0 { fn set(&mut self, _: uint, _: N) { } - #[inline] - fn shape(&self) -> uint { - 0 - } - #[inline] fn swap(&mut self, _: uint, _: uint) { } diff --git a/src/structs/vec.rs b/src/structs/vec.rs index 995fa9fa..e3c2d69f 100644 --- a/src/structs/vec.rs +++ b/src/structs/vec.rs @@ -10,7 +10,7 @@ use traits::operations::{ApproxEq, POrd, POrdering, PartialLess, PartialEqual, PartialGreater, NotComparable, Axpy}; use traits::geometry::{Transform, Rotate, FromHomogeneous, ToHomogeneous, Dot, Norm, Translation, Translate}; -use traits::structure::{Basis, Cast, Dim, Indexable, Iterable, IterableMut, VecAsPnt}; +use traits::structure::{Basis, Cast, Dim, Indexable, Iterable, IterableMut, VecAsPnt, Shape}; use structs::pnt::{Pnt1, Pnt2, Pnt3, Pnt4, Pnt5, Pnt6}; diff --git a/src/structs/vec_macros.rs b/src/structs/vec_macros.rs index 0947cd3b..ec22533d 100644 --- a/src/structs/vec_macros.rs +++ b/src/structs/vec_macros.rs @@ -170,6 +170,13 @@ macro_rules! vec_cast_impl( macro_rules! indexable_impl( ($t: ident, $dim: expr) => ( + impl Shape for $t { + #[inline] + fn shape(&self) -> uint { + $dim + } + } + impl Indexable for $t { #[inline] fn at(&self, i: uint) -> N { @@ -185,11 +192,6 @@ macro_rules! indexable_impl( } } - #[inline] - fn shape(&self) -> uint { - $dim - } - #[inline] fn swap(&mut self, i1: uint, i2: uint) { unsafe { diff --git a/src/traits/mod.rs b/src/traits/mod.rs index 4cd2aa0b..74c3910c 100644 --- a/src/traits/mod.rs +++ b/src/traits/mod.rs @@ -6,7 +6,7 @@ pub use self::geometry::{AbsoluteRotate, Cross, CrossMatrix, Dot, FromHomogeneou pub use self::structure::{FloatVec, FloatPnt, Basis, Cast, Col, Dim, Indexable, Iterable, IterableMut, Mat, Row, AnyVec, AnyPnt, PntAsVec, VecAsPnt, ColSlice, - RowSlice, Diag, Eye}; + RowSlice, Diag, Eye, Shape}; pub use self::operations::{Absolute, ApproxEq, Axpy, Cov, Det, Inv, LMul, Mean, Outer, POrd, RMul, ScalarAdd, ScalarSub, ScalarMul, ScalarDiv, Transpose}; diff --git a/src/traits/structure.rs b/src/traits/structure.rs index 24f3fa91..599bb7ae 100644 --- a/src/traits/structure.rs +++ b/src/traits/structure.rs @@ -96,36 +96,35 @@ pub trait Diag { fn diag(&self) -> V; } -// FIXME: this trait should not be on nalgebra. -// however, it is needed because std::ops::Index is (strangely) to poor: it -// does not have a function to set values. -// Also, using Index with tuples crashes. +/// The shape of an indexable object. +pub trait Shape: Index { + /// Returns the shape of an indexable object. + fn shape(&self) -> I; +} + /// This is a workaround of current Rust limitations. /// -/// It exists because the `Index` trait cannot be used to express write access. -/// Thus, this is the same as the `Index` trait but without the syntactic sugar and with a method +/// It exists because the `I` trait cannot be used to express write access. +/// Thus, this is the same as the `I` trait but without the syntactic sugar and with a method /// to write to a specific index. -pub trait Indexable { +pub trait Indexable: Shape + IndexMut { #[deprecated = "use the Index `[]` overloaded operator instead"] /// Reads the `i`-th element of `self`. - fn at(&self, i: Index) -> Res; + fn at(&self, i: I) -> Res; #[deprecated = "use the IndexMut `[]` overloaded operator instead"] /// Writes to the `i`-th element of `self`. - fn set(&mut self, i: Index, Res); + fn set(&mut self, i: I, Res); /// Swaps the `i`-th element of `self` with its `j`-th element. - fn swap(&mut self, i: Index, j: Index); - - /// Returns the shape of the iterable range. - fn shape(&self) -> Index; + fn swap(&mut self, i: I, j: I); /// Reads the `i`-th element of `self`. /// /// `i` is not checked. - unsafe fn unsafe_at(&self, i: Index) -> Res; + unsafe fn unsafe_at(&self, i: I) -> Res; /// Writes to the `i`-th element of `self`. /// /// `i` is not checked. - unsafe fn unsafe_set(&mut self, i: Index, Res); + unsafe fn unsafe_set(&mut self, i: I, Res); } /// This is a workaround of current Rust limitations.