Skip to content

Commit

Permalink
Add field names to Slice and SliceOrIndex::Slice
Browse files Browse the repository at this point in the history
Also rename .step() to .step_by().
  • Loading branch information
jturner314 committed Nov 4, 2017
1 parent 2d4ceab commit 79659c9
Show file tree
Hide file tree
Showing 4 changed files with 113 additions and 54 deletions.
12 changes: 6 additions & 6 deletions src/impl_methods.rs
Original file line number Diff line number Diff line change
Expand Up @@ -269,7 +269,7 @@ impl<A, S, D> ArrayBase<S, D> where S: Data<Elem=A>, 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()))
Expand Down Expand Up @@ -307,8 +307,8 @@ impl<A, S, D> ArrayBase<S, D> where S: Data<Elem=A>, 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);
Expand Down Expand Up @@ -348,9 +348,9 @@ impl<A, S, D> ArrayBase<S, D> where S: Data<Elem=A>, 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);
Expand Down
137 changes: 98 additions & 39 deletions src/slice.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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<Ixs>, pub Ixs);
pub struct Slice {
pub start: Ixs,
pub end: Option<Ixs>,
pub step: Ixs,
}

impl Slice {
pub fn new<I>(start: Ixs, end: I, step: Ixs) -> Slice
where
I: Into<Option<Ixs>>,
{
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<Range<Ixs>> for Slice {
#[inline]
fn from(r: Range<Ixs>) -> Slice {
Slice(r.start, Some(r.end), 1)
Slice {
start: r.start,
end: Some(r.end),
step: 1,
}
}
}

impl From<RangeFrom<Ixs>> for Slice {
#[inline]
fn from(r: RangeFrom<Ixs>) -> Slice {
Slice(r.start, None, 1)
Slice {
start: r.start,
end: None,
step: 1,
}
}
}

impl From<RangeTo<Ixs>> for Slice {
#[inline]
fn from(r: RangeTo<Ixs>) -> Slice {
Slice(0, Some(r.end), 1)
Slice {
start: 0,
end: Some(r.end),
step: 1,
}
}
}

impl From<RangeFull> for Slice {
#[inline]
fn from(_: RangeFull) -> Slice {
Slice(0, None, 1)
Slice {
start: 0,
end: None,
step: 1,
}
}
}

Expand All @@ -74,24 +108,29 @@ impl From<RangeFull> 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>, 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<Ixs>,
step: Ixs,
},
/// A single index.
Index(Ixs),
}
Expand All @@ -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,
}
}
Expand All @@ -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),
}
}
Expand All @@ -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)?;
}
Expand All @@ -149,14 +188,22 @@ impl fmt::Display for SliceOrIndex {
impl From<Slice> 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<Range<Ixs>> for SliceOrIndex {
#[inline]
fn from(r: Range<Ixs>) -> SliceOrIndex {
SliceOrIndex::Slice(r.start, Some(r.end), 1)
SliceOrIndex::Slice {
start: r.start,
end: Some(r.end),
step: 1,
}
}
}

Expand All @@ -170,21 +217,33 @@ impl From<Ixs> for SliceOrIndex {
impl From<RangeFrom<Ixs>> for SliceOrIndex {
#[inline]
fn from(r: RangeFrom<Ixs>) -> SliceOrIndex {
SliceOrIndex::Slice(r.start, None, 1)
SliceOrIndex::Slice {
start: r.start,
end: None,
step: 1,
}
}
}

impl From<RangeTo<Ixs>> for SliceOrIndex {
#[inline]
fn from(r: RangeTo<Ixs>) -> SliceOrIndex {
SliceOrIndex::Slice(0, Some(r.end), 1)
SliceOrIndex::Slice {
start: 0,
end: Some(r.end),
step: 1,
}
}
}

impl From<RangeFull> for SliceOrIndex {
#[inline]
fn from(_: RangeFull) -> SliceOrIndex {
SliceOrIndex::Slice(0, None, 1)
SliceOrIndex::Slice {
start: 0,
end: None,
step: 1,
}
}
}

Expand Down Expand Up @@ -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)*]
Expand Down
12 changes: 6 additions & 6 deletions tests/array.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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());
Expand Down Expand Up @@ -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);
Expand All @@ -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);
Expand All @@ -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());
Expand All @@ -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());
Expand Down Expand Up @@ -252,7 +252,7 @@ fn slice_oob()
#[test]
fn slice_axis_oob() {
let a = RcArray::<i32, _>::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]
Expand Down
6 changes: 3 additions & 3 deletions tests/oper.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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),
]
};

Expand Down

0 comments on commit 79659c9

Please sign in to comment.