Skip to content

Commit 4405d36

Browse files
committed
Add support for slicing with inclusive ranges
Rust 1.26 added support for inclusive ranges, which can be created with syntax `start..=end` or `..=end`. This commit bumps the required Rust version to 1.27 because the `.start()` and `.end()` methods of `RangeInclusive` were added only in 1.27.
1 parent df55183 commit 4405d36

File tree

5 files changed

+81
-11
lines changed

5 files changed

+81
-11
lines changed

.travis.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ sudo: required
44
dist: trusty
55
matrix:
66
include:
7-
- rust: 1.26.0
7+
- rust: 1.27.0
88
env:
99
- FEATURES='test docs'
1010
- rust: stable

README.rst

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -92,9 +92,10 @@ Recent Changes (ndarray)
9292

9393
- Add ``var_axis`` method for computing variance by @LukeMathWalker.
9494
- Add support for 128-bit integer scalars (``i128`` and ``u128``).
95+
- Add support for slicing with inclusive ranges (``start..=end`` and ``..=end``).
9596
- Bump ``num-traits`` and ``num-complex`` to version ``0.2``.
9697
- Bump ``blas-src`` to version ``0.2``.
97-
- Bump minimum required Rust version to 1.26.
98+
- Bump minimum required Rust version to 1.27.
9899
- Additional contributors to this release: @ExpHP, @jturner314, @alexbool, @messense, @danmack, @nbro
99100

100101
- 0.11.2

src/lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@
5353
//! + Efficient floating point matrix multiplication even for very large
5454
//! matrices; can optionally use BLAS to improve it further.
5555
//! + See also the [`ndarray-parallel`] crate for integration with rayon.
56-
//! - **Requires Rust 1.26**
56+
//! - **Requires Rust 1.27**
5757
//!
5858
//! [`ndarray-parallel`]: https://docs.rs/ndarray-parallel
5959
//!

src/slice.rs

Lines changed: 69 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -6,15 +6,16 @@
66
// option. This file may not be copied, modified, or distributed
77
// except according to those terms.
88
use error::{ShapeError, ErrorKind};
9-
use std::ops::{Deref, Range, RangeFrom, RangeFull, RangeTo};
9+
use std::ops::{Deref, Range, RangeFrom, RangeFull, RangeInclusive, RangeTo, RangeToInclusive};
1010
use std::fmt;
1111
use std::marker::PhantomData;
1212
use super::Dimension;
1313

1414
/// A slice (range with step size).
1515
///
16-
/// Negative `begin` or `end` indexes are counted from the back of the axis. If
17-
/// `end` is `None`, the slice extends to the end of the axis.
16+
/// `end` is an exclusive index. Negative `begin` or `end` indexes are counted
17+
/// from the back of the axis. If `end` is `None`, the slice extends to the end
18+
/// of the axis.
1819
///
1920
/// See also the [`s![]`](macro.s.html) macro.
2021
///
@@ -79,6 +80,18 @@ macro_rules! impl_slice_from_index_type {
7980
}
8081
}
8182

83+
impl From<RangeInclusive<$index>> for Slice {
84+
#[inline]
85+
fn from(r: RangeInclusive<$index>) -> Slice {
86+
let end = *r.end() as isize;
87+
Slice {
88+
start: *r.start() as isize,
89+
end: if end == -1 { None } else { Some(end + 1) },
90+
step: 1,
91+
}
92+
}
93+
}
94+
8295
impl From<RangeFrom<$index>> for Slice {
8396
#[inline]
8497
fn from(r: RangeFrom<$index>) -> Slice {
@@ -100,7 +113,19 @@ macro_rules! impl_slice_from_index_type {
100113
}
101114
}
102115
}
103-
}
116+
117+
impl From<RangeToInclusive<$index>> for Slice {
118+
#[inline]
119+
fn from(r: RangeToInclusive<$index>) -> Slice {
120+
let end = r.end as isize;
121+
Slice {
122+
start: 0,
123+
end: if end == -1 { None } else { Some(end + 1) },
124+
step: 1,
125+
}
126+
}
127+
}
128+
};
104129
}
105130

106131
impl_slice_from_index_type!(isize);
@@ -144,9 +169,9 @@ impl From<RangeFull> for Slice {
144169
/// The macro equivalent is `s![a..;-1]`.
145170
#[derive(Debug, PartialEq, Eq, Hash)]
146171
pub enum SliceOrIndex {
147-
/// A range with step size. Negative `begin` or `end` indexes are counted
148-
/// from the back of the axis. If `end` is `None`, the slice extends to the
149-
/// end of the axis.
172+
/// A range with step size. `end` is an exclusive index. Negative `begin`
173+
/// or `end` indexes are counted from the back of the axis. If `end` is
174+
/// `None`, the slice extends to the end of the axis.
150175
Slice {
151176
start: isize,
152177
end: Option<isize>,
@@ -250,6 +275,18 @@ macro_rules! impl_sliceorindex_from_index_type {
250275
}
251276
}
252277

278+
impl From<RangeInclusive<$index>> for SliceOrIndex {
279+
#[inline]
280+
fn from(r: RangeInclusive<$index>) -> SliceOrIndex {
281+
let end = *r.end() as isize;
282+
SliceOrIndex::Slice {
283+
start: *r.start() as isize,
284+
end: if end == -1 { None } else { Some(end + 1) },
285+
step: 1,
286+
}
287+
}
288+
}
289+
253290
impl From<RangeFrom<$index>> for SliceOrIndex {
254291
#[inline]
255292
fn from(r: RangeFrom<$index>) -> SliceOrIndex {
@@ -271,7 +308,19 @@ macro_rules! impl_sliceorindex_from_index_type {
271308
}
272309
}
273310
}
274-
}
311+
312+
impl From<RangeToInclusive<$index>> for SliceOrIndex {
313+
#[inline]
314+
fn from(r: RangeToInclusive<$index>) -> SliceOrIndex {
315+
let end = r.end as isize;
316+
SliceOrIndex::Slice {
317+
start: 0,
318+
end: if end == -1 { None } else { Some(end + 1) },
319+
step: 1,
320+
}
321+
}
322+
}
323+
};
275324
}
276325

277326
impl_sliceorindex_from_index_type!(isize);
@@ -453,6 +502,12 @@ impl<D1: Dimension, T> SliceNextDim<D1, D1::Larger> for Range<T> {
453502
}
454503
}
455504

505+
impl<D1: Dimension, T> SliceNextDim<D1, D1::Larger> for RangeInclusive<T> {
506+
fn next_dim(&self, _: PhantomData<D1>) -> PhantomData<D1::Larger> {
507+
PhantomData
508+
}
509+
}
510+
456511
impl<D1: Dimension, T> SliceNextDim<D1, D1::Larger> for RangeFrom<T> {
457512
fn next_dim(&self, _: PhantomData<D1>) -> PhantomData<D1::Larger> {
458513
PhantomData
@@ -465,6 +520,12 @@ impl<D1: Dimension, T> SliceNextDim<D1, D1::Larger> for RangeTo<T> {
465520
}
466521
}
467522

523+
impl<D1: Dimension, T> SliceNextDim<D1, D1::Larger> for RangeToInclusive<T> {
524+
fn next_dim(&self, _: PhantomData<D1>) -> PhantomData<D1::Larger> {
525+
PhantomData
526+
}
527+
}
528+
468529
impl<D1: Dimension> SliceNextDim<D1, D1::Larger> for RangeFull {
469530
fn next_dim(&self, _: PhantomData<D1>) -> PhantomData<D1::Larger> {
470531
PhantomData

tests/array.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,14 @@ fn test_slice()
8282
assert!(vi.iter().zip(A.iter()).all(|(a, b)| a == b));
8383
}
8484

85+
#[test]
86+
fn test_slice_inclusive_range() {
87+
let arr = array![[1, 2, 3], [4, 5, 6]];
88+
assert_eq!(arr.slice(s![1..=1, 1..=2]), array![[5, 6]]);
89+
assert_eq!(arr.slice(s![1..=-1, -2..=2;-1]), array![[6, 5]]);
90+
assert_eq!(arr.slice(s![0..=-1, 0..=2;2]), array![[1, 3], [4, 6]]);
91+
}
92+
8593
/// Test that the compiler can infer a type for a sliced array from the
8694
/// arguments to `s![]`.
8795
///

0 commit comments

Comments
 (0)