From 4ab8a290c7a930447222f94457730578bf6ec4b6 Mon Sep 17 00:00:00 2001 From: Jack Wrenn Date: Mon, 3 Dec 2018 16:32:47 -0500 Subject: [PATCH] groundwork for indexing with typenums --- src/base/indexing.rs | 165 ++++++++++++++++++++++++++++--------------- 1 file changed, 109 insertions(+), 56 deletions(-) diff --git a/src/base/indexing.rs b/src/base/indexing.rs index d742d1f0..397db7c4 100644 --- a/src/base/indexing.rs +++ b/src/base/indexing.rs @@ -1,6 +1,6 @@ -//! Indexing +//! Indexing -use base::{Dim, Dynamic, Matrix, MatrixSlice, MatrixSliceMut, Scalar, U1}; +use base::{Dim, DimName, DimDiff, DimSub, Dynamic, Matrix, MatrixSlice, MatrixSliceMut, Scalar, U1}; use base::storage::{Storage, StorageMut}; use std::ops; @@ -8,7 +8,7 @@ use std::ops; // N.B.: Not a public trait! trait DimRange { - ///asdf + /// The number of elements indexed by this range. type Length: Dim; /// The lower bound of the range, inclusive. @@ -110,6 +110,33 @@ fn dimrange_rangefrom_usize() { assert_eq!(DimRange::length(&(MAX..), Dynamic::new(MAX)), Dynamic::new(0)); } +impl DimRange for ops::RangeFrom +where D: DimSub +{ + type Length = DimDiff; + + #[inline(always)] + fn lower(&self, _: D) -> usize { + self.start.value() + } + + #[inline(always)] + fn length(&self, dimension: D) -> Self::Length { + dimension.sub(self.start) + } + + #[inline(always)] + fn contained_by(&self, _: D) -> bool { + true + } +} + +#[test] +fn dimrange_rangefrom_dimname() { + use base::dimension::{U5, U4}; + assert_eq!(DimRange::length(&(U1..), U5), U4); +} + impl DimRange for ops::RangeFull { type Length = D; @@ -246,12 +273,12 @@ pub trait MatrixIndex<'a, N: Scalar, R: Dim, C: Dim, S: Storage>: Sized type Output : 'a; /// Produces true if the given matrix is contained by this index. - #[doc(hidden)] + #[doc(hidden)] fn contained_by(&self, matrix: &Matrix) -> bool; /// Produces a shared view of the data at this location if in bounds, /// or `None`, otherwise. - #[doc(hidden)] + #[doc(hidden)] #[inline(always)] fn get(self, matrix: &'a Matrix) -> Option { if self.contained_by(matrix) { @@ -268,7 +295,7 @@ pub trait MatrixIndex<'a, N: Scalar, R: Dim, C: Dim, S: Storage>: Sized /// Produces a shared view to the data at this location, or panics /// if out of bounds. - #[doc(hidden)] + #[doc(hidden)] #[inline(always)] fn index(self, matrix: &'a Matrix) -> Self::Output { self.get(matrix).expect("Index out of bounds.") @@ -287,7 +314,7 @@ pub trait MatrixIndexMut<'a, N: Scalar, R: Dim, C: Dim, S: StorageMut>: /// Produces a mutable view of the data at this location, if in /// bounds. - #[doc(hidden)] + #[doc(hidden)] #[inline(always)] fn get_mut(self, matrix: &'a mut Matrix) -> Option { if self.contained_by(matrix) { @@ -313,7 +340,7 @@ pub trait MatrixIndexMut<'a, N: Scalar, R: Dim, C: Dim, S: StorageMut>: /// # use nalgebra::*; /// let matrix = Matrix2::new(0, 2, /// 1, 3); -/// +/// /// assert_eq!(matrix.index((0, 0)), &0); /// assert_eq!(matrix.index((1, 0)), &1); /// assert_eq!(matrix.index((0, 1)), &2); @@ -325,7 +352,7 @@ pub trait MatrixIndexMut<'a, N: Scalar, R: Dim, C: Dim, S: StorageMut>: /// # use nalgebra::*; /// let matrix = Matrix2::new(0, 2, /// 1, 3); -/// +/// /// assert_eq!(matrix.get(0), Some(&0)); /// assert_eq!(matrix.get(1), Some(&1)); /// assert_eq!(matrix.get(2), Some(&2)); @@ -338,7 +365,7 @@ pub trait MatrixIndexMut<'a, N: Scalar, R: Dim, C: Dim, S: StorageMut>: /// # use nalgebra::*; /// let matrix = Matrix2::new(0, 2, /// 1, 3); -/// +/// /// assert!(matrix.index((0, ..)) /// .eq(&Matrix1x2::new(0, 2))); /// ``` @@ -348,7 +375,7 @@ pub trait MatrixIndexMut<'a, N: Scalar, R: Dim, C: Dim, S: StorageMut>: /// # use nalgebra::*; /// let matrix = Matrix2::new(0, 2, /// 1, 3); -/// +/// /// assert!(matrix.index((.., 0)) /// .eq(&Matrix2x1::new(0, /// 1))); @@ -361,7 +388,7 @@ pub trait MatrixIndexMut<'a, N: Scalar, R: Dim, C: Dim, S: StorageMut>: /// let matrix = Matrix3::new(0, 3, 6, /// 1, 4, 7, /// 2, 5, 8); -/// +/// /// assert!(matrix.index((0, ..2)) /// .eq(&Matrix1x2::new(0, 3))); /// ``` @@ -372,10 +399,14 @@ pub trait MatrixIndexMut<'a, N: Scalar, R: Dim, C: Dim, S: StorageMut>: /// let matrix = Matrix3::new(0, 3, 6, /// 1, 4, 7, /// 2, 5, 8); -/// +/// /// assert!(matrix.index((..2, 0)) /// .eq(&Matrix2x1::new(0, /// 1))); +/// +/// assert!(matrix.index((U1.., 0)) +/// .eq(&Matrix2x1::new(1, +/// 2))); /// ``` /// ## Indicies to Ranges of Rows and Columns /// ### Index to a Range of Rows @@ -384,7 +415,7 @@ pub trait MatrixIndexMut<'a, N: Scalar, R: Dim, C: Dim, S: StorageMut>: /// let matrix = Matrix3::new(0, 3, 6, /// 1, 4, 7, /// 2, 5, 8); -/// +/// /// assert!(matrix.index((1..3, ..)) /// .eq(&Matrix2x3::new(1, 4, 7, /// 2, 5, 8))); @@ -555,23 +586,33 @@ where } } -macro_rules! impl_usize_slice_index { - (index Matrix<$R: ident, $C: ident> with [$RIdx: ty, $CIdx: ty] -> ($ROut: ty, ..)) => { - impl_usize_slice_index!{index Matrix<$R, $C> with [$RIdx, $CIdx] -> ($ROut, $C)} - }; - (index Matrix<$R: ident, $C: ident> with [$RIdx: ty, $CIdx: ty] -> (.., $COut: ty)) => { - impl_usize_slice_index!{index Matrix<$R, $C> with [$RIdx, $CIdx] -> ($R, $COut)} - }; - (index Matrix<$R: ident, $C: ident> with [$RIdx: ty, $CIdx: ty] -> (.., ..)) => { - impl_usize_slice_index!{index Matrix<$R, $C> with [$RIdx, $CIdx] -> ($R, $C)} - }; - (index Matrix<$R: ident, $C: ident> with [$RIdx: ty, $CIdx: ty] -> ($ROut: ty, $COut: ty)) => { - impl<'a, N, $R, $C, S> MatrixIndex<'a, N, $R, $C, S> for ($RIdx, $CIdx) +macro_rules! impl_index_pair { + ( + $R: ident, + $C: ident, + [<$($RTyP: ident : $RTyPB: ty,)*> usize => $ROut: ty + $(where $RConstraintType: ty: $RConstraintBound: ident<$($RConstraintBoundParams: ty $( = $REqBound: ty )*),*>)*], + [<$($CTyP: ident : $CTyPB: ty,)*> usize => $COut: ty + $(where $CConstraintType: ty: $CConstraintBound: ident<$($CConstraintBoundParams: ty $( = $CEqBound: ty )*),*>)*] + ) => {}; + + ( + $R: ident, + $C: ident, + [<$($RTyP: ident: $RTyPB: tt),*> $RIdx: ty => $ROut: ty + $(where $RConstraintType: ty: $RConstraintBound: ident $(<$($RConstraintBoundParams: ty $( = $REqBound: ty )*),*>)* )*], + [<$($CTyP: ident: $CTyPB: tt),*> $CIdx: ty => $COut: ty + $(where $CConstraintType: ty: $CConstraintBound: ident $(<$($CConstraintBoundParams: ty $( = $CEqBound: ty )*),*>)* )*] + ) => + { + impl<'a, N, $R, $C, S, $($RTyP : $RTyPB,)* $($CTyP : $CTyPB),*> MatrixIndex<'a, N, $R, $C, S> for ($RIdx, $CIdx) where N: Scalar, $R: Dim, $C: Dim, - S: Storage + S: Storage, + $( $RConstraintType: $RConstraintBound $(<$( $RConstraintBoundParams $( = $REqBound )*),*>)* ,)* + $( $CConstraintType: $CConstraintBound $(<$( $CConstraintBoundParams $( = $CEqBound )*),*>)* ),* { type Output = MatrixSlice<'a, N, $ROut, $COut, S::RStride, S::CStride>; @@ -600,12 +641,14 @@ macro_rules! impl_usize_slice_index { } } - impl<'a, N, $R, $C, S> MatrixIndexMut<'a, N, $R, $C, S> for ($RIdx, $CIdx) + impl<'a, N, $R, $C, S, $($RTyP : $RTyPB,)* $($CTyP : $CTyPB),*> MatrixIndexMut<'a, N, $R, $C, S> for ($RIdx, $CIdx) where N: Scalar, $R: Dim, $C: Dim, - S: StorageMut + S: StorageMut, + $( $RConstraintType: $RConstraintBound $(<$( $RConstraintBoundParams $( = $REqBound )*),*>)* ,)* + $( $CConstraintType: $CConstraintBound $(<$( $CConstraintBoundParams $( = $CEqBound )*),*>)* ),* { type OutputMut = MatrixSliceMut<'a, N, $ROut, $COut, S::RStride, S::CStride>; @@ -628,34 +671,44 @@ macro_rules! impl_usize_slice_index { } } -macro_rules! impl_slice_indices{ - (index Matrix<$R: ident, $C: ident> with) => {}; +macro_rules! impl_index_pairs { + (index $R: ident with {} index $C: ident with {$($r: tt,)* }) => {}; - (index Matrix<$R: ident, $C: ident> with usize => U1, $($RI: ty => $RO: tt,)*) => - { - $(impl_usize_slice_index!{index Matrix<$R, $C> with [usize, $RI] -> (U1, $RO)})* - $(impl_usize_slice_index!{index Matrix<$R, $C> with [$RI, usize] -> ($RO, U1)})* - impl_slice_indices!{index Matrix<$R, $C> with $($RI => $RO,)*} - }; - - (index Matrix<$R: ident, $C: ident> with - $HI: ty => $HO: tt, - $($RI: ty => $RO: tt,)*) => - { - impl_usize_slice_index!{index Matrix<$R, $C> with [$HI, $HI] -> ($HO, $HO)} - $(impl_usize_slice_index!{index Matrix<$R, $C> with [$HI, $RI] -> ($HO, $RO)})* - $(impl_usize_slice_index!{index Matrix<$R, $C> with [$RI, $HI] -> ($RO, $HO)})* - impl_slice_indices!{index Matrix<$R, $C> with $($RI => $RO,)*} - }; + (index $R: ident with {$lh : tt, $($lt : tt,)*} + index $C: ident with { $($r: tt,)* }) => + { + $( + impl_index_pair!{$R, $C, $lh, $r} + )* + impl_index_pairs!{index $R with {$($lt,)*} index $C with {$($r,)*}} + } } -impl_slice_indices!{ - index Matrix with - usize => U1, - ops::Range => Dynamic, - ops::RangeFrom => Dynamic, - ops::RangeFull => .., - ops::RangeInclusive => Dynamic, - ops::RangeTo => Dynamic, - ops::RangeToInclusive => Dynamic, +impl_index_pairs!{ + index R with { + [<> usize => U1], + [<> ops::Range => Dynamic], + [<> ops::RangeFrom => Dynamic], + [<> ops::RangeFull => R], + [<> ops::RangeInclusive => Dynamic], + [<> ops::RangeTo => Dynamic], + [<> ops::RangeToInclusive => Dynamic], + + [ ops::RangeFrom + => DimDiff + where R: DimSub], + } + index C with { + [<> usize => U1], + [<> ops::Range => Dynamic], + [<> ops::RangeFrom => Dynamic], + [<> ops::RangeFull => C], + [<> ops::RangeInclusive => Dynamic], + [<> ops::RangeTo => Dynamic], + [<> ops::RangeToInclusive => Dynamic], + + [ ops::RangeFrom + => DimDiff + where C: DimSub], + } } \ No newline at end of file