From 1e978ca3c9c50a893693405c78e956e2bb62b00c Mon Sep 17 00:00:00 2001 From: Jim Turner Date: Sun, 9 Dec 2018 16:53:27 -0500 Subject: [PATCH] Add support for inserting new axes while slicing --- src/dimension/mod.rs | 23 ++++--- src/doc/ndarray_for_numpy_users/mod.rs | 2 +- src/impl_methods.rs | 22 ++++-- src/lib.rs | 23 ++++--- src/prelude.rs | 5 ++ src/slice.rs | 92 ++++++++++++++++++++------ tests/array.rs | 48 ++++++++------ 7 files changed, 148 insertions(+), 67 deletions(-) diff --git a/src/dimension/mod.rs b/src/dimension/mod.rs index 12f643f2b..d59087afc 100644 --- a/src/dimension/mod.rs +++ b/src/dimension/mod.rs @@ -534,7 +534,11 @@ pub fn slices_intersect( indices2: &impl CanSlice, ) -> bool { debug_assert_eq!(indices1.in_ndim(), indices2.in_ndim()); - for (&axis_len, &si1, &si2) in izip!(dim.slice(), indices1.as_ref(), indices2.as_ref()) { + for (&axis_len, &si1, &si2) in izip!( + dim.slice(), + indices1.as_ref().iter().filter(|si| !si.is_new_axis()), + indices2.as_ref().iter().filter(|si| !si.is_new_axis()), + ) { // The slices do not intersect iff any pair of `AxisSliceInfo` does not intersect. match (si1, si2) { ( @@ -582,6 +586,7 @@ pub fn slices_intersect( return false; } } + (AxisSliceInfo::NewAxis, _) | (_, AxisSliceInfo::NewAxis) => unreachable!(), } } true @@ -626,7 +631,7 @@ mod test { use num_integer::gcd; use quickcheck::{quickcheck, TestResult}; use slice::Slice; - use {Dim, Dimension, Ix0, Ix1, Ix2, Ix3, IxDyn}; + use {Dim, Dimension, Ix0, Ix1, Ix2, Ix3, IxDyn, NewAxis}; #[test] fn slice_indexing_uncommon_strides() { @@ -882,17 +887,17 @@ mod test { #[test] fn slices_intersect_true() { - assert!(slices_intersect(&Dim([4, 5]), s![.., ..], s![.., ..])); - assert!(slices_intersect(&Dim([4, 5]), s![0, ..], s![0, ..])); - assert!(slices_intersect(&Dim([4, 5]), s![..;2, ..], s![..;3, ..])); - assert!(slices_intersect(&Dim([4, 5]), s![.., ..;2], s![.., 1..;3])); + assert!(slices_intersect(&Dim([4, 5]), s![NewAxis, .., NewAxis, ..], s![.., NewAxis, .., NewAxis])); + assert!(slices_intersect(&Dim([4, 5]), s![NewAxis, 0, ..], s![0, ..])); + assert!(slices_intersect(&Dim([4, 5]), s![..;2, ..], s![..;3, NewAxis, ..])); + assert!(slices_intersect(&Dim([4, 5]), s![.., ..;2], s![.., 1..;3, NewAxis])); assert!(slices_intersect(&Dim([4, 10]), s![.., ..;9], s![.., 3..;6])); } #[test] fn slices_intersect_false() { - assert!(!slices_intersect(&Dim([4, 5]), s![..;2, ..], s![1..;2, ..])); - assert!(!slices_intersect(&Dim([4, 5]), s![..;2, ..], s![1..;3, ..])); - assert!(!slices_intersect(&Dim([4, 5]), s![.., ..;9], s![.., 3..;6])); + assert!(!slices_intersect(&Dim([4, 5]), s![..;2, ..], s![NewAxis, 1..;2, ..])); + assert!(!slices_intersect(&Dim([4, 5]), s![..;2, NewAxis, ..], s![1..;3, ..])); + assert!(!slices_intersect(&Dim([4, 5]), s![.., ..;9], s![.., 3..;6, NewAxis])); } } diff --git a/src/doc/ndarray_for_numpy_users/mod.rs b/src/doc/ndarray_for_numpy_users/mod.rs index b268c9b24..bcdf282ba 100644 --- a/src/doc/ndarray_for_numpy_users/mod.rs +++ b/src/doc/ndarray_for_numpy_users/mod.rs @@ -519,7 +519,7 @@ //! `a[:] = 3.` | [`a.fill(3.)`][.fill()] | set all array elements to the same scalar value //! `a[:] = b` | [`a.assign(&b)`][.assign()] | copy the data from array `b` into array `a` //! `np.concatenate((a,b), axis=1)` | [`stack![Axis(1), a, b]`][stack!] or [`stack(Axis(1), &[a.view(), b.view()])`][stack()] | concatenate arrays `a` and `b` along axis 1 -//! `a[:,np.newaxis]` or `np.expand_dims(a, axis=1)` | [`a.insert_axis(Axis(1))`][.insert_axis()] | create an array from `a`, inserting a new axis 1 +//! `a[:,np.newaxis]` or `np.expand_dims(a, axis=1)` | [`a.slice(s![.., NewAxis])`][.slice()] or [`a.insert_axis(Axis(1))`][.insert_axis()] | create an view of 1-D array `a`, inserting a new axis 1 //! `a.transpose()` or `a.T` | [`a.t()`][.t()] or [`a.reversed_axes()`][.reversed_axes()] | transpose of array `a` (view for `.t()` or by-move for `.reversed_axes()`) //! `np.diag(a)` | [`a.diag()`][.diag()] | view the diagonal of `a` //! `a.flatten()` | [`Array::from_iter(a.iter())`][::from_iter()] | create a 1-D array by flattening `a` diff --git a/src/impl_methods.rs b/src/impl_methods.rs index 8d0a7a5df..eacc18ed9 100644 --- a/src/impl_methods.rs +++ b/src/impl_methods.rs @@ -366,6 +366,12 @@ where // Skip the old axis since it should be removed. old_axis += 1; } + &AxisSliceInfo::NewAxis => { + // Set the dim and stride of the new axis. + new_dim[new_axis] = 1; + new_strides[new_axis] = 0; + new_axis += 1; + } }); debug_assert_eq!(old_axis, self.ndim()); debug_assert_eq!(new_axis, out_ndim); @@ -381,6 +387,8 @@ where /// Slice the array in place without changing the number of dimensions. /// + /// Note that `NewAxis` elements in `info` are ignored. + /// /// See [*Slicing*](#slicing) for full documentation. /// /// **Panics** if an index is out of bounds or step size is zero.
@@ -394,18 +402,20 @@ where self.ndim(), "The input dimension of `info` must match the array to be sliced.", ); - info.as_ref() - .iter() - .enumerate() - .for_each(|(axis, ax_info)| match ax_info { + let mut axis = 0; + info.as_ref().iter().for_each(|ax_info| match ax_info { &AxisSliceInfo::Slice { start, end, step } => { - self.slice_axis_inplace(Axis(axis), Slice { start, end, step }) + self.slice_axis_inplace(Axis(axis), Slice { start, end, step }); + axis += 1; } &AxisSliceInfo::Index(index) => { let i_usize = abs_index(self.len_of(Axis(axis)), index); - self.collapse_axis(Axis(axis), i_usize) + self.collapse_axis(Axis(axis), i_usize); + axis += 1; } + &AxisSliceInfo::NewAxis => {} }); + debug_assert_eq!(axis, self.ndim()); } /// Slice the array in place without changing the number of dimensions. diff --git a/src/lib.rs b/src/lib.rs index 31912e8be..52adcedb4 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -127,7 +127,7 @@ pub use indexes::{indices, indices_of}; pub use error::{ShapeError, ErrorKind}; pub use slice::{ deref_raw_view_mut_into_view_with_life, deref_raw_view_mut_into_view_mut_with_life, - life_of_view_mut, AxisSliceInfo, Slice, SliceInfo, SliceNextInDim, SliceNextOutDim, + life_of_view_mut, AxisSliceInfo, NewAxis, Slice, SliceInfo, SliceNextInDim, SliceNextOutDim, }; use iterators::Baseiter; @@ -467,14 +467,16 @@ pub type Ixs = isize; /// /// If a range is used, the axis is preserved. If an index is used, that index /// is selected and the axis is removed; this selects a subview. See -/// [*Subviews*](#subviews) for more information about subviews. Note that -/// [`.slice_collapse()`] behaves like [`.collapse_axis()`] by preserving -/// the number of dimensions. +/// [*Subviews*](#subviews) for more information about subviews. If a +/// [`NewAxis`] instance is used, a new axis is inserted. Note that +/// [`.slice_collapse()`] ignores `NewAxis` elements and behaves like +/// [`.collapse_axis()`] by preserving the number of dimensions. /// /// [`.slice()`]: #method.slice /// [`.slice_mut()`]: #method.slice_mut /// [`.slice_move()`]: #method.slice_move /// [`.slice_collapse()`]: #method.slice_collapse +/// [`NewAxis`]: struct.NewAxis.html /// /// It's possible to take multiple simultaneous *mutable* slices with the /// [`multislice!()`](macro.multislice!.html) macro. @@ -482,7 +484,7 @@ pub type Ixs = isize; /// ``` /// extern crate ndarray; /// -/// use ndarray::{arr2, arr3, multislice, s}; +/// use ndarray::{arr2, arr3, multislice, s, NewAxis}; /// /// fn main() { /// @@ -519,16 +521,17 @@ pub type Ixs = isize; /// assert_eq!(d, e); /// assert_eq!(d.shape(), &[2, 1, 3]); /// -/// // Let’s create a slice while selecting a subview with +/// // Let’s create a slice while selecting a subview and inserting a new axis with /// // /// // - Both submatrices of the greatest dimension: `..` /// // - The last row in each submatrix, removing that axis: `-1` /// // - Row elements in reverse order: `..;-1` -/// let f = a.slice(s![.., -1, ..;-1]); -/// let g = arr2(&[[ 6, 5, 4], -/// [12, 11, 10]]); +/// // - A new axis at the end. +/// let f = a.slice(s![.., -1, ..;-1, NewAxis]); +/// let g = arr3(&[[ [6], [5], [4]], +/// [[12], [11], [10]]]); /// assert_eq!(f, g); -/// assert_eq!(f.shape(), &[2, 3]); +/// assert_eq!(f.shape(), &[2, 3, 1]); /// /// // Let's take two disjoint, mutable slices of a matrix with /// // diff --git a/src/prelude.rs b/src/prelude.rs index 20e1600c8..2b81b35d8 100644 --- a/src/prelude.rs +++ b/src/prelude.rs @@ -66,6 +66,11 @@ pub use { ShapeBuilder, }; +#[doc(no_inline)] +pub use { + NewAxis, +}; + #[doc(no_inline)] pub use { NdFloat, diff --git a/src/slice.rs b/src/slice.rs index dde1bffa0..d420fe6c1 100644 --- a/src/slice.rs +++ b/src/slice.rs @@ -67,7 +67,12 @@ impl Slice { } } -/// A slice (range with step) or an index. +/// Token to represent a new axis in a slice description. +/// +/// See also the [`s![]`](macro.s!.html) macro. +pub struct NewAxis; + +/// A slice (range with step), an index, or a new axis token. /// /// See also the [`s![]`](macro.s!.html) macro for a convenient way to create a /// `&SliceInfo<[AxisSliceInfo; n], Di, Do>`. @@ -91,6 +96,10 @@ impl Slice { /// from `a` until the end, in reverse order. It can also be created with /// `AxisSliceInfo::from(a..).step_by(-1)`. The Python equivalent is `[a::-1]`. /// The macro equivalent is `s![a..;-1]`. +/// +/// `AxisSliceInfo::NewAxis` is a new axis of length 1. It can also be created +/// with `AxisSliceInfo::from(NewAxis)`. The Python equivalent is +/// `[np.newaxis]`. The macro equivalent is `s![NewAxis]`. #[derive(Debug, PartialEq, Eq, Hash)] pub enum AxisSliceInfo { /// A range with step size. `end` is an exclusive index. Negative `begin` @@ -103,6 +112,8 @@ pub enum AxisSliceInfo { }, /// A single index. Index(isize), + /// A new axis of length 1. + NewAxis, } copy_and_clone!{AxisSliceInfo} @@ -124,6 +135,14 @@ impl AxisSliceInfo { } } + /// Returns `true` if `self` is a `NewAxis` value. + pub fn is_new_axis(&self) -> bool { + match self { + &AxisSliceInfo::NewAxis => true, + _ => false, + } + } + /// Returns a new `AxisSliceInfo` with the given step size (multiplied with /// the previous step size). /// @@ -143,6 +162,7 @@ impl AxisSliceInfo { step: orig_step * step, }, AxisSliceInfo::Index(s) => AxisSliceInfo::Index(s), + AxisSliceInfo::NewAxis => AxisSliceInfo::NewAxis, } } } @@ -163,6 +183,7 @@ impl fmt::Display for AxisSliceInfo { write!(f, ";{}", step)?; } } + AxisSliceInfo::NewAxis => write!(f, "NewAxis")?, } Ok(()) } @@ -282,6 +303,13 @@ impl_sliceorindex_from_index!(isize); impl_sliceorindex_from_index!(usize); impl_sliceorindex_from_index!(i32); +impl From for AxisSliceInfo { + #[inline] + fn from(_: NewAxis) -> AxisSliceInfo { + AxisSliceInfo::NewAxis + } +} + /// A type that can slice an array of dimension `D`. /// /// This trait is unsafe to implement because the implementation must ensure @@ -402,12 +430,12 @@ where /// Errors if `Di` or `Do` is not consistent with `indices`. pub fn new(indices: T) -> Result, ShapeError> { if let Some(ndim) = Di::NDIM { - if ndim != indices.as_ref().len() { + if ndim != indices.as_ref().iter().filter(|s| !s.is_new_axis()).count() { return Err(ShapeError::from_kind(ErrorKind::IncompatibleShape)); } } if let Some(ndim) = Do::NDIM { - if ndim != indices.as_ref().iter().filter(|s| s.is_slice()).count() { + if ndim != indices.as_ref().iter().filter(|s| !s.is_index()).count() { return Err(ShapeError::from_kind(ErrorKind::IncompatibleShape)); } } @@ -427,8 +455,18 @@ where { /// Returns the number of dimensions of the input array for /// [`.slice()`](struct.ArrayBase.html#method.slice). + /// + /// If `Di` is a fixed-size dimension type, then this is equivalent to + /// `Di::NDIM.unwrap()`. Otherwise, the value is calculated by iterating + /// over the `AxisSliceInfo` elements. pub fn in_ndim(&self) -> usize { - Di::NDIM.unwrap_or_else(|| self.indices.as_ref().len()) + Di::NDIM.unwrap_or_else(|| { + self.indices + .as_ref() + .iter() + .filter(|s| !s.is_new_axis()) + .count() + }) } /// Returns the number of dimensions after calling @@ -443,7 +481,7 @@ where self.indices .as_ref() .iter() - .filter(|s| s.is_slice()) + .filter(|s| !s.is_index()) .count() }) } @@ -506,6 +544,12 @@ pub trait SliceNextInDim { fn next_dim(&self, PhantomData) -> PhantomData; } +impl SliceNextInDim for NewAxis { + fn next_dim(&self, _: PhantomData) -> PhantomData { + PhantomData + } +} + macro_rules! impl_slicenextindim_larger { (($($generics:tt)*), $self:ty) => { impl SliceNextInDim for $self { @@ -560,12 +604,13 @@ impl_slicenextoutdim_larger!((T), RangeTo); impl_slicenextoutdim_larger!((T), RangeToInclusive); impl_slicenextoutdim_larger!((), RangeFull); impl_slicenextoutdim_larger!((), Slice); +impl_slicenextoutdim_larger!((), NewAxis); /// Slice argument constructor. /// -/// `s![]` takes a list of ranges/slices/indices, separated by comma, with -/// optional step sizes that are separated from the range by a semicolon. It is -/// converted into a [`&SliceInfo`] instance. +/// `s![]` takes a list of ranges/slices/indices/new-axes, separated by comma, +/// with optional step sizes that are separated from the range by a semicolon. +/// It is converted into a [`&SliceInfo`] instance. /// /// [`&SliceInfo`]: struct.SliceInfo.html /// @@ -584,22 +629,25 @@ impl_slicenextoutdim_larger!((), Slice); /// * *slice*: a [`Slice`] instance to use for slicing that axis. /// * *slice* `;` *step*: a range constructed from the start and end of a [`Slice`] /// instance, with new step size *step*, to use for slicing that axis. +/// * *new-axis*: a [`NewAxis`] instance that represents the creation of a new axis. /// /// [`Slice`]: struct.Slice.html +/// [`NewAxis`]: struct.NewAxis.html /// -/// The number of *axis-slice-info* must match the number of axes in the array. -/// *index*, *range*, *slice*, and *step* can be expressions. *index* must be -/// of type `isize`, `usize`, or `i32`. *range* must be of type `Range`, -/// `RangeTo`, `RangeFrom`, or `RangeFull` where `I` is `isize`, `usize`, -/// or `i32`. *step* must be a type that can be converted to `isize` with the -/// `as` keyword. +/// The number of *axis-slice-info*, not including *new-axis*, must match the +/// number of axes in the array. *index*, *range*, *slice*, *step*, and +/// *new-axis* can be expressions. *index* must be of type `isize`, `usize`, or +/// `i32`. *range* must be of type `Range`, `RangeTo`, `RangeFrom`, or +/// `RangeFull` where `I` is `isize`, `usize`, or `i32`. *step* must be a type +/// that can be converted to `isize` with the `as` keyword. /// -/// For example `s![0..4;2, 6, 1..5]` is a slice of the first axis for 0..4 -/// with step size 2, a subview of the second axis at index 6, and a slice of -/// the third axis for 1..5 with default step size 1. The input array must have -/// 3 dimensions. The resulting slice would have shape `[2, 4]` for -/// [`.slice()`], [`.slice_mut()`], and [`.slice_move()`], and shape -/// `[2, 1, 4]` for [`.slice_collapse()`]. +/// For example `s![0..4;2, 6, 1..5, NewAxis]` is a slice of the first axis for +/// 0..4 with step size 2, a subview of the second axis at index 6, a slice of +/// the third axis for 1..5 with default step size 1, and a new axis of length +/// 1 at the end of the shape. The input array must have 3 dimensions. The +/// resulting slice would have shape `[2, 4, 1]` for [`.slice()`], +/// [`.slice_mut()`], and [`.slice_move()`], and shape `[2, 1, 4]` for +/// [`.slice_collapse()`]. /// /// [`.slice()`]: struct.ArrayBase.html#method.slice /// [`.slice_mut()`]: struct.ArrayBase.html#method.slice_mut @@ -726,11 +774,11 @@ macro_rules! s( } } }; - // convert range/index into AxisSliceInfo + // convert range/index/new-axis into AxisSliceInfo (@convert $r:expr) => { <$crate::AxisSliceInfo as ::std::convert::From<_>>::from($r) }; - // convert range/index and step into AxisSliceInfo + // convert range/index/new-axis and step into AxisSliceInfo (@convert $r:expr, $s:expr) => { <$crate::AxisSliceInfo as ::std::convert::From<_>>::from($r).step_by($s as isize) }; diff --git a/tests/array.rs b/tests/array.rs index d47199bc8..06c49c934 100644 --- a/tests/array.rs +++ b/tests/array.rs @@ -89,8 +89,8 @@ fn test_slice() *elt = i; } - let vi = A.slice(s![1.., ..;2, Slice::new(0, None, 2)]); - assert_eq!(vi.shape(), &[2, 2, 3]); + let vi = A.slice(s![1.., ..;2, NewAxis, Slice::new(0, None, 2)]); + assert_eq!(vi.shape(), &[2, 2, 1, 3]); let vi = A.slice(s![.., .., ..]); assert_eq!(vi.shape(), A.shape()); assert!(vi.iter().zip(A.iter()).all(|(a, b)| a == b)); @@ -126,8 +126,8 @@ fn test_slice_with_many_dim() { *elt = i; } - let vi = A.slice(s![..2, .., ..;2, ..1, ..1, 1.., ..]); - let new_shape = &[2, 1, 2, 1, 1, 1, 1][..]; + let vi = A.slice(s![..2, NewAxis, .., ..;2, NewAxis, ..1, ..1, 1.., ..]); + let new_shape = &[2, 1, 1, 2, 1, 1, 1, 1, 1][..]; assert_eq!(vi.shape(), new_shape); let correct = array![ [A[&[0, 0, 0, 0, 0, 1, 0][..]], A[&[0, 0, 2, 0, 0, 1, 0][..]]], @@ -183,7 +183,7 @@ fn test_slice_args_eval_step_once() { #[test] fn test_slice_array_fixed() { let mut arr = Array3::::zeros((5, 2, 5)); - let info = s![1.., 1, ..;2]; + let info = s![1.., 1, NewAxis, ..;2]; arr.slice(info); arr.slice_mut(info); arr.view().slice_move(info); @@ -193,7 +193,7 @@ fn test_slice_array_fixed() { #[test] fn test_slice_dyninput_array_fixed() { let mut arr = Array3::::zeros((5, 2, 5)).into_dyn(); - let info = s![1.., 1, ..;2]; + let info = s![1.., 1, NewAxis, ..;2]; arr.slice(info); arr.slice_mut(info); arr.view().slice_move(info); @@ -206,6 +206,7 @@ fn test_slice_array_dyn() { let info = &SliceInfo::<_, Ix3, IxDyn>::new([ AxisSliceInfo::from(1..), AxisSliceInfo::from(1), + AxisSliceInfo::from(NewAxis), AxisSliceInfo::from(..).step_by(2), ]).unwrap(); arr.slice(info); @@ -220,6 +221,7 @@ fn test_slice_dyninput_array_dyn() { let info = &SliceInfo::<_, Ix3, IxDyn>::new([ AxisSliceInfo::from(1..), AxisSliceInfo::from(1), + AxisSliceInfo::from(NewAxis), AxisSliceInfo::from(..).step_by(2), ]).unwrap(); arr.slice(info); @@ -231,9 +233,10 @@ fn test_slice_dyninput_array_dyn() { #[test] fn test_slice_dyninput_vec_fixed() { let mut arr = Array3::::zeros((5, 2, 5)).into_dyn(); - let info = &SliceInfo::<_, Ix3, Ix2>::new(vec![ + let info = &SliceInfo::<_, Ix3, Ix3>::new(vec![ AxisSliceInfo::from(1..), AxisSliceInfo::from(1), + AxisSliceInfo::from(NewAxis), AxisSliceInfo::from(..).step_by(2), ]).unwrap(); arr.slice(info); @@ -248,6 +251,7 @@ fn test_slice_dyninput_vec_dyn() { let info = &SliceInfo::<_, Ix3, IxDyn>::new(vec![ AxisSliceInfo::from(1..), AxisSliceInfo::from(1), + AxisSliceInfo::from(NewAxis), AxisSliceInfo::from(..).step_by(2), ]).unwrap(); arr.slice(info); @@ -257,28 +261,34 @@ fn test_slice_dyninput_vec_dyn() { } #[test] -fn test_slice_with_subview() { +fn test_slice_with_subview_and_new_axis() { let mut arr = ArcArray::::zeros((3, 5, 4)); for (i, elt) in arr.iter_mut().enumerate() { *elt = i; } - let vi = arr.slice(s![1.., 2, ..;2]); - assert_eq!(vi.shape(), &[2, 2]); + let vi = arr.slice(s![NewAxis, 1.., 2, ..;2]); + assert_eq!(vi.shape(), &[1, 2, 2]); assert!( vi.iter() - .zip(arr.index_axis(Axis(1), 2).slice(s![1.., ..;2]).iter()) + .zip( + arr.index_axis(Axis(1), 2) + .slice(s![1.., ..;2]) + .insert_axis(Axis(0)) + .iter(), + ) .all(|(a, b)| a == b) ); - let vi = arr.slice(s![1, 2, ..;2]); - assert_eq!(vi.shape(), &[2]); + let vi = arr.slice(s![1, NewAxis, 2, ..;2]); + assert_eq!(vi.shape(), &[1, 2]); assert!( vi.iter() .zip( arr.index_axis(Axis(0), 1) .index_axis(Axis(0), 2) .slice(s![..;2]) + .insert_axis(Axis(0)) .iter() ) .all(|(a, b)| a == b) @@ -298,7 +308,7 @@ fn test_slice_collapse_with_indices() { { let mut vi = arr.view(); - vi.slice_collapse(s![1.., 2, ..;2]); + vi.slice_collapse(s![NewAxis, 1.., 2, ..;2]); assert_eq!(vi.shape(), &[2, 1, 2]); assert!( vi.iter() @@ -307,7 +317,7 @@ fn test_slice_collapse_with_indices() { ); let mut vi = arr.view(); - vi.slice_collapse(s![1, 2, ..;2]); + vi.slice_collapse(s![1, NewAxis, 2, ..;2]); assert_eq!(vi.shape(), &[1, 1, 2]); assert!( vi.iter() @@ -316,7 +326,7 @@ fn test_slice_collapse_with_indices() { ); let mut vi = arr.view(); - vi.slice_collapse(s![1, 2, 3]); + vi.slice_collapse(s![1, 2, NewAxis, 3]); assert_eq!(vi.shape(), &[1, 1, 1]); assert_eq!(vi, Array3::from_elem((1, 1, 1), arr[(1, 2, 3)])); } @@ -324,7 +334,7 @@ fn test_slice_collapse_with_indices() { // Do it to the ArcArray itself let elem = arr[(1, 2, 3)]; let mut vi = arr; - vi.slice_collapse(s![1, 2, 3]); + vi.slice_collapse(s![1, 2, 3, NewAxis]); assert_eq!(vi.shape(), &[1, 1, 1]); assert_eq!(vi, Array3::from_elem((1, 1, 1), elem)); } @@ -378,7 +388,7 @@ fn test_multislice() { fn test_multislice_intersecting() { assert_panics!({ let mut arr = Array2::::zeros((8, 6)); - multislice!(arr, mut [3, ..], [3, ..]); + multislice!(arr, mut [3, .., NewAxis], [3, ..]); }); assert_panics!({ let mut arr = Array2::::zeros((8, 6)); @@ -386,7 +396,7 @@ fn test_multislice_intersecting() { }); assert_panics!({ let mut arr = Array2::::zeros((8, 6)); - multislice!(arr, mut [3, ..], [..;3, ..]); + multislice!(arr, mut [3, ..], [..;3, NewAxis, ..]); }); assert_panics!({ let mut arr = Array2::::zeros((8, 6));