From 716600e141e4b42ce5e480b02110ac2971281b8d Mon Sep 17 00:00:00 2001 From: Jim Turner Date: Sun, 9 Dec 2018 16:39:00 -0500 Subject: [PATCH] Switch from Dimension::SliceArg to CanSlice trait --- src/dimension/dimension_trait.rs | 23 +-- src/dimension/mod.rs | 7 +- src/impl_methods.rs | 83 ++++++----- src/lib.rs | 2 +- src/slice.rs | 248 +++++++++++++++++++++++-------- tests/array.rs | 28 ++-- tests/oper.rs | 2 +- 7 files changed, 252 insertions(+), 141 deletions(-) diff --git a/src/dimension/dimension_trait.rs b/src/dimension/dimension_trait.rs index b8d0fa7c2..d22356e3f 100644 --- a/src/dimension/dimension_trait.rs +++ b/src/dimension/dimension_trait.rs @@ -13,7 +13,7 @@ use std::ops::{Add, Sub, Mul, AddAssign, SubAssign, MulAssign}; use itertools::{enumerate, izip, zip}; -use {Ix, Ixs, Ix0, Ix1, Ix2, Ix3, Ix4, Ix5, Ix6, IxDyn, Dim, AxisSliceInfo, IxDynImpl}; +use {Ix, Ixs, Ix0, Ix1, Ix2, Ix3, Ix4, Ix5, Ix6, IxDyn, Dim, IxDynImpl}; use IntoDimension; use RemoveAxis; use {ArrayView1, ArrayViewMut1}; @@ -45,21 +45,6 @@ pub trait Dimension : Clone + Eq + Debug + Send + Sync + Default + /// `Some(ndim)`, and for variable-size dimension representations (e.g. /// `IxDyn`), this should be `None`. const NDIM: Option; - /// `SliceArg` is the type which is used to specify slicing for this - /// dimension. - /// - /// For the fixed size dimensions it is a fixed size array of the correct - /// size, which you pass by reference. For the dynamic dimension it is - /// a slice. - /// - /// - For `Ix1`: `[AxisSliceInfo; 1]` - /// - For `Ix2`: `[AxisSliceInfo; 2]` - /// - and so on.. - /// - For `IxDyn`: `[AxisSliceInfo]` - /// - /// The easiest way to create a `&SliceInfo` is using the - /// [`s![]`](macro.s!.html) macro. - type SliceArg: ?Sized + AsRef<[AxisSliceInfo]>; /// Pattern matching friendly form of the dimension value. /// /// - For `Ix1`: `usize`, @@ -364,7 +349,6 @@ macro_rules! impl_insert_axis_array( impl Dimension for Dim<[Ix; 0]> { const NDIM: Option = Some(0); - type SliceArg = [AxisSliceInfo; 0]; type Pattern = (); type Smaller = Self; type Larger = Ix1; @@ -401,7 +385,6 @@ impl Dimension for Dim<[Ix; 0]> { impl Dimension for Dim<[Ix; 1]> { const NDIM: Option = Some(1); - type SliceArg = [AxisSliceInfo; 1]; type Pattern = Ix; type Smaller = Ix0; type Larger = Ix2; @@ -499,7 +482,6 @@ impl Dimension for Dim<[Ix; 1]> { impl Dimension for Dim<[Ix; 2]> { const NDIM: Option = Some(2); - type SliceArg = [AxisSliceInfo; 2]; type Pattern = (Ix, Ix); type Smaller = Ix1; type Larger = Ix3; @@ -645,7 +627,6 @@ impl Dimension for Dim<[Ix; 2]> { impl Dimension for Dim<[Ix; 3]> { const NDIM: Option = Some(3); - type SliceArg = [AxisSliceInfo; 3]; type Pattern = (Ix, Ix, Ix); type Smaller = Ix2; type Larger = Ix4; @@ -763,7 +744,6 @@ macro_rules! large_dim { ($n:expr, $name:ident, $pattern:ty, $larger:ty, { $($insert_axis:tt)* }) => ( impl Dimension for Dim<[Ix; $n]> { const NDIM: Option = Some($n); - type SliceArg = [AxisSliceInfo; $n]; type Pattern = $pattern; type Smaller = Dim<[Ix; $n - 1]>; type Larger = $larger; @@ -815,7 +795,6 @@ large_dim!(6, Ix6, (Ix, Ix, Ix, Ix, Ix, Ix), IxDyn, { impl Dimension for IxDyn { const NDIM: Option = None; - type SliceArg = [AxisSliceInfo]; type Pattern = Self; type Smaller = Self; type Larger = Self; diff --git a/src/dimension/mod.rs b/src/dimension/mod.rs index 6be333eb0..12f643f2b 100644 --- a/src/dimension/mod.rs +++ b/src/dimension/mod.rs @@ -8,6 +8,7 @@ use {AxisSliceInfo, Ix, Ixs, Slice}; use error::{from_kind, ErrorKind, ShapeError}; +use slice::CanSlice; use itertools::izip; use num_integer::div_floor; @@ -529,10 +530,10 @@ fn slice_min_max(axis_len: usize, slice: Slice) -> Option<(usize, usize)> { #[doc(hidden)] pub fn slices_intersect( dim: &D, - indices1: &D::SliceArg, - indices2: &D::SliceArg, + indices1: &impl CanSlice, + indices2: &impl CanSlice, ) -> bool { - debug_assert_eq!(indices1.as_ref().len(), indices2.as_ref().len()); + debug_assert_eq!(indices1.in_ndim(), indices2.in_ndim()); for (&axis_len, &si1, &si2) in izip!(dim.slice(), indices1.as_ref(), indices2.as_ref()) { // The slices do not intersect iff any pair of `AxisSliceInfo` does not intersect. match (si1, si2) { diff --git a/src/impl_methods.rs b/src/impl_methods.rs index 87b597d7f..8d0a7a5df 100644 --- a/src/impl_methods.rs +++ b/src/impl_methods.rs @@ -25,7 +25,6 @@ use { AxisSliceInfo, NdIndex, Slice, - SliceInfo, }; use iter::{ AxisChunksIter, @@ -42,6 +41,7 @@ use iter::{ ExactChunksMut, Windows }; +use slice::CanSlice; use stacking::stack; /// # Methods For All Array Types @@ -303,9 +303,9 @@ where /// /// **Panics** if an index is out of bounds or step size is zero.
/// (**Panics** if `D` is `IxDyn` and `info` does not match the number of array axes.) - pub fn slice(&self, info: &SliceInfo) -> ArrayView + pub fn slice(&self, info: &I) -> ArrayView where - Do: Dimension, + I: CanSlice, S: Data, { self.view().slice_move(info) @@ -321,9 +321,9 @@ where /// /// **Panics** if an index is out of bounds or step size is zero.
/// (**Panics** if `D` is `IxDyn` and `info` does not match the number of array axes.) - pub fn slice_mut(&mut self, info: &SliceInfo) -> ArrayViewMut + pub fn slice_mut(&mut self, info: &I) -> ArrayViewMut where - Do: Dimension, + I: CanSlice, S: DataMut, { self.view_mut().slice_move(info) @@ -339,29 +339,37 @@ where /// /// **Panics** if an index is out of bounds or step size is zero.
/// (**Panics** if `D` is `IxDyn` and `info` does not match the number of array axes.) - pub fn slice_move(mut self, info: &SliceInfo) -> ArrayBase + pub fn slice_move(mut self, info: &I) -> ArrayBase where - Do: Dimension, + I: CanSlice, { // Slice and collapse in-place without changing the number of dimensions. - self.slice_collapse(&*info); + self.slice_collapse(info); - let indices: &[AxisSliceInfo] = (**info).as_ref(); - - // Copy the dim and strides that remain after removing the subview axes. let out_ndim = info.out_ndim(); - let mut new_dim = Do::zeros(out_ndim); - let mut new_strides = Do::zeros(out_ndim); - izip!(self.dim.slice(), self.strides.slice(), indices) - .filter_map(|(d, s, slice_or_index)| match slice_or_index { - &AxisSliceInfo::Slice {..} => Some((d, s)), - &AxisSliceInfo::Index(_) => None, - }) - .zip(izip!(new_dim.slice_mut(), new_strides.slice_mut())) - .for_each(|((d, s), (new_d, new_s))| { - *new_d = *d; - *new_s = *s; + let mut new_dim = I::OutDim::zeros(out_ndim); + let mut new_strides = I::OutDim::zeros(out_ndim); + + // Write the dim and strides to the correct new axes. + { + let mut old_axis = 0; + let mut new_axis = 0; + info.as_ref().iter().for_each(|ax_info| match ax_info { + &AxisSliceInfo::Slice { .. } => { + // Copy the old dim and stride to corresponding axis. + new_dim[new_axis] = self.dim[old_axis]; + new_strides[new_axis] = self.strides[old_axis]; + old_axis += 1; + new_axis += 1; + } + &AxisSliceInfo::Index(_) => { + // Skip the old axis since it should be removed. + old_axis += 1; + } }); + debug_assert_eq!(old_axis, self.ndim()); + debug_assert_eq!(new_axis, out_ndim); + } ArrayBase { ptr: self.ptr, @@ -373,25 +381,23 @@ where /// Slice the array in place without changing the number of dimensions. /// - /// Note that [`&SliceInfo`](struct.SliceInfo.html) (produced by the - /// [`s![]`](macro.s!.html) macro) will usually coerce into `&D::SliceArg` - /// automatically, but in some cases (e.g. if `D` is `IxDyn`), you may need - /// to call `.as_ref()`. - /// /// See [*Slicing*](#slicing) for full documentation. - /// See also [`D::SliceArg`]. - /// - /// [`D::SliceArg`]: trait.Dimension.html#associatedtype.SliceArg /// /// **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_collapse(&mut self, indices: &D::SliceArg) { - let indices: &[AxisSliceInfo] = indices.as_ref(); - assert_eq!(indices.len(), self.ndim()); - indices + /// (**Panics** if `D` is `IxDyn` and `info` does not match the number of array axes.) + pub fn slice_collapse(&mut self, info: &I) + where + I: CanSlice, + { + assert_eq!( + info.in_ndim(), + self.ndim(), + "The input dimension of `info` must match the array to be sliced.", + ); + info.as_ref() .iter() .enumerate() - .for_each(|(axis, slice_or_index)| match slice_or_index { + .for_each(|(axis, ax_info)| match ax_info { &AxisSliceInfo::Slice { start, end, step } => { self.slice_axis_inplace(Axis(axis), Slice { start, end, step }) } @@ -407,7 +413,10 @@ where /// **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) { + pub fn slice_inplace(&mut self, indices: &I) + where + I: CanSlice, + { self.slice_collapse(indices) } diff --git a/src/lib.rs b/src/lib.rs index 035b0139a..31912e8be 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, SliceNextDim, + life_of_view_mut, AxisSliceInfo, Slice, SliceInfo, SliceNextInDim, SliceNextOutDim, }; use iterators::Baseiter; diff --git a/src/slice.rs b/src/slice.rs index f8b6ddc8b..dde1bffa0 100644 --- a/src/slice.rs +++ b/src/slice.rs @@ -9,7 +9,7 @@ use error::{ShapeError, ErrorKind}; use std::ops::{Deref, Range, RangeFrom, RangeFull, RangeInclusive, RangeTo, RangeToInclusive}; use std::fmt; use std::marker::PhantomData; -use crate::{ArrayView, ArrayViewMut, Dimension, RawArrayViewMut}; +use crate::{ArrayView, ArrayViewMut, Dimension, Ix0, Ix1, Ix2, Ix3, Ix4, Ix5, Ix6, IxDyn, RawArrayViewMut}; /// A slice (range with step size). /// @@ -70,7 +70,7 @@ impl Slice { /// A slice (range with step) or an index. /// /// See also the [`s![]`](macro.s!.html) macro for a convenient way to create a -/// `&SliceInfo<[AxisSliceInfo; n], D>`. +/// `&SliceInfo<[AxisSliceInfo; n], Di, Do>`. /// /// ## Examples /// @@ -282,23 +282,85 @@ impl_sliceorindex_from_index!(isize); impl_sliceorindex_from_index!(usize); impl_sliceorindex_from_index!(i32); +/// A type that can slice an array of dimension `D`. +/// +/// This trait is unsafe to implement because the implementation must ensure +/// that `D`, `Self::OutDim`, `self.in_dim()`, and `self.out_ndim()` are +/// consistent with the `&[AxisSliceInfo]` returned by `self.as_ref()`. +pub unsafe trait CanSlice: AsRef<[AxisSliceInfo]> { + type OutDim: Dimension; + + fn in_ndim(&self) -> usize; + + fn out_ndim(&self) -> usize; +} + +macro_rules! impl_canslice_samedim { + ($in_dim:ty) => { + unsafe impl CanSlice<$in_dim> for SliceInfo + where + T: AsRef<[AxisSliceInfo]>, + Do: Dimension, + { + type OutDim = Do; + + fn in_ndim(&self) -> usize { + self.in_ndim() + } + + fn out_ndim(&self) -> usize { + self.out_ndim() + } + } + }; +} +impl_canslice_samedim!(Ix0); +impl_canslice_samedim!(Ix1); +impl_canslice_samedim!(Ix2); +impl_canslice_samedim!(Ix3); +impl_canslice_samedim!(Ix4); +impl_canslice_samedim!(Ix5); +impl_canslice_samedim!(Ix6); + +unsafe impl CanSlice for SliceInfo +where + T: AsRef<[AxisSliceInfo]>, + Di: Dimension, + Do: Dimension, +{ + type OutDim = Do; + + fn in_ndim(&self) -> usize { + self.in_ndim() + } + + fn out_ndim(&self) -> usize { + self.out_ndim() + } +} + /// Represents all of the necessary information to perform a slice. /// /// The type `T` is typically `[AxisSliceInfo; n]`, `[AxisSliceInfo]`, or -/// `Vec`. The type `D` is the output dimension after calling -/// [`.slice()`]. +/// `Vec`. The type `Di` is the dimension of the array to be +/// sliced, and `Do` is the output dimension after calling [`.slice()`]. Note +/// that if `Di` is a fixed dimension type (`Ix0`, `Ix1`, `Ix2`, etc.), the +/// `SliceInfo` instance can still be used to slice an array with dimension +/// `IxDyn` as long as the number of axes matches. /// /// [`.slice()`]: struct.ArrayBase.html#method.slice #[derive(Debug)] #[repr(C)] -pub struct SliceInfo { - out_dim: PhantomData, +pub struct SliceInfo { + in_dim: PhantomData, + out_dim: PhantomData, indices: T, } -impl Deref for SliceInfo +impl Deref for SliceInfo where - D: Dimension, + Di: Dimension, + Do: Dimension, { type Target = T; fn deref(&self) -> &Self::Target { @@ -306,58 +368,78 @@ where } } -impl SliceInfo +impl SliceInfo where - D: Dimension, + Di: Dimension, + Do: Dimension, { /// Returns a new `SliceInfo` instance. /// - /// If you call this method, you are guaranteeing that `out_dim` is - /// consistent with `indices`. + /// If you call this method, you are guaranteeing that `in_dim` and + /// `out_dim` are consistent with `indices`. #[doc(hidden)] - pub unsafe fn new_unchecked(indices: T, out_dim: PhantomData) -> SliceInfo { + pub unsafe fn new_unchecked( + indices: T, + in_dim: PhantomData, + out_dim: PhantomData, + ) -> SliceInfo { SliceInfo { + in_dim: in_dim, out_dim: out_dim, indices: indices, } } } -impl SliceInfo +impl SliceInfo where T: AsRef<[AxisSliceInfo]>, - D: Dimension, + Di: Dimension, + Do: Dimension, { /// Returns a new `SliceInfo` instance. /// - /// Errors if `D` is not consistent with `indices`. - pub fn new(indices: T) -> Result, ShapeError> { - if let Some(ndim) = D::NDIM { + /// 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() { + 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() { return Err(ShapeError::from_kind(ErrorKind::IncompatibleShape)); } } Ok(SliceInfo { + in_dim: PhantomData, out_dim: PhantomData, indices: indices, }) } } -impl SliceInfo +impl SliceInfo where T: AsRef<[AxisSliceInfo]>, - D: Dimension, + Di: Dimension, + Do: Dimension, { + /// Returns the number of dimensions of the input array for + /// [`.slice()`](struct.ArrayBase.html#method.slice). + pub fn in_ndim(&self) -> usize { + Di::NDIM.unwrap_or_else(|| self.indices.as_ref().len()) + } + /// Returns the number of dimensions after calling /// [`.slice()`](struct.ArrayBase.html#method.slice) (including taking /// subviews). /// - /// If `D` is a fixed-size dimension type, then this is equivalent to - /// `D::NDIM.unwrap()`. Otherwise, the value is calculated by iterating - /// over the ranges/indices. + /// If `Do` is a fixed-size dimension type, then this is equivalent to + /// `Do::NDIM.unwrap()`. Otherwise, the value is calculated by iterating + /// over the `AxisSliceInfo` elements. pub fn out_ndim(&self) -> usize { - D::NDIM.unwrap_or_else(|| { + Do::NDIM.unwrap_or_else(|| { self.indices .as_ref() .iter() @@ -367,88 +449,117 @@ where } } -impl AsRef<[AxisSliceInfo]> for SliceInfo +impl AsRef<[AxisSliceInfo]> for SliceInfo where T: AsRef<[AxisSliceInfo]>, - D: Dimension, + Di: Dimension, + Do: Dimension, { fn as_ref(&self) -> &[AxisSliceInfo] { self.indices.as_ref() } } -impl AsRef> for SliceInfo +impl AsRef> for SliceInfo where T: AsRef<[AxisSliceInfo]>, - D: Dimension, + Di: Dimension, + Do: Dimension, { - fn as_ref(&self) -> &SliceInfo<[AxisSliceInfo], D> { + fn as_ref(&self) -> &SliceInfo<[AxisSliceInfo], Di, Do> { unsafe { // This is okay because the only non-zero-sized member of - // `SliceInfo` is `indices`, so `&SliceInfo<[AxisSliceInfo], D>` + // `SliceInfo` is `indices`, so `&SliceInfo<[AxisSliceInfo], Di, Do>` // should have the same bitwise representation as // `&[AxisSliceInfo]`. &*(self.indices.as_ref() as *const [AxisSliceInfo] - as *const SliceInfo<[AxisSliceInfo], D>) + as *const SliceInfo<[AxisSliceInfo], Di, Do>) } } } -impl Copy for SliceInfo +impl Copy for SliceInfo where T: Copy, - D: Dimension, + Di: Dimension, + Do: Dimension, { } -impl Clone for SliceInfo +impl Clone for SliceInfo where T: Clone, - D: Dimension, + Di: Dimension, + Do: Dimension, { fn clone(&self) -> Self { SliceInfo { + in_dim: PhantomData, out_dim: PhantomData, indices: self.indices.clone(), } } } +#[doc(hidden)] +pub trait SliceNextInDim { + fn next_dim(&self, PhantomData) -> PhantomData; +} + +macro_rules! impl_slicenextindim_larger { + (($($generics:tt)*), $self:ty) => { + impl SliceNextInDim for $self { + fn next_dim(&self, _: PhantomData) -> PhantomData { + PhantomData + } + } + } +} +impl_slicenextindim_larger!((), isize); +impl_slicenextindim_larger!((), usize); +impl_slicenextindim_larger!((), i32); +impl_slicenextindim_larger!((T), Range); +impl_slicenextindim_larger!((T), RangeInclusive); +impl_slicenextindim_larger!((T), RangeFrom); +impl_slicenextindim_larger!((T), RangeTo); +impl_slicenextindim_larger!((T), RangeToInclusive); +impl_slicenextindim_larger!((), RangeFull); +impl_slicenextindim_larger!((), Slice); #[doc(hidden)] -pub trait SliceNextDim { +pub trait SliceNextOutDim { fn next_dim(&self, PhantomData) -> PhantomData; } -macro_rules! impl_slicenextdim_equal { +macro_rules! impl_slicenextoutdim_equal { ($self:ty) => { - impl SliceNextDim for $self { + impl SliceNextOutDim for $self { fn next_dim(&self, _: PhantomData) -> PhantomData { PhantomData } } } } -impl_slicenextdim_equal!(isize); -impl_slicenextdim_equal!(usize); -impl_slicenextdim_equal!(i32); +impl_slicenextoutdim_equal!(isize); +impl_slicenextoutdim_equal!(usize); +impl_slicenextoutdim_equal!(i32); -macro_rules! impl_slicenextdim_larger { +macro_rules! impl_slicenextoutdim_larger { (($($generics:tt)*), $self:ty) => { - impl SliceNextDim for $self { + impl SliceNextOutDim for $self { fn next_dim(&self, _: PhantomData) -> PhantomData { PhantomData } } } } -impl_slicenextdim_larger!((T), Range); -impl_slicenextdim_larger!((T), RangeInclusive); -impl_slicenextdim_larger!((T), RangeFrom); -impl_slicenextdim_larger!((T), RangeTo); -impl_slicenextdim_larger!((T), RangeToInclusive); -impl_slicenextdim_larger!((), RangeFull); -impl_slicenextdim_larger!((), Slice); +impl_slicenextoutdim_larger!((T), Range); +impl_slicenextoutdim_larger!((T), RangeInclusive); +impl_slicenextoutdim_larger!((T), RangeFrom); +impl_slicenextoutdim_larger!((T), RangeTo); +impl_slicenextoutdim_larger!((T), RangeToInclusive); +impl_slicenextoutdim_larger!((), RangeFull); +impl_slicenextoutdim_larger!((), Slice); /// Slice argument constructor. /// @@ -548,14 +659,16 @@ impl_slicenextdim_larger!((), Slice); #[macro_export] macro_rules! s( // convert a..b;c into @convert(a..b, c), final item - (@parse $dim:expr, [$($stack:tt)*] $r:expr;$s:expr) => { + (@parse $in_dim:expr, $out_dim:expr, [$($stack:tt)*] $r:expr;$s:expr) => { match $r { r => { - let out_dim = $crate::SliceNextDim::next_dim(&r, $dim); + let in_dim = $crate::SliceNextInDim::next_dim(&r, $in_dim); + let out_dim = $crate::SliceNextOutDim::next_dim(&r, $out_dim); #[allow(unsafe_code)] unsafe { $crate::SliceInfo::new_unchecked( [$($stack)* $crate::s!(@convert r, $s)], + in_dim, out_dim, ) } @@ -563,14 +676,16 @@ macro_rules! s( } }; // convert a..b into @convert(a..b), final item - (@parse $dim:expr, [$($stack:tt)*] $r:expr) => { + (@parse $in_dim:expr, $out_dim:expr, [$($stack:tt)*] $r:expr) => { match $r { r => { - let out_dim = $crate::SliceNextDim::next_dim(&r, $dim); + let in_dim = $crate::SliceNextInDim::next_dim(&r, $in_dim); + let out_dim = $crate::SliceNextOutDim::next_dim(&r, $out_dim); #[allow(unsafe_code)] unsafe { $crate::SliceInfo::new_unchecked( [$($stack)* $crate::s!(@convert r)], + in_dim, out_dim, ) } @@ -578,19 +693,20 @@ macro_rules! s( } }; // convert a..b;c into @convert(a..b, c), final item, trailing comma - (@parse $dim:expr, [$($stack:tt)*] $r:expr;$s:expr ,) => { - $crate::s![@parse $dim, [$($stack)*] $r;$s] + (@parse $in_dim:expr, $out_dim:expr, [$($stack:tt)*] $r:expr;$s:expr ,) => { + $crate::s![@parse $in_dim, $out_dim, [$($stack)*] $r;$s] }; // convert a..b into @convert(a..b), final item, trailing comma - (@parse $dim:expr, [$($stack:tt)*] $r:expr ,) => { - $crate::s![@parse $dim, [$($stack)*] $r] + (@parse $in_dim:expr, $out_dim:expr, [$($stack:tt)*] $r:expr ,) => { + $crate::s![@parse $in_dim, $out_dim, [$($stack)*] $r] }; // convert a..b;c into @convert(a..b, c) - (@parse $dim:expr, [$($stack:tt)*] $r:expr;$s:expr, $($t:tt)*) => { + (@parse $in_dim:expr, $out_dim:expr, [$($stack:tt)*] $r:expr;$s:expr, $($t:tt)*) => { match $r { r => { $crate::s![@parse - $crate::SliceNextDim::next_dim(&r, $dim), + $crate::SliceNextInDim::next_dim(&r, $in_dim), + $crate::SliceNextOutDim::next_dim(&r, $out_dim), [$($stack)* $crate::s!(@convert r, $s),] $($t)* ] @@ -598,11 +714,12 @@ macro_rules! s( } }; // convert a..b into @convert(a..b) - (@parse $dim:expr, [$($stack:tt)*] $r:expr, $($t:tt)*) => { + (@parse $in_dim:expr, $out_dim:expr, [$($stack:tt)*] $r:expr, $($t:tt)*) => { match $r { r => { $crate::s![@parse - $crate::SliceNextDim::next_dim(&r, $dim), + $crate::SliceNextInDim::next_dim(&r, $in_dim), + $crate::SliceNextOutDim::next_dim(&r, $out_dim), [$($stack)* $crate::s!(@convert r),] $($t)* ] @@ -620,7 +737,12 @@ macro_rules! s( ($($t:tt)*) => { // The extra `*&` is a workaround for this compiler bug: // https://github.com/rust-lang/rust/issues/23014 - &*&$crate::s![@parse ::std::marker::PhantomData::<$crate::Ix0>, [] $($t)*] + &*&$crate::s![@parse + ::std::marker::PhantomData::<$crate::Ix0>, + ::std::marker::PhantomData::<$crate::Ix0>, + [] + $($t)* + ] }; ); diff --git a/tests/array.rs b/tests/array.rs index 88ea79fa8..d47199bc8 100644 --- a/tests/array.rs +++ b/tests/array.rs @@ -197,13 +197,13 @@ fn test_slice_dyninput_array_fixed() { arr.slice(info); arr.slice_mut(info); arr.view().slice_move(info); - arr.view().slice_collapse(info.as_ref()); + arr.view().slice_collapse(info); } #[test] fn test_slice_array_dyn() { let mut arr = Array3::::zeros((5, 2, 5)); - let info = &SliceInfo::<_, IxDyn>::new([ + let info = &SliceInfo::<_, Ix3, IxDyn>::new([ AxisSliceInfo::from(1..), AxisSliceInfo::from(1), AxisSliceInfo::from(..).step_by(2), @@ -217,7 +217,7 @@ fn test_slice_array_dyn() { #[test] fn test_slice_dyninput_array_dyn() { let mut arr = Array3::::zeros((5, 2, 5)).into_dyn(); - let info = &SliceInfo::<_, IxDyn>::new([ + let info = &SliceInfo::<_, Ix3, IxDyn>::new([ AxisSliceInfo::from(1..), AxisSliceInfo::from(1), AxisSliceInfo::from(..).step_by(2), @@ -225,35 +225,35 @@ fn test_slice_dyninput_array_dyn() { arr.slice(info); arr.slice_mut(info); arr.view().slice_move(info); - arr.view().slice_collapse(info.as_ref()); + arr.view().slice_collapse(info); } #[test] fn test_slice_dyninput_vec_fixed() { let mut arr = Array3::::zeros((5, 2, 5)).into_dyn(); - let info = &SliceInfo::<_, Ix2>::new(vec![ + let info = &SliceInfo::<_, Ix3, Ix2>::new(vec![ AxisSliceInfo::from(1..), AxisSliceInfo::from(1), AxisSliceInfo::from(..).step_by(2), ]).unwrap(); - arr.slice(info.as_ref()); - arr.slice_mut(info.as_ref()); - arr.view().slice_move(info.as_ref()); - arr.view().slice_collapse(info.as_ref()); + arr.slice(info); + arr.slice_mut(info); + arr.view().slice_move(info); + arr.view().slice_collapse(info); } #[test] fn test_slice_dyninput_vec_dyn() { let mut arr = Array3::::zeros((5, 2, 5)).into_dyn(); - let info = &SliceInfo::<_, IxDyn>::new(vec![ + let info = &SliceInfo::<_, Ix3, IxDyn>::new(vec![ AxisSliceInfo::from(1..), AxisSliceInfo::from(1), AxisSliceInfo::from(..).step_by(2), ]).unwrap(); - arr.slice(info.as_ref()); - arr.slice_mut(info.as_ref()); - arr.view().slice_move(info.as_ref()); - arr.view().slice_collapse(info.as_ref()); + arr.slice(info); + arr.slice_mut(info); + arr.view().slice_move(info); + arr.view().slice_collapse(info); } #[test] diff --git a/tests/oper.rs b/tests/oper.rs index db92bd3bd..1e5a3a570 100644 --- a/tests/oper.rs +++ b/tests/oper.rs @@ -610,7 +610,7 @@ fn scaled_add_3() { { let mut av = a.slice_mut(s![..;s1, ..;s2]); - let c = c.slice(SliceInfo::<_, IxDyn>::new(cslice).unwrap().as_ref()); + let c = c.slice(&SliceInfo::<_, IxDyn, IxDyn>::new(cslice).unwrap()); let mut answerv = answer.slice_mut(s![..;s1, ..;s2]); answerv += &(beta * &c);