From 79659c9e5376da1aadea041976c50a8cdb1f0657 Mon Sep 17 00:00:00 2001 From: Jim Turner Date: Fri, 3 Nov 2017 20:08:24 -0400 Subject: [PATCH] Add field names to Slice and SliceOrIndex::Slice Also rename .step() to .step_by(). --- src/impl_methods.rs | 12 ++-- src/slice.rs | 137 +++++++++++++++++++++++++++++++------------- tests/array.rs | 12 ++-- tests/oper.rs | 6 +- 4 files changed, 113 insertions(+), 54 deletions(-) diff --git a/src/impl_methods.rs b/src/impl_methods.rs index f63a83ca0..171670893 100644 --- a/src/impl_methods.rs +++ b/src/impl_methods.rs @@ -269,7 +269,7 @@ impl ArrayBase where S: Data, D: Dimension let mut new_strides = Do::zero_index_with_ndim(out_ndim); izip!(self.dim.slice(), self.strides.slice(), indices) .filter_map(|(d, s, slice_or_index)| match slice_or_index { - &SliceOrIndex::Slice(..) => Some((d, s)), + &SliceOrIndex::Slice {..} => Some((d, s)), &SliceOrIndex::Index(_) => None, }) .zip(izip!(new_dim.slice_mut(), new_strides.slice_mut())) @@ -307,8 +307,8 @@ impl ArrayBase where S: Data, D: Dimension .iter() .enumerate() .for_each(|(axis, slice_or_index)| match slice_or_index { - &SliceOrIndex::Slice(start, end, step) => { - self.slice_axis_inplace(Axis(axis), Slice(start, end, step)) + &SliceOrIndex::Slice { start, end, step } => { + self.slice_axis_inplace(Axis(axis), Slice { start, end, step }) } &SliceOrIndex::Index(index) => { let i_usize = abs_index(self.len_of(Axis(axis)), index); @@ -348,9 +348,9 @@ impl ArrayBase where S: Data, D: Dimension let offset = do_slice( &mut self.dim.slice_mut()[axis.index()], &mut self.strides.slice_mut()[axis.index()], - indices.0, - indices.1, - indices.2, + indices.start, + indices.end, + indices.step, ); unsafe { self.ptr = self.ptr.offset(offset); diff --git a/src/slice.rs b/src/slice.rs index 153b5fd73..41788ca6d 100644 --- a/src/slice.rs +++ b/src/slice.rs @@ -12,54 +12,88 @@ use super::{Dimension, Ixs}; /// A slice (range with step size). /// +/// Negative `begin` or `end` indexes are counted from the back of the axis. If +/// `end` is `None`, the slice extends to the end of the axis. +/// /// ## Examples /// -/// `Slice(0, None, 1)` is the full range of an axis. It can also be created -/// with `Slice::from(..)`. The Python equivalent is `[:]`. +/// `Slice::new(0, None, 1)` is the full range of an axis. It can also be +/// created with `Slice::from(..)`. The Python equivalent is `[:]`. /// -/// `Slice(a, Some(b), 2)` is every second element from `a` until `b`. It can -/// also be created with `Slice::from(a..b).step(2)`. The Python equivalent is -/// `[a:b:2]`. +/// `Slice::new(a, b, 2)` is every second element from `a` until `b`. It can +/// also be created with `Slice::from(a..b).step_by(2)`. The Python equivalent +/// is `[a:b:2]`. /// -/// `Slice(a, None, -1)` is every element, from `a` until the end, in reverse -/// order. It can also be created with `Slice::from(a..).step(-1)`. The Python -/// equivalent is `[a::-1]`. +/// `Slice::new(a, None, -1)` is every element, from `a` until the end, in +/// reverse order. It can also be created with `Slice::from(a..).step_by(-1)`. +/// The Python equivalent is `[a::-1]`. #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)] -pub struct Slice(pub Ixs, pub Option, pub Ixs); +pub struct Slice { + pub start: Ixs, + pub end: Option, + pub step: Ixs, +} impl Slice { + pub fn new(start: Ixs, end: I, step: Ixs) -> Slice + where + I: Into>, + { + Slice { + start, + end: end.into(), + step, + } + } + /// Returns a new `Slice` with the given step size. #[inline] - pub fn step(self, step: Ixs) -> Self { - Slice(self.0, self.1, step) + pub fn step_by(self, step: Ixs) -> Self { + Slice { step, ..self } } } impl From> for Slice { #[inline] fn from(r: Range) -> Slice { - Slice(r.start, Some(r.end), 1) + Slice { + start: r.start, + end: Some(r.end), + step: 1, + } } } impl From> for Slice { #[inline] fn from(r: RangeFrom) -> Slice { - Slice(r.start, None, 1) + Slice { + start: r.start, + end: None, + step: 1, + } } } impl From> for Slice { #[inline] fn from(r: RangeTo) -> Slice { - Slice(0, Some(r.end), 1) + Slice { + start: 0, + end: Some(r.end), + step: 1, + } } } impl From for Slice { #[inline] fn from(_: RangeFull) -> Slice { - Slice(0, None, 1) + Slice { + start: 0, + end: None, + step: 1, + } } } @@ -74,24 +108,29 @@ impl From for Slice { /// `SliceOrIndex::from(a)`. The Python equivalent is `[a]`. The macro /// equivalent is `s![a]`. /// -/// `SliceOrIndex::Slice(0, None, 1)` is the full range of an axis. It can also -/// be created with `SliceOrIndex::from(..)`. The Python equivalent is `[:]`. -/// The macro equivalent is `s![..]`. +/// `SliceOrIndex::Slice { start: 0, end: None, step: 1 }` is the full range of +/// an axis. It can also be created with `SliceOrIndex::from(..)`. The Python +/// equivalent is `[:]`. The macro equivalent is `s![..]`. /// -/// `SliceOrIndex::Slice(a, Some(b), 2)` is every second element from `a` until -/// `b`. It can also be created with `SliceOrIndex::from(a..b).step(2)`. The -/// Python equivalent is `[a:b:2]`. The macro equivalent is `s![a..b;2]`. +/// `SliceOrIndex::Slice { start: a, end: Some(b), step: 2 }` is every second +/// element from `a` until `b`. It can also be created with +/// `SliceOrIndex::from(a..b).step_by(2)`. The Python equivalent is `[a:b:2]`. +/// The macro equivalent is `s![a..b;2]`. /// -/// `SliceOrIndex::Slice(a, None, -1)` is every element, from `a` until the -/// end, in reverse order. It can also be created with -/// `SliceOrIndex::from(a..).step(-1)`. The Python equivalent is `[a::-1]`. The -/// macro equivalent is `s![a..;-1]`. +/// `SliceOrIndex::Slice { start: a, end: None, step: -1 }` is every element, +/// from `a` until the end, in reverse order. It can also be created with +/// `SliceOrIndex::from(a..).step_by(-1)`. The Python equivalent is `[a::-1]`. +/// The macro equivalent is `s![a..;-1]`. #[derive(Debug, PartialEq, Eq, Hash)] pub enum SliceOrIndex { - /// A range with step size. The fields are `begin`, `end`, and `step`, - /// where negative `begin` or `end` indexes are counted from the back of - /// the axis. If `end` is `None`, the slice extends to the end of the axis. - Slice(Ixs, Option, Ixs), + /// A range with step size. Negative `begin` or `end` indexes are counted + /// from the back of the axis. If `end` is `None`, the slice extends to the + /// end of the axis. + Slice { + start: Ixs, + end: Option, + step: Ixs, + }, /// A single index. Index(Ixs), } @@ -102,7 +141,7 @@ impl SliceOrIndex { /// Returns `true` if `self` is a `Slice` value. pub fn is_slice(&self) -> bool { match self { - &SliceOrIndex::Slice(..) => true, + &SliceOrIndex::Slice { .. } => true, _ => false, } } @@ -117,9 +156,9 @@ impl SliceOrIndex { /// Returns a new `SliceOrIndex` with the given step size. #[inline] - pub fn step(self, step: Ixs) -> Self { + pub fn step_by(self, step: Ixs) -> Self { match self { - SliceOrIndex::Slice(start, end, _) => SliceOrIndex::Slice(start, end, step), + SliceOrIndex::Slice { start, end, .. } => SliceOrIndex::Slice { start, end, step }, SliceOrIndex::Index(s) => SliceOrIndex::Index(s), } } @@ -129,7 +168,7 @@ impl fmt::Display for SliceOrIndex { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match *self { SliceOrIndex::Index(index) => write!(f, "{}", index)?, - SliceOrIndex::Slice(start, end, step) => { + SliceOrIndex::Slice { start, end, step } => { if start != 0 { write!(f, "{}", start)?; } @@ -149,14 +188,22 @@ impl fmt::Display for SliceOrIndex { impl From for SliceOrIndex { #[inline] fn from(s: Slice) -> SliceOrIndex { - SliceOrIndex::Slice(s.0, s.1, s.2) + SliceOrIndex::Slice { + start: s.start, + end: s.end, + step: s.step, + } } } impl From> for SliceOrIndex { #[inline] fn from(r: Range) -> SliceOrIndex { - SliceOrIndex::Slice(r.start, Some(r.end), 1) + SliceOrIndex::Slice { + start: r.start, + end: Some(r.end), + step: 1, + } } } @@ -170,21 +217,33 @@ impl From for SliceOrIndex { impl From> for SliceOrIndex { #[inline] fn from(r: RangeFrom) -> SliceOrIndex { - SliceOrIndex::Slice(r.start, None, 1) + SliceOrIndex::Slice { + start: r.start, + end: None, + step: 1, + } } } impl From> for SliceOrIndex { #[inline] fn from(r: RangeTo) -> SliceOrIndex { - SliceOrIndex::Slice(0, Some(r.end), 1) + SliceOrIndex::Slice { + start: 0, + end: Some(r.end), + step: 1, + } } } impl From for SliceOrIndex { #[inline] fn from(_: RangeFull) -> SliceOrIndex { - SliceOrIndex::Slice(0, None, 1) + SliceOrIndex::Slice { + start: 0, + end: None, + step: 1, + } } } @@ -483,7 +542,7 @@ macro_rules! s( }; // convert range/index and step into SliceOrIndex (@convert $r:expr, $s:expr) => { - <$crate::SliceOrIndex as ::std::convert::From<_>>::from($r).step($s) + <$crate::SliceOrIndex as ::std::convert::From<_>>::from($r).step_by($s) }; ($($t:tt)*) => { s![@parse ::std::marker::PhantomData::<$crate::Ix0>, [] $($t)*] diff --git a/tests/array.rs b/tests/array.rs index b542f9fae..73b7eedca 100644 --- a/tests/array.rs +++ b/tests/array.rs @@ -60,7 +60,7 @@ fn test_slice() *elt = i; } - let vi = A.slice(s![1.., ..;2, Slice(0, None, 2)]); + let vi = A.slice(s![1.., ..;2, Slice::new(0, None, 2)]); assert_eq!(vi.shape(), &[2, 2, 3]); let vi = A.slice(s![.., .., ..]); assert_eq!(vi.shape(), A.shape()); @@ -119,7 +119,7 @@ fn test_slice_array_dyn() { let info = &SliceInfo::<_, IxDyn>::new([ SliceOrIndex::from(1..), SliceOrIndex::from(1), - SliceOrIndex::from(..).step(2), + SliceOrIndex::from(..).step_by(2), ]); arr.slice(info); arr.slice_mut(info); @@ -133,7 +133,7 @@ fn test_slice_dyninput_array_dyn() { let info = &SliceInfo::<_, IxDyn>::new([ SliceOrIndex::from(1..), SliceOrIndex::from(1), - SliceOrIndex::from(..).step(2), + SliceOrIndex::from(..).step_by(2), ]); arr.slice(info); arr.slice_mut(info); @@ -147,7 +147,7 @@ fn test_slice_dyninput_vec_fixed() { let info = &SliceInfo::<_, Ix2>::new(vec![ SliceOrIndex::from(1..), SliceOrIndex::from(1), - SliceOrIndex::from(..).step(2), + SliceOrIndex::from(..).step_by(2), ]); arr.slice(info.as_ref()); arr.slice_mut(info.as_ref()); @@ -161,7 +161,7 @@ fn test_slice_dyninput_vec_dyn() { let info = &SliceInfo::<_, IxDyn>::new(vec![ SliceOrIndex::from(1..), SliceOrIndex::from(1), - SliceOrIndex::from(..).step(2), + SliceOrIndex::from(..).step_by(2), ]); arr.slice(info.as_ref()); arr.slice_mut(info.as_ref()); @@ -252,7 +252,7 @@ fn slice_oob() #[test] fn slice_axis_oob() { let a = RcArray::::zeros((3, 4)); - let _vi = a.slice_axis(Axis(0), Slice(0, Some(10), 1)); + let _vi = a.slice_axis(Axis(0), Slice::new(0, 10, 1)); } #[should_panic] diff --git a/tests/oper.rs b/tests/oper.rs index 1eb427675..5dbc5b923 100644 --- a/tests/oper.rs +++ b/tests/oper.rs @@ -577,11 +577,11 @@ fn scaled_add_3() { vec![n, q] }; let cslice = if n == 1 { - vec![SliceOrIndex::from(..).step(s2)] + vec![SliceOrIndex::from(..).step_by(s2)] } else { vec![ - SliceOrIndex::from(..).step(s1), - SliceOrIndex::from(..).step(s2), + SliceOrIndex::from(..).step_by(s1), + SliceOrIndex::from(..).step_by(s2), ] };