8000 implement creating SliceArg from arbitrary Dimension by SparrowLii · Pull Request #909 · rust-ndarray/ndarray · GitHub
[go: up one dir, main page]

Skip to content

implement creating SliceArg from arbitrary Dimension #909

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 4 commits into from
Closed
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Transfer function into SliceInfo; Use Result as the return value
  • Loading branch information
SparrowLii committed Feb 5, 2021
commit 03c379165477b99b08b38f221d96c03c6519793d
96 changes: 47 additions & 49 deletions src/dimension/dimension_trait.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ use super::axes_of;
use super::conversion::Convert;
use super::{stride_offset, stride_offset_checked};
use crate::itertools::{enumerate, zip};
use crate::{Axis, SliceInfo};
use crate::{Axis, ShapeError, ErrorKind};
use crate::IntoDimension;
use crate::RemoveAxis;
use crate::{ArrayView1, ArrayViewMut1};
Expand Down Expand Up @@ -78,35 +78,6 @@ pub trait Dimension:
type Smaller: Dimension;
/// Next larger dimension
type Larger: Dimension + RemoveAxis;

/// Convert index to &Self::SliceArg. Make sure that length of index
/// consists with Self::NDIM(if it exists).
///
/// Panics if conversion failed.
#[doc(hidden)]
fn slice_arg_from(index: &[SliceOrIndex]) -> &Self::SliceArg ;

/// Convert &SliceInfo<AsRef<[SliceOrIndex]>, Do> to &SliceInfo<D::SliceArg, Do>.
/// Generate SliceArg of any dimension via this method.
///
/// Panics if conversion failed.
#[doc(hidden)]
fn slice_info_from<T, Do>(indices: &T) -> &SliceInfo<Self::SliceArg, Do>
where
T: AsRef<[SliceOrIndex]>,
Do: Dimension,
{
let arg_ref = Self::slice_arg_from(indices.as_ref());
unsafe {
// This is okay because the only non-zero-sized member of
// `SliceInfo` is `indices`, so `&SliceInfo<[SliceOrIndex], D>`
// should have the same bitwise representation as
// `&[SliceOrIndex]`.
&*(arg_ref as *const Self::SliceArg
as *const SliceInfo<Self::SliceArg, Do>)
}
}

/// Returns the number of dimensions (number of axes).
fn ndim(&self) -> usize;

Expand Down Expand Up @@ -404,6 +375,11 @@ pub trait Dimension:
#[doc(hidden)]
fn try_remove_axis(&self, axis: Axis) -> Self::Smaller;

/// Convert index to &Self::SliceArg. Return ShapeError if the length of index
/// doesn't consist with Self::NDIM(if it exists).
#[doc(hidden)]
fn slice_arg_from<T: AsRef<[SliceOrIndex]>>(index: &T) -> Result<&Self::SliceArg, ShapeError>;

private_decl! {}
}

Expand All @@ -427,10 +403,6 @@ impl Dimension for Dim<[Ix; 0]> {
type Pattern = ();
type Smaller = Self;
type Larger = Ix1;
#[inline]
fn slice_arg_from(index: &[SliceOrIndex]) -> &Self::SliceArg {
index.try_into().unwrap()
}
// empty product is 1 -> size is 1
#[inline]
fn ndim(&self) -> usize {
Expand Down Expand Up @@ -465,6 +437,13 @@ impl Dimension for Dim<[Ix; 0]> {
fn try_remove_axis(&self, _ignore: Axis) -> Self::Smaller {
*self
}
#[inline]
fn slice_arg_from<T: AsRef<[SliceOrIndex]>>(index: &T) -> Result<&Self::SliceArg, ShapeError> {
match index.as_ref().try_into() {
Ok(arg) => Ok(arg),
Err(_) => Err(ShapeError::from_kind(ErrorKind::IncompatibleShape))
}
}

private_impl! {}
}
Expand All @@ -475,9 +454,6 @@ impl Dimension for Dim<[Ix; 1]> {
type Pattern = Ix;
type Smaller = Ix0;
type Larger = Ix2;
fn slice_arg_from(index: &[SliceOrIndex]) -> &Self::SliceArg {
index.try_into().unwrap()
}
#[inline]
fn ndim(&self) -> usize {
1
Expand Down Expand Up @@ -585,6 +561,15 @@ impl Dimension for Dim<[Ix; 1]> {
None
}
}

#[inline]
fn slice_arg_from<T: AsRef<[SliceOrIndex]>>(index: &T) -> Result<&Self::SliceArg, ShapeError> {
match index.as_ref().try_into() {
Ok(arg) => Ok(arg),
Err(_) => Err(ShapeError::from_kind(ErrorKind::IncompatibleShape))
}
}

private_impl! {}
}

Expand All @@ -594,9 +579,6 @@ impl Dimension for Dim<[Ix; 2]> {
type Pattern = (Ix, Ix);
type Smaller = Ix1;
type Larger = Ix3;
fn slice_arg_from(index: &[SliceOrIndex]) -> &Self::SliceArg {
index.try_into().unwrap()
}
#[inline]
fn ndim(&self) -> usize {
2
Expand Down Expand Up @@ -745,6 +727,13 @@ impl Dimension for Dim<[Ix; 2]> {
fn try_remove_axis(&self, axis: Axis) -> Self::Smaller {
self.remove_axis(axis)
}
#[inline]
fn slice_arg_from<T: AsRef<[SliceOrIndex]>>(index: &T) -> Result<&Self::SliceArg, ShapeError> {
match index.as_ref().try_into() {
Ok(arg) => Ok(arg),
Err(_) => Err(ShapeError::from_kind(ErrorKind::IncompatibleShape))
}
}
private_impl! {}
}

Expand All @@ -754,9 +743,6 @@ impl Dimension for Dim<[Ix; 3]> {
type Pattern = (Ix, Ix, Ix);
type Smaller = Ix2;
type Larger = Ix4;
fn slice_arg_from(index: &[SliceOrIndex]) -> &Self::SliceArg {
index.try_into().unwrap()
}
#[inline]
fn ndim(&self) -> usize {
3
Expand Down Expand Up @@ -869,6 +855,13 @@ impl Dimension for Dim<[Ix; 3]> {
fn try_remove_axis(&self, axis: Axis) -> Self::Smaller {
self.remove_axis(axis)
}
#[inline]
fn slice_arg_from<T: AsRef<[SliceOrIndex]>>(index: &T) -> Result<&Self::SliceArg, ShapeError> {
match index.as_ref().try_into() {
Ok(arg) => Ok(arg),
Err(_) => Err(ShapeError::from_kind(ErrorKind::IncompatibleShape))
}
}
private_impl! {}
}

Expand All @@ -880,9 +873,6 @@ macro_rules! large_dim {
type Pattern = $pattern;
type Smaller = Dim<[Ix; $n - 1]>;
type Larger = $larger;
fn slice_arg_from(index: &[SliceOrIndex]) -> &Self::SliceArg {
index.try_into().unwrap()
}
#[inline]
fn ndim(&self) -> usize { $n }
#[inline]
Expand All @@ -904,6 +894,13 @@ macro_rules! large_dim {
fn try_remove_axis(&self, axis: Axis) -> Self::Smaller {
self.remove_axis(axis)
}
#[inline]
fn slice_arg_from<T: AsRef<[SliceOrIndex]>>(index: &T) -> Result<&Self::SliceArg, ShapeError> {
match index.as_ref().try_into() {
Ok(arg) => Ok(arg),
Err(_) => Err(ShapeError::from_kind(ErrorKind::IncompatibleShape))
}
}
private_impl!{}
}
)
Expand Down Expand Up @@ -934,9 +931,6 @@ impl Dimension for IxDyn {
type Pattern = Self;
type Smaller = Self;
type Larger = Self;
fn slice_arg_from(index: &[SliceOrIndex]) -> &Self::SliceArg {
index
}
#[inline]
fn ndim(&self) -> usize {
self.ix().len()
Expand Down Expand Up @@ -977,6 +971,10 @@ impl Dimension for IxDyn {
fn from_dimension<D2: Dimension>(d: &D2) -> Option<Self> {
Some(IxDyn(d.slice()))
}
#[inline]
fn slice_arg_from<T: AsRef<[SliceOrIndex]>>(index: &T) -> Result<&Self::SliceArg, ShapeError> {
Ok(index.as_ref())
}
private_impl! {}
}

Expand Down
17 changes: 17 additions & 0 deletions src/slice.rs
Original file line number Diff line number Diff line change
Expand Up @@ -333,6 +333,23 @@ where
indices,
})
}

/// Generate the corresponding SliceInfo from AsRef<[SliceOrIndex]>
/// for the specific dimension E.
///
/// Return ShapeError if length does not match
pub fn for_dimensionality<E: Dimension>(indices: &T) -> Result<&SliceInfo<E::SliceArg, D>, ShapeError>
{
let arg_ref = E::slice_arg_from(indices)?;
unsafe {
// This is okay because the only non-zero-sized member of
// `SliceInfo` is `indices`, so `&SliceInfo<[SliceOrIndex], D>`
// should have the same bitwise representation as
// `&[SliceOrIndex]`.
Ok(&*(arg_ref as *const E::SliceArg
as *const SliceInfo<E::SliceArg, D>))
}
}
}

impl<T: ?Sized, D> SliceInfo<T, D>
Expand Down
8 changes: 4 additions & 4 deletions tests/array.rs
Original file line number Diff line number Diff line change
Expand Up @@ -285,14 +285,14 @@ fn test_slice_arg() {
let mut x = Array::from_elem(shape, 0);
let indices = x.shape().iter().map(f).collect::<Vec<_>>();
let s = x.slice_mut(
<Sh::Dim as Dimension>::slice_info_from::<_, Sh::Dim>(&indices)
SliceInfo::<_, Sh::Dim>::for_dimensionality::<Sh::Dim>(&indices).unwrap()
);
let s2 = shape2.slice();
assert_eq!(s.shape(), s2)
}
use_arg_map(0,|x| SliceOrIndex::from(*x/2..*x),Dim([0]));
use_arg_map((2, 4, 8),|x| SliceOrIndex::from(*x/2..*x),Dim([1, 2, 4]));
use_arg_map(vec![3, 6, 9],|x| SliceOrIndex::from(*x/3..*x/2),Dim([0, 1, 1]));
use_arg_map(0, |x| SliceOrIndex::from(*x/2..*x),Dim([0]));
use_arg_map((2, 4, 8), |x| SliceOrIndex::from(*x/2..*x),Dim([1, 2, 4]));
use_arg_map(vec![3, 6, 9], |x| SliceOrIndex::from(*x/3..*x/2),Dim([0, 1, 1]));
use_arg_map(vec![1, 2, 3, 4, 5, 6, 7], |x| SliceOrIndex::from(x-1), Dim([]));
}

Expand Down
0