Skip to content

Commit a380737

Browse files
authored
Merge pull request #377 from jturner314/slice-subview4
Add support for slicing with subviews
2 parents 50679f3 + 79659c9 commit a380737

File tree

12 files changed

+1078
-346
lines changed

12 files changed

+1078
-346
lines changed

.travis.yml

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,6 @@ sudo: required
44
dist: trusty
55
matrix:
66
include:
7-
- rust: 1.18.0
8-
env:
9-
- FEATURES='test'
107
- rust: stable
118
env:
129
- FEATURES='test'

examples/axis_ops.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ fn main() {
4747
}
4848
a.swap_axes(0, 1);
4949
a.swap_axes(0, 2);
50-
a.islice(s![.., ..;-1, ..]);
50+
a.slice_inplace(s![.., ..;-1, ..]);
5151
regularize(&mut a).ok();
5252

5353
let mut b = Array::<u8, _>::zeros((2, 3, 4));
@@ -64,6 +64,6 @@ fn main() {
6464
for (i, elt) in (0..).zip(&mut a) {
6565
*elt = i;
6666
}
67-
a.islice(s![..;-1, ..;2, ..]);
67+
a.slice_inplace(s![..;-1, ..;2, ..]);
6868
regularize(&mut a).ok();
6969
}

serialization-tests/tests/serialize.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ fn serial_many_dim()
5353
{
5454
// Test a sliced array.
5555
let mut a = RcArray::linspace(0., 31., 32).reshape((2, 2, 2, 4));
56-
a.islice(s![..;-1, .., .., ..2]);
56+
a.slice_inplace(s![..;-1, .., .., ..2]);
5757
let serial = json::encode(&a).unwrap();
5858
println!("Encode {:?} => {:?}", a, serial);
5959
let res = json::decode::<RcArray<f32, _>>(&serial);
@@ -114,7 +114,7 @@ fn serial_many_dim_serde()
114114
{
115115
// Test a sliced array.
116116
let mut a = RcArray::linspace(0., 31., 32).reshape((2, 2, 2, 4));
117-
a.islice(s![..;-1, .., .., ..2]);
117+
a.slice_inplace(s![..;-1, .., .., ..2]);
118118
let serial = serde_json::to_string(&a).unwrap();
119119
println!("Encode {:?} => {:?}", a, serial);
120120
let res = serde_json::from_str::<RcArray<f32, _>>(&serial);
@@ -221,7 +221,7 @@ fn serial_many_dim_serde_msgpack()
221221
{
222222
// Test a sliced array.
223223
let mut a = RcArray::linspace(0., 31., 32).reshape((2, 2, 2, 4));
224-
a.islice(s![..;-1, .., .., ..2]);
224+
a.slice_inplace(s![..;-1, .., .., ..2]);
225225

226226
let mut buf = Vec::new();
227227
serde::Serialize::serialize(&a, &mut rmp_serde::Serializer::new(&mut buf)).ok().unwrap();
@@ -273,7 +273,7 @@ fn serial_many_dim_ron()
273273
{
274274
// Test a sliced array.
275275
let mut a = RcArray::linspace(0., 31., 32).reshape((2, 2, 2, 4));
276-
a.islice(s![..;-1, .., .., ..2]);
276+
a.slice_inplace(s![..;-1, .., .., ..2]);
277277

278278
let a_s = ron_serialize(&a).unwrap();
279279

src/dimension/dimension_trait.rs

Lines changed: 63 additions & 88 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ use std::ops::{Add, Sub, Mul, AddAssign, SubAssign, MulAssign};
1313

1414
use itertools::{enumerate, zip};
1515

16-
use {Ix, Ixs, Ix0, Ix1, Ix2, Ix3, Ix4, Ix5, Ix6, IxDyn, Dim, Si, IxDynImpl};
16+
use {Ix, Ixs, Ix0, Ix1, Ix2, Ix3, Ix4, Ix5, Ix6, IxDyn, Dim, SliceOrIndex, IxDynImpl};
1717
use IntoDimension;
1818
use RemoveAxis;
1919
use {ArrayView1, ArrayViewMut1};
@@ -41,21 +41,25 @@ pub trait Dimension : Clone + Eq + Debug + Send + Sync + Default +
4141
MulAssign + for<'x> MulAssign<&'x Self> + MulAssign<usize>
4242

4343
{
44+
/// For fixed-size dimension representations (e.g. `Ix2`), this should be
45+
/// `Some(ndim)`, and for variable-size dimension representations (e.g.
46+
/// `IxDyn`), this should be `None`.
47+
const NDIM: Option<usize>;
4448
/// `SliceArg` is the type which is used to specify slicing for this
4549
/// dimension.
4650
///
4751
/// For the fixed size dimensions it is a fixed size array of the correct
4852
/// size, which you pass by reference. For the dynamic dimension it is
4953
/// a slice.
5054
///
51-
/// - For `Ix1`: `[Si; 1]`
52-
/// - For `Ix2`: `[Si; 2]`
55+
/// - For `Ix1`: `[SliceOrIndex; 1]`
56+
/// - For `Ix2`: `[SliceOrIndex; 2]`
5357
/// - and so on..
54-
/// - For `IxDyn`: `[Si]`
58+
/// - For `IxDyn`: `[SliceOrIndex]`
5559
///
56-
/// The easiest way to create a `&SliceArg` is using the macro
57-
/// [`s![]`](macro.s!.html).
58-
type SliceArg: ?Sized + AsRef<[Si]>;
60+
/// The easiest way to create a `&SliceInfo<SliceArg, Do>` is using the
61+
/// [`s![]`](macro.s!.html) macro.
62+
type SliceArg: ?Sized + AsRef<[SliceOrIndex]>;
5963
/// Pattern matching friendly form of the dimension value.
6064
///
6165
/// - For `Ix1`: `usize`,
@@ -152,6 +156,15 @@ pub trait Dimension : Clone + Eq + Debug + Send + Sync + Default +
152156
Self::default()
153157
}
154158

159+
#[doc(hidden)]
160+
/// Return an index of same type and with the specified dimensionality.
161+
///
162+
/// This method is useful for generalizing over fixed-size and
163+
/// variable-size dimension representations.
164+
///
165+
/// **Panics** if `Self` has a fixed size that is not `ndim`.
166+
fn zero_index_with_ndim(ndim: usize) -> Self;
167+
155168
#[doc(hidden)]
156169
#[inline]
157170
fn first_index(&self) -> Option<Self> {
@@ -239,69 +252,6 @@ pub trait Dimension : Clone + Eq + Debug + Send + Sync + Default +
239252
self.slice_mut()[nd - 1] = i;
240253
}
241254

242-
#[doc(hidden)]
243-
/// Modify dimension, strides and return data pointer offset
244-
///
245-
/// **Panics** if `slices` does not correspond to the number of axes,
246-
/// if any stride is 0, or if any index is out of bounds.
247-
fn do_slices(dim: &mut Self, strides: &mut Self, slices: &Self::SliceArg) -> isize {
248-
let slices = slices.as_ref();
249-
let mut offset = 0;
250-
ndassert!(slices.len() == dim.slice().len(),
251-
"SliceArg {:?}'s length does not match dimension {:?}",
252-
slices, dim);
253-
for (dr, sr, &slc) in izip!(dim.slice_mut(), strides.slice_mut(), slices) {
254-
let m = *dr;
255-
let mi = m as Ixs;
256-
let Si(b1, opt_e1, s1) = slc;
257-
let e1 = opt_e1.unwrap_or(mi);
258-
259-
let b1 = abs_index(mi, b1);
260-
let mut e1 = abs_index(mi, e1);
261-
if e1 < b1 { e1 = b1; }
262-
263-
ndassert!(b1 <= m,
264-
concat!("Slice begin {} is past end of axis of length {}",
265-
" (for SliceArg {:?})"),
266-
b1, m, slices);
267-
ndassert!(e1 <= m,
268-
concat!("Slice end {} is past end of axis of length {}",
269-
" (for SliceArg {:?})"),
270-
e1, m, slices);
271-
272-
let m = e1 - b1;
273-
// stride
274-
let s = (*sr) as Ixs;
275-
276-
// Data pointer offset
277-
offset += stride_offset(b1, *sr);
278-
// Adjust for strides
279-
ndassert!(s1 != 0,
280-
concat!("Slice stride must not be none",
281-
"(for SliceArg {:?})"),
282-
slices);
283-
// How to implement negative strides:
284-
//
285-
// Increase start pointer by
286-
// old stride * (old dim - 1)
287-
// to put the pointer completely in the other end
288-
if s1 < 0 {
289-
offset += stride_offset(m - 1, *sr);
290-
}
291-
292-
let s_prim = s * s1;
293-
294-
let d = m / s1.abs() as Ix;
295-
let r = m % s1.abs() as Ix;
296-
let m_prim = d + if r > 0 { 1 } else { 0 };
297-
298-
// Update dimension and stride coordinate
299-
*dr = m_prim;
300-
*sr = s_prim as Ix;
301-
}
302-
offset
303-
}
304-
305255
#[doc(hidden)]
306256
fn is_contiguous(dim: &Self, strides: &Self) -> bool {
307257
let defaults = dim.default_strides();
@@ -398,18 +348,6 @@ pub trait Dimension : Clone + Eq + Debug + Send + Sync + Default +
398348
private_decl!{}
399349
}
400350

401-
// utility functions
402-
403-
#[inline]
404-
fn abs_index(len: Ixs, index: Ixs) -> Ix {
405-
if index < 0 {
406-
(len + index) as Ix
407-
} else {
408-
index as Ix
409-
}
410-
}
411-
412-
413351
// Dimension impls
414352

415353
macro_rules! impl_insert_axis_array(
@@ -425,7 +363,8 @@ macro_rules! impl_insert_axis_array(
425363
);
426364

427365
impl Dimension for Dim<[Ix; 0]> {
428-
type SliceArg = [Si; 0];
366+
const NDIM: Option<usize> = Some(0);
367+
type SliceArg = [SliceOrIndex; 0];
429368
type Pattern = ();
430369
type Smaller = Self;
431370
type Larger = Ix1;
@@ -441,6 +380,11 @@ impl Dimension for Dim<[Ix; 0]> {
441380
#[inline]
442381
fn into_pattern(self) -> Self::Pattern { }
443382
#[inline]
383+
fn zero_index_with_ndim(ndim: usize) -> Self {
384+
assert_eq!(ndim, 0);
385+
Self::default()
386+
}
387+
#[inline]
444388
fn next_for(&self, _index: Self) -> Option<Self> {
445389
None
446390
}
@@ -456,7 +400,8 @@ impl Dimension for Dim<[Ix; 0]> {
456400

457401

458402
impl Dimension for Dim<[Ix; 1]> {
459-
type SliceArg = [Si; 1];
403+
const NDIM: Option<usize> = Some(1);
404+
type SliceArg = [SliceOrIndex; 1];
460405
type Pattern = Ix;
461406
type Smaller = Ix0;
462407
type Larger = Ix2;
@@ -471,6 +416,11 @@ impl Dimension for Dim<[Ix; 1]> {
471416
get!(&self, 0)
472417
}
473418
#[inline]
419+
fn zero_index_with_ndim(ndim: usize) -> Self {
420+
assert_eq!(ndim, 1);
421+
Self::default()
422+
}
423+
#[inline]
474424
fn next_for(&self, mut index: Self) -> Option<Self> {
475425
getm!(index, 0) += 1;
476426
if get!(&index, 0) < get!(self, 0) {
@@ -544,7 +494,8 @@ impl Dimension for Dim<[Ix; 1]> {
544494
}
545495

546496
impl Dimension for Dim<[Ix; 2]> {
547-
type SliceArg = [Si; 2];
497+
const NDIM: Option<usize> = Some(2);
498+
type SliceArg = [SliceOrIndex; 2];
548499
type Pattern = (Ix, Ix);
549500
type Smaller = Ix1;
550501
type Larger = Ix3;
@@ -559,6 +510,11 @@ impl Dimension for Dim<[Ix; 2]> {
559510
#[inline]
560511
fn slice_mut(&mut self) -> &mut [Ix] { self.ixm() }
561512
#[inline]
513+
fn zero_index_with_ndim(ndim: usize) -> Self {
514+
assert_eq!(ndim, 2);
515+
Self::default()
516+
}
517+
#[inline]
562518
fn next_for(&self, index: Self) -> Option<Self> {
563519
let mut i = get!(&index, 0);
564520
let mut j = get!(&index, 1);
@@ -674,7 +630,8 @@ impl Dimension for Dim<[Ix; 2]> {
674630
}
675631

676632
impl Dimension for Dim<[Ix; 3]> {
677-
type SliceArg = [Si; 3];
633+
const NDIM: Option<usize> = Some(3);
634+
type SliceArg = [SliceOrIndex; 3];
678635
type Pattern = (Ix, Ix, Ix);
679636
type Smaller = Ix2;
680637
type Larger = Ix4;
@@ -697,6 +654,12 @@ impl Dimension for Dim<[Ix; 3]> {
697654
m as usize * n as usize * o as usize
698655
}
699656

657+
#[inline]
658+
fn zero_index_with_ndim(ndim: usize) -> Self {
659+
assert_eq!(ndim, 3);
660+
Self::default()
661+
}
662+
700663
#[inline]
701664
fn next_for(&self, index: Self) -> Option<Self> {
702665
let mut i = get!(&index, 0);
@@ -785,7 +748,8 @@ impl Dimension for Dim<[Ix; 3]> {
785748
macro_rules! large_dim {
786749
($n:expr, $name:ident, $pattern:ty, $larger:ty, { $($insert_axis:tt)* }) => (
787750
impl Dimension for Dim<[Ix; $n]> {
788-
type SliceArg = [Si; $n];
751+
const NDIM: Option<usize> = Some($n);
752+
type SliceArg = [SliceOrIndex; $n];
789753
type Pattern = $pattern;
790754
type Smaller = Dim<[Ix; $n - 1]>;
791755
type Larger = $larger;
@@ -800,6 +764,11 @@ macro_rules! large_dim {
800764
#[inline]
801765
fn slice_mut(&mut self) -> &mut [Ix] { self.ixm() }
802766
#[inline]
767+
fn zero_index_with_ndim(ndim: usize) -> Self {
768+
assert_eq!(ndim, $n);
769+
Self::default()
770+
}
771+
#[inline]
803772
$($insert_axis)*
804773
#[inline]
805774
fn try_remove_axis(&self, axis: Axis) -> Self::Smaller {
@@ -831,7 +800,8 @@ large_dim!(6, Ix6, (Ix, Ix, Ix, Ix, Ix, Ix), IxDyn, {
831800
/// and memory wasteful, but it allows an arbitrary and dynamic number of axes.
832801
impl Dimension for IxDyn
833802
{
834-
type SliceArg = [Si];
803+
const NDIM: Option<usize> = None;
804+
type SliceArg = [SliceOrIndex];
835805
type Pattern = Self;
836806
type Smaller = Self;
837807
type Larger = Self;
@@ -851,6 +821,11 @@ impl Dimension for IxDyn
851821
IxDyn::zeros(self.ndim())
852822
}
853823

824+
#[inline]
825+
fn zero_index_with_ndim(ndim: usize) -> Self {
826+
IxDyn::zeros(ndim)
827+
}
828+
854829
#[inline]
855830
fn insert_axis(&self, axis: Axis) -> Self::Larger {
856831
debug_assert!(axis.index() <= self.ndim());

0 commit comments

Comments
 (0)