Skip to content

Commit

Permalink
Switch from Dimension::SliceArg to CanSlice trait
Browse files Browse the repository at this point in the history
  • Loading branch information
jturner314 committed Dec 10, 2018
1 parent d45eeb9 commit 716600e
Show file tree
Hide file tree
Showing 7 changed files with 252 additions and 141 deletions.
23 changes: 1 addition & 22 deletions src/dimension/dimension_trait.rs
Expand Up @@ -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};
Expand Down Expand Up @@ -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<usize>;
/// `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<SliceArg, Do>` is using the
/// [`s![]`](macro.s!.html) macro.
type SliceArg: ?Sized + AsRef<[AxisSliceInfo]>;
/// Pattern matching friendly form of the dimension value.
///
/// - For `Ix1`: `usize`,
Expand Down Expand Up @@ -364,7 +349,6 @@ macro_rules! impl_insert_axis_array(

impl Dimension for Dim<[Ix; 0]> {
const NDIM: Option<usize> = Some(0);
type SliceArg = [AxisSliceInfo; 0];
type Pattern = ();
type Smaller = Self;
type Larger = Ix1;
Expand Down Expand Up @@ -401,7 +385,6 @@ impl Dimension for Dim<[Ix; 0]> {

impl Dimension for Dim<[Ix; 1]> {
const NDIM: Option<usize> = Some(1);
type SliceArg = [AxisSliceInfo; 1];
type Pattern = Ix;
type Smaller = Ix0;
type Larger = Ix2;
Expand Down Expand Up @@ -499,7 +482,6 @@ impl Dimension for Dim<[Ix; 1]> {

impl Dimension for Dim<[Ix; 2]> {
const NDIM: Option<usize> = Some(2);
type SliceArg = [AxisSliceInfo; 2];
type Pattern = (Ix, Ix);
type Smaller = Ix1;
type Larger = Ix3;
Expand Down Expand Up @@ -645,7 +627,6 @@ impl Dimension for Dim<[Ix; 2]> {

impl Dimension for Dim<[Ix; 3]> {
const NDIM: Option<usize> = Some(3);
type SliceArg = [AxisSliceInfo; 3];
type Pattern = (Ix, Ix, Ix);
type Smaller = Ix2;
type Larger = Ix4;
Expand Down Expand Up @@ -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<usize> = Some($n);
type SliceArg = [AxisSliceInfo; $n];
type Pattern = $pattern;
type Smaller = Dim<[Ix; $n - 1]>;
type Larger = $larger;
Expand Down Expand Up @@ -815,7 +795,6 @@ large_dim!(6, Ix6, (Ix, Ix, Ix, Ix, Ix, Ix), IxDyn, {
impl Dimension for IxDyn
{
const NDIM: Option<usize> = None;
type SliceArg = [AxisSliceInfo];
type Pattern = Self;
type Smaller = Self;
type Larger = Self;
Expand Down
7 changes: 4 additions & 3 deletions src/dimension/mod.rs
Expand Up @@ -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;

Expand Down Expand Up @@ -529,10 +530,10 @@ fn slice_min_max(axis_len: usize, slice: Slice) -> Option<(usize, usize)> {
#[doc(hidden)]
pub fn slices_intersect<D: Dimension>(
dim: &D,
indices1: &D::SliceArg,
indices2: &D::SliceArg,
indices1: &impl CanSlice<D>,
indices2: &impl CanSlice<D>,
) -> 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) {
Expand Down
83 changes: 46 additions & 37 deletions src/impl_methods.rs
Expand Up @@ -25,7 +25,6 @@ use {
AxisSliceInfo,
NdIndex,
Slice,
SliceInfo,
};
use iter::{
AxisChunksIter,
Expand All @@ -42,6 +41,7 @@ use iter::{
ExactChunksMut,
Windows
};
use slice::CanSlice;
use stacking::stack;

/// # Methods For All Array Types
Expand Down Expand Up @@ -303,9 +303,9 @@ where
///
/// **Panics** if an index is out of bounds or step size is zero.<br>
/// (**Panics** if `D` is `IxDyn` and `info` does not match the number of array axes.)
pub fn slice<Do>(&self, info: &SliceInfo<D::SliceArg, Do>) -> ArrayView<A, Do>
pub fn slice<I>(&self, info: &I) -> ArrayView<A, I::OutDim>
where
Do: Dimension,
I: CanSlice<D>,
S: Data,
{
self.view().slice_move(info)
Expand All @@ -321,9 +321,9 @@ where
///
/// **Panics** if an index is out of bounds or step size is zero.<br>
/// (**Panics** if `D` is `IxDyn` and `info` does not match the number of array axes.)
pub fn slice_mut<Do>(&mut self, info: &SliceInfo<D::SliceArg, Do>) -> ArrayViewMut<A, Do>
pub fn slice_mut<I>(&mut self, info: &I) -> ArrayViewMut<A, I::OutDim>
where
Do: Dimension,
I: CanSlice<D>,
S: DataMut,
{
self.view_mut().slice_move(info)
Expand All @@ -339,29 +339,37 @@ where
///
/// **Panics** if an index is out of bounds or step size is zero.<br>
/// (**Panics** if `D` is `IxDyn` and `info` does not match the number of array axes.)
pub fn slice_move<Do>(mut self, info: &SliceInfo<D::SliceArg, Do>) -> ArrayBase<S, Do>
pub fn slice_move<I>(mut self, info: &I) -> ArrayBase<S, I::OutDim>
where
Do: Dimension,
I: CanSlice<D>,
{
// 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,
Expand All @@ -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.<br>
/// (**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<I>(&mut self, info: &I)
where
I: CanSlice<D>,
{
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 })
}
Expand All @@ -407,7 +413,10 @@ where
/// **Panics** if an index is out of bounds or step size is zero.<br>
/// (**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<I>(&mut self, indices: &I)
where
I: CanSlice<D>,
{
self.slice_collapse(indices)
}

Expand Down
2 changes: 1 addition & 1 deletion src/lib.rs
Expand Up @@ -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;
Expand Down

0 comments on commit 716600e

Please sign in to comment.