diff --git a/examples/axis_ops.rs b/examples/axis_ops.rs index 452dbba88..46a0b3c5d 100644 --- a/examples/axis_ops.rs +++ b/examples/axis_ops.rs @@ -47,7 +47,7 @@ fn main() { } a.swap_axes(0, 1); a.swap_axes(0, 2); - a.slice_inplace(s![.., ..;-1, ..]); + a.slice_collapse(s![.., ..;-1, ..]); regularize(&mut a).ok(); let mut b = Array::::zeros((2, 3, 4)); @@ -64,6 +64,6 @@ fn main() { for (i, elt) in (0..).zip(&mut a) { *elt = i; } - a.slice_inplace(s![..;-1, ..;2, ..]); + a.slice_collapse(s![..;-1, ..;2, ..]); regularize(&mut a).ok(); } diff --git a/examples/sort-axis.rs b/examples/sort-axis.rs index 69b1f13aa..1a23146e9 100644 --- a/examples/sort-axis.rs +++ b/examples/sort-axis.rs @@ -109,8 +109,8 @@ impl PermuteArray for Array result = Array::from_shape_vec_unchecked(self.dim(), v); for i in 0..axis_len { let perm_i = perm.indices[i]; - Zip::from(result.subview_mut(axis, perm_i)) - .and(self.subview(axis, i)) + Zip::from(result.index_axis_mut(axis, perm_i)) + .and(self.index_axis(axis, i)) .apply(|to, from| { copy_nonoverlapping(from, to, 1) }); diff --git a/serialization-tests/tests/serialize.rs b/serialization-tests/tests/serialize.rs index 99d9f8191..9df55c37f 100644 --- a/serialization-tests/tests/serialize.rs +++ b/serialization-tests/tests/serialize.rs @@ -53,7 +53,7 @@ fn serial_many_dim() { // Test a sliced array. let mut a = RcArray::linspace(0., 31., 32).reshape((2, 2, 2, 4)); - a.slice_inplace(s![..;-1, .., .., ..2]); + a.slice_collapse(s![..;-1, .., .., ..2]); let serial = json::encode(&a).unwrap(); println!("Encode {:?} => {:?}", a, serial); let res = json::decode::>(&serial); @@ -114,7 +114,7 @@ fn serial_many_dim_serde() { // Test a sliced array. let mut a = RcArray::linspace(0., 31., 32).reshape((2, 2, 2, 4)); - a.slice_inplace(s![..;-1, .., .., ..2]); + a.slice_collapse(s![..;-1, .., .., ..2]); let serial = serde_json::to_string(&a).unwrap(); println!("Encode {:?} => {:?}", a, serial); let res = serde_json::from_str::>(&serial); @@ -221,7 +221,7 @@ fn serial_many_dim_serde_msgpack() { // Test a sliced array. let mut a = RcArray::linspace(0., 31., 32).reshape((2, 2, 2, 4)); - a.slice_inplace(s![..;-1, .., .., ..2]); + a.slice_collapse(s![..;-1, .., .., ..2]); let mut buf = Vec::new(); serde::Serialize::serialize(&a, &mut rmp_serde::Serializer::new(&mut buf)).ok().unwrap(); @@ -273,7 +273,7 @@ fn serial_many_dim_ron() { // Test a sliced array. let mut a = RcArray::linspace(0., 31., 32).reshape((2, 2, 2, 4)); - a.slice_inplace(s![..;-1, .., .., ..2]); + a.slice_collapse(s![..;-1, .., .., ..2]); let a_s = ron_serialize(&a).unwrap(); diff --git a/src/dimension/mod.rs b/src/dimension/mod.rs index fee9e9c37..7be31babb 100644 --- a/src/dimension/mod.rs +++ b/src/dimension/mod.rs @@ -197,13 +197,18 @@ impl<'a> DimensionExt for [Ix] /// /// **Panics** if `index` is larger than the size of the axis // FIXME: Move to Dimension trait -pub fn do_sub(dims: &mut D, ptr: &mut *mut A, strides: &D, - axis: usize, index: Ix) { +pub fn do_collapse_axis( + dims: &mut D, + ptr: &mut *mut A, + strides: &D, + axis: usize, + index: usize, +) { let dim = dims.slice()[axis]; let stride = strides.slice()[axis]; ndassert!(index < dim, - concat!("subview: Index {} must be less than axis length {} ", - "for array with shape {:?}"), + "collapse_axis: Index {} must be less than axis length {} for \ + array with shape {:?}", index, dim, *dims); dims.slice_mut()[axis] = 1; let off = stride_offset(index, stride); diff --git a/src/doc/ndarray_for_numpy_users/mod.rs b/src/doc/ndarray_for_numpy_users/mod.rs index 80fec5dfe..0e46c6850 100644 --- a/src/doc/ndarray_for_numpy_users/mod.rs +++ b/src/doc/ndarray_for_numpy_users/mod.rs @@ -229,7 +229,7 @@ //! Only the non-mutable methods that take the array by reference are listed in //! this table. For example, [`.slice()`][.slice()] also has corresponding //! methods [`.slice_mut()`][.slice_mut()], [`.slice_move()`][.slice_move()], and -//! [`.slice_inplace()`][.slice_inplace()]. +//! [`.slice_collapse()`][.slice_collapse()]. //! //! * The behavior of slicing is slightly different from NumPy for slices with //! `step < -1`. See the docs for the [`s![]` macro][s!] for more details. @@ -238,7 +238,7 @@ //! ------|-----------|------ //! `a[-1]` | [`a[a.len() - 1]`][.index()] | access the last element in 1-D array `a` //! `a[1, 4]` | [`a[[1, 4]]`][.index()] | access the element in row 1, column 4 -//! `a[1]` or `a[1, :, :]` | [`a.slice(s![1, .., ..])`][.slice()] or [`a.subview(Axis(0), 1)`][.subview()] | get a 2-D subview of a 3-D array at index 1 of axis 0 +//! `a[1]` or `a[1, :, :]` | [`a.slice(s![1, .., ..])`][.slice()] or [`a.index_axis(Axis(0), 1)`][.index_axis()] | get a 2-D subview of a 3-D array at index 1 of axis 0 //! `a[0:5]` or `a[:5]` or `a[0:5, :]` | [`a.slice(s![0..5, ..])`][.slice()] or [`a.slice(s![..5, ..])`][.slice()] or [`a.slice_axis(Axis(0), Slice::from(0..5))`][.slice_axis()] | get the first 5 rows of a 2-D array //! `a[-5:]` or `a[-5:, :]` | [`a.slice(s![-5.., ..])`][.slice()] or [`a.slice_axis(Axis(0), Slice::from(-5..))`][.slice_axis()] | get the last 5 rows of a 2-D array //! `a[:3, 4:9]` | [`a.slice(s![..3, 4..9])`][.slice()] | columns 4, 5, 6, 7, and 8 of the first 3 rows @@ -618,14 +618,14 @@ //! [.sum()]: ../../struct.ArrayBase.html#method.sum //! [.slice()]: ../../struct.ArrayBase.html#method.slice //! [.slice_axis()]: ../../struct.ArrayBase.html#method.slice_axis -//! [.slice_inplace()]: ../../struct.ArrayBase.html#method.slice_inplace +//! [.slice_collapse()]: ../../struct.ArrayBase.html#method.slice_collapse //! [.slice_move()]: ../../struct.ArrayBase.html#method.slice_move //! [.slice_mut()]: ../../struct.ArrayBase.html#method.slice_mut //! [.shape()]: ../../struct.ArrayBase.html#method.shape //! [stack!]: ../../macro.stack.html //! [stack()]: ../../fn.stack.html //! [.strides()]: ../../struct.ArrayBase.html#method.strides -//! [.subview()]: ../../struct.ArrayBase.html#method.subview +//! [.index_axis()]: ../../struct.ArrayBase.html#method.index_axis //! [.sum_axis()]: ../../struct.ArrayBase.html#method.sum_axis //! [.t()]: ../../struct.ArrayBase.html#method.t //! [::uninitialized()]: ../../struct.ArrayBase.html#method.uninitialized diff --git a/src/impl_2d.rs b/src/impl_2d.rs index 540a6c65d..428da0f23 100644 --- a/src/impl_2d.rs +++ b/src/impl_2d.rs @@ -19,7 +19,7 @@ impl ArrayBase /// **Panics** if `index` is out of bounds. pub fn row(&self, index: Ix) -> ArrayView1 { - self.subview(Axis(0), index) + self.index_axis(Axis(0), index) } /// Return a mutable array view of row `index`. @@ -28,7 +28,7 @@ impl ArrayBase pub fn row_mut(&mut self, index: Ix) -> ArrayViewMut1 where S: DataMut { - self.subview_mut(Axis(0), index) + self.index_axis_mut(Axis(0), index) } /// Return the number of rows (length of `Axis(0)`) in the two-dimensional array. @@ -41,7 +41,7 @@ impl ArrayBase /// **Panics** if `index` is out of bounds. pub fn column(&self, index: Ix) -> ArrayView1 { - self.subview(Axis(1), index) + self.index_axis(Axis(1), index) } /// Return a mutable array view of column `index`. @@ -50,7 +50,7 @@ impl ArrayBase pub fn column_mut(&mut self, index: Ix) -> ArrayViewMut1 where S: DataMut { - self.subview_mut(Axis(1), index) + self.index_axis_mut(Axis(1), index) } /// Return the number of columns (length of `Axis(1)`) in the two-dimensional array. diff --git a/src/impl_dyn.rs b/src/impl_dyn.rs new file mode 100644 index 000000000..174ab8e44 --- /dev/null +++ b/src/impl_dyn.rs @@ -0,0 +1,58 @@ +// Copyright 2018 bluss and ndarray developers. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +//! Methods for dynamic-dimensional arrays. +use imp_prelude::*; + +/// # Methods for Dynamic-Dimensional Arrays +impl ArrayBase +where + S: Data, +{ + /// Insert new array axis of length 1 at `axis`, modifying the shape and + /// strides in-place. + /// + /// **Panics** if the axis is out of bounds. + /// + /// ``` + /// use ndarray::{Axis, arr2, arr3}; + /// + /// let mut a = arr2(&[[1, 2, 3], [4, 5, 6]]).into_dyn(); + /// assert_eq!(a.shape(), &[2, 3]); + /// + /// a.insert_axis_inplace(Axis(1)); + /// assert_eq!(a, arr3(&[[[1, 2, 3]], [[4, 5, 6]]]).into_dyn()); + /// assert_eq!(a.shape(), &[2, 1, 3]); + /// ``` + pub fn insert_axis_inplace(&mut self, axis: Axis) { + assert!(axis.index() <= self.ndim()); + self.dim = self.dim.insert_axis(axis); + self.strides = self.strides.insert_axis(axis); + } + + /// Collapses the array to `index` along the axis and removes the axis, + /// modifying the shape and strides in-place. + /// + /// **Panics** if `axis` or `index` is out of bounds. + /// + /// ``` + /// use ndarray::{Axis, arr1, arr2}; + /// + /// let mut a = arr2(&[[1, 2, 3], [4, 5, 6]]).into_dyn(); + /// assert_eq!(a.shape(), &[2, 3]); + /// + /// a.index_axis_inplace(Axis(1), 1); + /// assert_eq!(a, arr1(&[2, 5]).into_dyn()); + /// assert_eq!(a.shape(), &[2]); + /// ``` + pub fn index_axis_inplace(&mut self, axis: Axis, index: usize) { + self.collapse_axis(axis, index); + self.dim = self.dim.remove_axis(axis); + self.strides = self.strides.remove_axis(axis); + } +} diff --git a/src/impl_methods.rs b/src/impl_methods.rs index d37695e69..8187d7dc8 100644 --- a/src/impl_methods.rs +++ b/src/impl_methods.rs @@ -310,8 +310,8 @@ impl ArrayBase where S: Data, D: Dimension where Do: Dimension, { - // Slice and subview in-place without changing the number of dimensions. - self.slice_inplace(&*info); + // Slice and collapse in-place without changing the number of dimensions. + self.slice_collapse(&*info); let indices: &[SliceOrIndex] = (**info).as_ref(); @@ -352,7 +352,7 @@ impl ArrayBase where S: Data, D: Dimension /// /// **Panics** if an index is out of bounds or step size is zero.
/// (**Panics** if `D` is `IxDyn` and `indices` does not match the number of array axes.) - pub fn slice_inplace(&mut self, indices: &D::SliceArg) { + pub fn slice_collapse(&mut self, indices: &D::SliceArg) { let indices: &[SliceOrIndex] = indices.as_ref(); assert_eq!(indices.len(), self.ndim()); indices @@ -364,11 +364,20 @@ impl ArrayBase where S: Data, D: Dimension } &SliceOrIndex::Index(index) => { let i_usize = abs_index(self.len_of(Axis(axis)), index); - self.subview_inplace(Axis(axis), i_usize) + self.collapse_axis(Axis(axis), i_usize) } }); } + /// Slice the array in place without changing the number of dimensions. + /// + /// **Panics** if an index is out of bounds or step size is zero.
+ /// (**Panics** if `D` is `IxDyn` and `indices` does not match the number of array axes.) + #[deprecated(note="renamed to `slice_collapse`", since="0.12.1")] + pub fn slice_inplace(&mut self, indices: &D::SliceArg) { + self.slice_collapse(indices) + } + /// Return a view of the array, sliced along the specified axis. /// /// **Panics** if an index is out of bounds or step size is zero.
@@ -542,8 +551,8 @@ impl ArrayBase where S: Data, D: Dimension } } - /// Along `axis`, select the subview `index` and return a - /// view with that axis removed. + /// Returns a view restricted to `index` along the axis, with the axis + /// removed. /// /// See [*Subviews*](#subviews) for full documentation. /// @@ -559,18 +568,19 @@ impl ArrayBase where S: Data, D: Dimension /// // . axis 1, column 1 /// // axis 1, column 0 /// assert!( - /// a.subview(Axis(0), 1) == ArrayView::from(&[3., 4.]) && - /// a.subview(Axis(1), 1) == ArrayView::from(&[2., 4., 6.]) + /// a.index_axis(Axis(0), 1) == ArrayView::from(&[3., 4.]) && + /// a.index_axis(Axis(1), 1) == ArrayView::from(&[2., 4., 6.]) /// ); /// ``` - pub fn subview(&self, axis: Axis, index: Ix) -> ArrayView - where D: RemoveAxis, + pub fn index_axis(&self, axis: Axis, index: usize) -> ArrayView + where + D: RemoveAxis, { - self.view().into_subview(axis, index) + self.view().index_axis_move(axis, index) } - /// Along `axis`, select the subview `index` and return a read-write view - /// with the axis removed. + /// Returns a mutable view restricted to `index` along the axis, with the + /// axis removed. /// /// **Panics** if `axis` or `index` is out of bounds. /// @@ -584,7 +594,7 @@ impl ArrayBase where S: Data, D: Dimension /// // axis 1, column 0 /// /// { - /// let mut column1 = a.subview_mut(Axis(1), 1); + /// let mut column1 = a.index_axis_mut(Axis(1), 1); /// column1 += 10.; /// } /// @@ -593,32 +603,87 @@ impl ArrayBase where S: Data, D: Dimension /// [3., 14.]]) /// ); /// ``` + pub fn index_axis_mut(&mut self, axis: Axis, index: usize) -> ArrayViewMut + where + S: DataMut, + D: RemoveAxis, + { + self.view_mut().index_axis_move(axis, index) + } + + /// Collapses the array to `index` along the axis and removes the axis. + /// + /// See [`.index_axis()`](#method.index_axis) and [*Subviews*](#subviews) for full documentation. + /// + /// **Panics** if `axis` or `index` is out of bounds. + pub fn index_axis_move(mut self, axis: Axis, index: usize) -> ArrayBase + where + D: RemoveAxis, + { + self.collapse_axis(axis, index); + let dim = self.dim.remove_axis(axis); + let strides = self.strides.remove_axis(axis); + ArrayBase { + ptr: self.ptr, + data: self.data, + dim, + strides, + } + } + + /// Selects `index` along the axis, collapsing the axis into length one. + /// + /// **Panics** if `axis` or `index` is out of bounds. + pub fn collapse_axis(&mut self, axis: Axis, index: usize) { + dimension::do_collapse_axis( + &mut self.dim, + &mut self.ptr, + &self.strides, + axis.index(), + index, + ) + } + + /// Along `axis`, select the subview `index` and return a + /// view with that axis removed. + /// + /// **Panics** if `axis` or `index` is out of bounds. + #[deprecated(note="renamed to `index_axis`", since="0.12.1")] + pub fn subview(&self, axis: Axis, index: Ix) -> ArrayView + where D: RemoveAxis, + { + self.index_axis(axis, index) + } + + /// Along `axis`, select the subview `index` and return a read-write view + /// with the axis removed. + /// + /// **Panics** if `axis` or `index` is out of bounds. + #[deprecated(note="renamed to `index_axis_mut`", since="0.12.1")] pub fn subview_mut(&mut self, axis: Axis, index: Ix) -> ArrayViewMut where S: DataMut, D: RemoveAxis, { - self.view_mut().into_subview(axis, index) + self.index_axis_mut(axis, index) } /// Collapse dimension `axis` into length one, /// and select the subview of `index` along that axis. /// /// **Panics** if `index` is past the length of the axis. + #[deprecated(note="renamed to `collapse_axis`", since="0.12.1")] pub fn subview_inplace(&mut self, axis: Axis, index: Ix) { - dimension::do_sub(&mut self.dim, &mut self.ptr, &self.strides, - axis.index(), index) + self.collapse_axis(axis, index) } /// Along `axis`, select the subview `index` and return `self` /// with that axis removed. - /// - /// See [`.subview()`](#method.subview) and [*Subviews*](#subviews) for full documentation. - pub fn into_subview(mut self, axis: Axis, index: Ix) -> ArrayBase + #[deprecated(note="renamed to `index_axis_move`", since="0.12.1")] + pub fn into_subview(self, axis: Axis, index: Ix) -> ArrayBase where D: RemoveAxis, { - self.subview_inplace(axis, index); - self.remove_axis(axis) + self.index_axis_move(axis, index) } /// Along `axis`, select arbitrary subviews corresponding to `indices` @@ -648,7 +713,7 @@ impl ArrayBase where S: Data, D: Dimension { let mut subs = vec![self.view(); indices.len()]; for (&i, sub) in zip(indices, &mut subs[..]) { - sub.subview_inplace(axis, i); + sub.collapse_axis(axis, i); } if subs.is_empty() { let mut dim = self.raw_dim(); @@ -1528,18 +1593,11 @@ impl ArrayBase where S: Data, D: Dimension /// Remove array axis `axis` and return the result. /// /// **Panics** if the axis is out of bounds or its length is zero. + #[deprecated(note="use `.index_axis_move(Axis(_), 0)` instead", since="0.12.1")] pub fn remove_axis(self, axis: Axis) -> ArrayBase where D: RemoveAxis, { - assert_ne!(self.len_of(axis), 0, "Length of removed axis must be nonzero."); - let d = self.dim.remove_axis(axis); - let s = self.strides.remove_axis(axis); - ArrayBase { - ptr: self.ptr, - data: self.data, - dim: d, - strides: s, - } + self.index_axis_move(axis, 0) } fn pointer_is_inbounds(&self) -> bool { @@ -1857,7 +1915,7 @@ impl ArrayBase where S: Data, D: Dimension let view_stride = self.strides.axis(axis); // use the 0th subview as a map to each 1d array view extended from // the 0th element. - self.subview(axis, 0).map(|first_elt| { + self.index_axis(axis, 0).map(|first_elt| { unsafe { mapping(ArrayView::new_(first_elt, Ix1(view_len), Ix1(view_stride))) } @@ -1885,7 +1943,7 @@ impl ArrayBase where S: Data, D: Dimension let view_stride = self.strides.axis(axis); // use the 0th subview as a map to each 1d array view extended from // the 0th element. - self.subview_mut(axis, 0).map_mut(|first_elt: &mut A| { + self.index_axis_mut(axis, 0).map_mut(|first_elt: &mut A| { unsafe { mapping(ArrayViewMut::new_(first_elt, Ix1(view_len), Ix1(view_stride))) } diff --git a/src/lib.rs b/src/lib.rs index ed60d55d2..2e0f7490e 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -242,6 +242,7 @@ pub type Ixs = isize; /// + [Methods For All Array Types](#methods-for-all-array-types) /// + [Methods For 1-D Arrays](#methods-for-1-d-arrays) /// + [Methods For 2-D Arrays](#methods-for-2-d-arrays) +/// + [Methods for Dynamic-Dimensional Arrays](#methods-for-dynamic-dimensional-arrays) /// + [Numerical Methods for Arrays](#numerical-methods-for-arrays) /// /// ## `Array` @@ -444,7 +445,7 @@ pub type Ixs = isize; /// /// You can use slicing to create a view of a subset of the data in /// the array. Slicing methods include [`.slice()`], [`.slice_mut()`], -/// [`.slice_move()`], and [`.slice_inplace()`]. +/// [`.slice_move()`], and [`.slice_collapse()`]. /// /// The slicing argument can be passed using the macro [`s![]`](macro.s!.html), /// which will be used in all examples. (The explicit form is an instance of @@ -452,15 +453,16 @@ pub type Ixs = isize; /// /// [`&SliceInfo`]: struct.SliceInfo.html /// -/// If a range is used, the axis is preserved. If an index is used, a subview -/// is taken with respect to the axis. See [*Subviews*](#subviews) for more -/// information about subviews. Note that [`.slice_inplace()`] behaves like -/// [`.subview_inplace()`] by preserving the number of dimensions. +/// 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. /// /// [`.slice()`]: #method.slice /// [`.slice_mut()`]: #method.slice_mut /// [`.slice_move()`]: #method.slice_move -/// [`.slice_inplace()`]: #method.slice_inplace +/// [`.slice_collapse()`]: #method.slice_collapse /// /// ``` /// // import the s![] macro @@ -504,7 +506,7 @@ pub type Ixs = isize; /// assert_eq!(d, e); /// assert_eq!(d.shape(), &[2, 1, 3]); /// -/// // Let’s create a slice while taking a subview with +/// // Let’s create a slice while selecting a subview with /// // /// // - Both submatrices of the greatest dimension: `..` /// // - The last row in each submatrix, removing that axis: `-1` @@ -520,17 +522,31 @@ pub type Ixs = isize; /// ## Subviews /// /// Subview methods allow you to restrict the array view while removing one -/// axis from the array. Subview methods include [`.subview()`], -/// [`.subview_mut()`], [`.into_subview()`], and [`.subview_inplace()`]. You -/// can also take a subview by using a single index instead of a range when -/// slicing. -/// -/// Subview takes two arguments: `axis` and `index`. -/// -/// [`.subview()`]: #method.subview -/// [`.subview_mut()`]: #method.subview_mut -/// [`.into_subview()`]: #method.into_subview -/// [`.subview_inplace()`]: #method.subview_inplace +/// axis from the array. Methods for selecting individual subviews include +/// [`.index_axis()`], [`.index_axis_mut()`], [`.index_axis_move()`], and +/// [`.index_axis_inplace()`]. You can also select a subview by using a single +/// index instead of a range when slicing. Some other methods, such as +/// [`.fold_axis()`], [`.axis_iter()`], [`.axis_iter_mut()`], +/// [`.outer_iter()`], and [`.outer_iter_mut()`] operate on all the subviews +/// along an axis. +/// +/// A related method is [`.collapse_axis()`], which modifies the view in the +/// same way as [`.index_axis()`] except for removing the collapsed axis, since +/// it operates *in place*. The length of the axis becomes 1. +/// +/// Methods for selecting an individual subview take two arguments: `axis` and +/// `index`. +/// +/// [`.axis_iter()`]: #method.axis_iter +/// [`.axis_iter_mut()`]: #method.axis_iter_mut +/// [`.fold_axis()`]: #method.fold_axis +/// [`.index_axis()`]: #method.index_axis +/// [`.index_axis_inplace()`]: #method.index_axis_inplace +/// [`.index_axis_mut()`]: #method.index_axis_mut +/// [`.index_axis_move()`]: #method.index_axis_move +/// [`.collapse_axis()`]: #method.collapse_axis +/// [`.outer_iter()`]: #method.outer_iter +/// [`.outer_iter_mut()`]: #method.outer_iter_mut /// /// ``` /// #[macro_use(s)] extern crate ndarray; @@ -553,8 +569,8 @@ pub type Ixs = isize; /// // Let’s take a subview along the greatest dimension (axis 0), /// // taking submatrix 0, then submatrix 1 /// -/// let sub_0 = a.subview(Axis(0), 0); -/// let sub_1 = a.subview(Axis(0), 1); +/// let sub_0 = a.index_axis(Axis(0), 0); +/// let sub_1 = a.index_axis(Axis(0), 1); /// /// assert_eq!(sub_0, aview2(&[[ 1, 2, 3], /// [ 4, 5, 6]])); @@ -563,7 +579,7 @@ pub type Ixs = isize; /// assert_eq!(sub_0.shape(), &[2, 3]); /// /// // This is the subview picking only axis 2, column 0 -/// let sub_col = a.subview(Axis(2), 0); +/// let sub_col = a.index_axis(Axis(2), 0); /// /// assert_eq!(sub_col, aview2(&[[ 1, 4], /// [ 7, 10]])); @@ -574,14 +590,6 @@ pub type Ixs = isize; /// # } /// ``` /// -/// [`.subview_inplace()`] modifies the view in the same way as [`.subview()`], -/// but since it is *in place*, it cannot remove the collapsed axis. It becomes -/// an axis of length 1. -/// -/// `.outer_iter()` is an iterator of every subview along the zeroth (outer) -/// axis, while `.axis_iter()` is an iterator of every subview along a -/// specific axis. -/// /// ## Arithmetic Operations /// /// Arrays support all arithmetic operations the same way: they apply elementwise. @@ -1144,6 +1152,7 @@ impl ArrayBase mod impl_1d; mod impl_2d; +mod impl_dyn; mod numeric; diff --git a/src/numeric/impl_numeric.rs b/src/numeric/impl_numeric.rs index ac6864f4c..60e995a59 100644 --- a/src/numeric/impl_numeric.rs +++ b/src/numeric/impl_numeric.rs @@ -107,11 +107,11 @@ impl ArrayBase // contiguous along the axis we are summing let ax = axis.index(); for (i, elt) in enumerate(&mut res) { - *elt = self.subview(Axis(1 - ax), i).sum(); + *elt = self.index_axis(Axis(1 - ax), i).sum(); } } else { for i in 0..n { - let view = self.subview(axis, i); + let view = self.index_axis(axis, i); res = res + &view; } } diff --git a/src/slice.rs b/src/slice.rs index e2145e7b0..a1f0bc35b 100644 --- a/src/slice.rs +++ b/src/slice.rs @@ -465,12 +465,14 @@ impl_slicenextdim_larger!((), Slice); /// The syntax is `s![` *[ axis-slice-or-index [, axis-slice-or-index [ , ... ] /// ] ]* `]`, where *axis-slice-or-index* is any of the following: /// -/// * *index*: an index to use for taking a subview with respect to that axis -/// * *range*: a range with step size 1 to use for slicing that axis -/// * *range* `;` *step*: a range with step size *step* to use for slicing that axis -/// * *slice*: a [`Slice`] instance to use for slicing that axis +/// * *index*: an index to use for taking a subview with respect to that axis. +/// (The index is selected. The axis is removed except with +/// [`.slice_collapse()`].) +/// * *range*: a range with step size 1 to use for slicing that axis. +/// * *range* `;` *step*: a range with step size *step* to use for slicing that axis. +/// * *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 +/// instance, with new step size *step*, to use for slicing that axis. /// /// [`Slice`]: struct.Slice.html /// @@ -486,12 +488,12 @@ impl_slicenextdim_larger!((), Slice); /// 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_inplace()`]. +/// `[2, 1, 4]` for [`.slice_collapse()`]. /// /// [`.slice()`]: struct.ArrayBase.html#method.slice /// [`.slice_mut()`]: struct.ArrayBase.html#method.slice_mut /// [`.slice_move()`]: struct.ArrayBase.html#method.slice_move -/// [`.slice_inplace()`]: struct.ArrayBase.html#method.slice_inplace +/// [`.slice_collapse()`]: struct.ArrayBase.html#method.slice_collapse /// /// See also [*Slicing*](struct.ArrayBase.html#slicing). /// diff --git a/tests/array.rs b/tests/array.rs index a075246f1..6fc69014b 100644 --- a/tests/array.rs +++ b/tests/array.rs @@ -173,7 +173,7 @@ fn test_slice_array_fixed() { arr.slice(info); arr.slice_mut(info); arr.view().slice_move(info); - arr.view().slice_inplace(info); + arr.view().slice_collapse(info); } #[test] @@ -183,7 +183,7 @@ fn test_slice_dyninput_array_fixed() { arr.slice(info); arr.slice_mut(info); arr.view().slice_move(info); - arr.view().slice_inplace(info.as_ref()); + arr.view().slice_collapse(info.as_ref()); } #[test] @@ -197,7 +197,7 @@ fn test_slice_array_dyn() { arr.slice(info); arr.slice_mut(info); arr.view().slice_move(info); - arr.view().slice_inplace(info); + arr.view().slice_collapse(info); } #[test] @@ -211,7 +211,7 @@ fn test_slice_dyninput_array_dyn() { arr.slice(info); arr.slice_mut(info); arr.view().slice_move(info); - arr.view().slice_inplace(info.as_ref()); + arr.view().slice_collapse(info.as_ref()); } #[test] @@ -225,7 +225,7 @@ fn test_slice_dyninput_vec_fixed() { arr.slice(info.as_ref()); arr.slice_mut(info.as_ref()); arr.view().slice_move(info.as_ref()); - arr.view().slice_inplace(info.as_ref()); + arr.view().slice_collapse(info.as_ref()); } #[test] @@ -239,7 +239,7 @@ fn test_slice_dyninput_vec_dyn() { arr.slice(info.as_ref()); arr.slice_mut(info.as_ref()); arr.view().slice_move(info.as_ref()); - arr.view().slice_inplace(info.as_ref()); + arr.view().slice_collapse(info.as_ref()); } #[test] @@ -253,7 +253,7 @@ fn test_slice_with_subview() { assert_eq!(vi.shape(), &[2, 2]); assert!( vi.iter() - .zip(arr.subview(Axis(1), 2).slice(s![1.., ..;2]).iter()) + .zip(arr.index_axis(Axis(1), 2).slice(s![1.., ..;2]).iter()) .all(|(a, b)| a == b) ); @@ -262,8 +262,8 @@ fn test_slice_with_subview() { assert!( vi.iter() .zip( - arr.subview(Axis(0), 1) - .subview(Axis(0), 2) + arr.index_axis(Axis(0), 1) + .index_axis(Axis(0), 2) .slice(s![..;2]) .iter() ) @@ -276,7 +276,7 @@ fn test_slice_with_subview() { } #[test] -fn test_slice_inplace_with_subview_inplace() { +fn test_slice_collapse_with_indices() { let mut arr = RcArray::::zeros((3, 5, 4)); for (i, elt) in arr.iter_mut().enumerate() { *elt = i; @@ -284,7 +284,7 @@ fn test_slice_inplace_with_subview_inplace() { { let mut vi = arr.view(); - vi.slice_inplace(s![1.., 2, ..;2]); + vi.slice_collapse(s![1.., 2, ..;2]); assert_eq!(vi.shape(), &[2, 1, 2]); assert!( vi.iter() @@ -293,7 +293,7 @@ fn test_slice_inplace_with_subview_inplace() { ); let mut vi = arr.view(); - vi.slice_inplace(s![1, 2, ..;2]); + vi.slice_collapse(s![1, 2, ..;2]); assert_eq!(vi.shape(), &[1, 1, 2]); assert!( vi.iter() @@ -302,7 +302,7 @@ fn test_slice_inplace_with_subview_inplace() { ); let mut vi = arr.view(); - vi.slice_inplace(s![1, 2, 3]); + vi.slice_collapse(s![1, 2, 3]); assert_eq!(vi.shape(), &[1, 1, 1]); assert_eq!(vi, Array3::from_elem((1, 1, 1), arr[(1, 2, 3)])); } @@ -310,7 +310,7 @@ fn test_slice_inplace_with_subview_inplace() { // Do it to the RcArray itself let elem = arr[(1, 2, 3)]; let mut vi = arr; - vi.slice_inplace(s![1, 2, 3]); + vi.slice_collapse(s![1, 2, 3]); assert_eq!(vi.shape(), &[1, 1, 1]); assert_eq!(vi, Array3::from_elem((1, 1, 1), elem)); } @@ -458,7 +458,7 @@ fn test_cow() assert_eq!(n[[0, 1]], 0); assert_eq!(n.get((0, 1)), Some(&0)); let mut rev = mat.reshape(4); - rev.slice_inplace(s![..;-1]); + rev.slice_collapse(s![..;-1]); assert_eq!(rev[0], 4); assert_eq!(rev[1], 3); assert_eq!(rev[2], 2); @@ -483,7 +483,7 @@ fn test_cow_shrink() // mutation shrinks the array and gives it different strides // let mut mat = RcArray::zeros((2, 3)); - //mat.slice_inplace(s![.., ..;2]); + //mat.slice_collapse(s![.., ..;2]); mat[[0, 0]] = 1; let n = mat.clone(); mat[[0, 1]] = 2; @@ -498,7 +498,7 @@ fn test_cow_shrink() assert_eq!(n.get((0, 1)), Some(&0)); // small has non-C strides this way let mut small = mat.reshape(6); - small.slice_inplace(s![4..;-1]); + small.slice_collapse(s![4..;-1]); assert_eq!(small[0], 6); assert_eq!(small[1], 5); let before = small.clone(); @@ -515,21 +515,21 @@ fn test_cow_shrink() fn test_sub() { let mat = RcArray::linspace(0., 15., 16).reshape((2, 4, 2)); - let s1 = mat.subview(Axis(0), 0); - let s2 = mat.subview(Axis(0), 1); + let s1 = mat.index_axis(Axis(0), 0); + let s2 = mat.index_axis(Axis(0), 1); assert_eq!(s1.shape(), &[4, 2]); assert_eq!(s2.shape(), &[4, 2]); let n = RcArray::linspace(8., 15., 8).reshape((4,2)); assert_eq!(n, s2); let m = RcArray::from_vec(vec![2., 3., 10., 11.]).reshape((2, 2)); - assert_eq!(m, mat.subview(Axis(1), 1)); + assert_eq!(m, mat.index_axis(Axis(1), 1)); } #[should_panic] #[test] fn test_sub_oob_1() { let mat = RcArray::linspace(0., 15., 16).reshape((2, 4, 2)); - mat.subview(Axis(0), 2); + mat.index_axis(Axis(0), 2); } @@ -590,7 +590,7 @@ fn swapaxes() #[test] fn permuted_axes() { - let a = array![1].into_subview(Axis(0), 0); + let a = array![1].index_axis_move(Axis(0), 0); let permuted = a.view().permuted_axes([]); assert_eq!(a, permuted); @@ -652,9 +652,9 @@ fn standard_layout() assert!(!a.is_standard_layout()); a.swap_axes(0, 1); assert!(a.is_standard_layout()); - let x1 = a.subview(Axis(0), 0); + let x1 = a.index_axis(Axis(0), 0); assert!(x1.is_standard_layout()); - let x2 = a.subview(Axis(1), 0); + let x2 = a.index_axis(Axis(1), 0); assert!(!x2.is_standard_layout()); } @@ -678,7 +678,7 @@ fn assign() let mut a = arr2(&[[1, 2], [3, 4]]); { let mut v = a.view_mut(); - v.slice_inplace(s![..1, ..]); + v.slice_collapse(s![..1, ..]); v.fill(0); } assert_eq!(a, arr2(&[[0, 0], [3, 4]])); @@ -887,7 +887,7 @@ fn zero_axes() println!("{:?}\n{:?}", b.shape(), b); // we can even get a subarray of b - let bsub = b.subview(Axis(0), 2); + let bsub = b.index_axis(Axis(0), 2); assert_eq!(bsub.dim(), 0); } @@ -932,14 +932,14 @@ fn as_slice_memory_order() fn array0_into_scalar() { // With this kind of setup, the `Array`'s pointer is not the same as the // underlying `Vec`'s pointer. - let a: Array0 = array![4, 5, 6, 7].into_subview(Axis(0), 2); + let a: Array0 = array![4, 5, 6, 7].index_axis_move(Axis(0), 2); assert_ne!(a.as_ptr(), a.into_raw_vec().as_ptr()); // `.into_scalar()` should still work correctly. - let a: Array0 = array![4, 5, 6, 7].into_subview(Axis(0), 2); + let a: Array0 = array![4, 5, 6, 7].index_axis_move(Axis(0), 2); assert_eq!(a.into_scalar(), 6); // It should work for zero-size elements too. - let a: Array0<()> = array![(), (), (), ()].into_subview(Axis(0), 2); + let a: Array0<()> = array![(), (), (), ()].index_axis_move(Axis(0), 2); assert_eq!(a.into_scalar(), ()); } @@ -1010,7 +1010,7 @@ fn owned_array_discontiguous_drop() { let v: Vec<_> = (0..12).map(|x| InsertOnDrop(set.clone(), Some(x))).collect(); let mut a = Array::from_shape_vec((2, 6), v).unwrap(); // discontiguous and non-zero offset - a.slice_inplace(s![.., 1..]); + a.slice_collapse(s![.., 1..]); } // each item was dropped exactly once itertools::assert_equal(set.borrow().iter().cloned(), 0..12); @@ -1400,9 +1400,9 @@ fn insert_axis_f() { fn insert_axis_view() { let a = array![[[1, 2], [3, 4]], [[5, 6], [7, 8]], [[9, 10], [11, 12]]]; - assert_eq!(a.subview(Axis(1), 0).insert_axis(Axis(0)), array![[[1, 2], [5, 6], [9, 10]]]); - assert_eq!(a.subview(Axis(1), 0).insert_axis(Axis(1)), array![[[1, 2]], [[5, 6]], [[9, 10]]]); - assert_eq!(a.subview(Axis(1), 0).insert_axis(Axis(2)), array![[[1], [2]], [[5], [6]], [[9], [10]]]); + assert_eq!(a.index_axis(Axis(1), 0).insert_axis(Axis(0)), array![[[1, 2], [5, 6], [9, 10]]]); + assert_eq!(a.index_axis(Axis(1), 0).insert_axis(Axis(1)), array![[[1, 2]], [[5, 6]], [[9, 10]]]); + assert_eq!(a.index_axis(Axis(1), 0).insert_axis(Axis(2)), array![[[1], [2]], [[5], [6]], [[9], [10]]]); } #[test] @@ -1420,7 +1420,7 @@ fn char_array() { // test compilation & basics of non-numerical array let cc = RcArray::from_iter("alphabet".chars()).reshape((4, 2)); - assert!(cc.subview(Axis(1), 0) == RcArray::from_iter("apae".chars())); + assert!(cc.index_axis(Axis(1), 0) == RcArray::from_iter("apae".chars())); } #[test] @@ -1576,7 +1576,7 @@ fn to_owned_memory_order() { fn to_owned_neg_stride() { let mut c = arr2(&[[1, 2, 3], [4, 5, 6]]); - c.slice_inplace(s![.., ..;-1]); + c.slice_collapse(s![.., ..;-1]); let co = c.to_owned(); assert_eq!(c, co); } @@ -1585,7 +1585,7 @@ fn to_owned_neg_stride() { fn discontiguous_owned_to_owned() { let mut c = arr2(&[[1, 2, 3], [4, 5, 6]]); - c.slice_inplace(s![.., ..;2]); + c.slice_collapse(s![.., ..;2]); let co = c.to_owned(); assert_eq!(c.strides(), &[3, 2]); @@ -1753,10 +1753,10 @@ fn test_to_vec() { [7, 8, 9], [10,11,12]]); - a.slice_inplace(s![..;-1, ..]); + a.slice_collapse(s![..;-1, ..]); assert_eq!(a.row(3).to_vec(), vec![1, 2, 3]); assert_eq!(a.column(2).to_vec(), vec![12, 9, 6, 3]); - a.slice_inplace(s![.., ..;-1]); + a.slice_collapse(s![.., ..;-1]); assert_eq!(a.row(3).to_vec(), vec![3, 2, 1]); } @@ -1772,7 +1772,7 @@ fn test_array_clone_unalias() { #[test] fn test_array_clone_same_view() { let mut a = Array::from_iter(0..9).into_shape((3, 3)).unwrap(); - a.slice_inplace(s![..;-1, ..;-1]); + a.slice_collapse(s![..;-1, ..;-1]); let b = a.clone(); assert_eq!(a, b); } diff --git a/tests/dimension.rs b/tests/dimension.rs index 0f095ab94..e10e19bf1 100644 --- a/tests/dimension.rs +++ b/tests/dimension.rs @@ -53,10 +53,10 @@ fn remove_axis() assert_eq!(Dim(vec![4, 5, 6]).remove_axis(Axis(1)), Dim(vec![4, 6])); let a = RcArray::::zeros((4,5)); - a.subview(Axis(1), 0); + a.index_axis(Axis(1), 0); let a = RcArray::::zeros(vec![4,5,6]); - let _b = a.into_subview(Axis(1), 0).reshape((4, 6)).reshape(vec![2, 3, 4]); + let _b = a.index_axis_move(Axis(1), 0).reshape((4, 6)).reshape(vec![2, 3, 4]); } #[test] diff --git a/tests/iterators.rs b/tests/iterators.rs index ca1e56c4b..56940cb98 100644 --- a/tests/iterators.rs +++ b/tests/iterators.rs @@ -92,12 +92,12 @@ fn as_slice() { let a = a.reshape((2, 4)); assert_slice_correct(&a); - assert!(a.view().subview(Axis(1), 0).as_slice().is_none()); + assert!(a.view().index_axis(Axis(1), 0).as_slice().is_none()); let v = a.view(); assert_slice_correct(&v); - assert_slice_correct(&v.subview(Axis(0), 0)); - assert_slice_correct(&v.subview(Axis(0), 1)); + assert_slice_correct(&v.index_axis(Axis(0), 0)); + assert_slice_correct(&v.index_axis(Axis(0), 1)); assert!(v.slice(s![.., ..1]).as_slice().is_none()); println!("{:?}", v.slice(s![..1;2, ..])); @@ -180,12 +180,12 @@ fn outer_iter() { // [8, 9], // ... assert_equal(a.outer_iter(), - vec![a.subview(Axis(0), 0), a.subview(Axis(0), 1)]); + vec![a.index_axis(Axis(0), 0), a.index_axis(Axis(0), 1)]); let mut b = RcArray::zeros((2, 3, 2)); b.swap_axes(0, 2); b.assign(&a); assert_equal(b.outer_iter(), - vec![a.subview(Axis(0), 0), a.subview(Axis(0), 1)]); + vec![a.index_axis(Axis(0), 0), a.index_axis(Axis(0), 1)]); let mut found_rows = Vec::new(); for sub in b.outer_iter() { @@ -210,7 +210,7 @@ fn outer_iter() { cv.assign(&a); assert_eq!(&a, &cv); assert_equal(cv.outer_iter(), - vec![a.subview(Axis(0), 0), a.subview(Axis(0), 1)]); + vec![a.index_axis(Axis(0), 0), a.index_axis(Axis(0), 1)]); let mut found_rows = Vec::new(); for sub in cv.outer_iter() { @@ -233,9 +233,9 @@ fn axis_iter() { // [8, 9], // ... assert_equal(a.axis_iter(Axis(1)), - vec![a.subview(Axis(1), 0), - a.subview(Axis(1), 1), - a.subview(Axis(1), 2)]); + vec![a.index_axis(Axis(1), 0), + a.index_axis(Axis(1), 1), + a.index_axis(Axis(1), 2)]); } #[test] @@ -264,7 +264,7 @@ fn outer_iter_mut() { b.swap_axes(0, 2); b.assign(&a); assert_equal(b.outer_iter_mut(), - vec![a.subview(Axis(0), 0), a.subview(Axis(0), 1)]); + vec![a.index_axis(Axis(0), 0), a.index_axis(Axis(0), 1)]); let mut found_rows = Vec::new(); for sub in b.outer_iter_mut() {