@@ -10,13 +10,70 @@ use std::fmt;
1010use std:: marker:: PhantomData ;
1111use super :: { Dimension , Ixs } ;
1212
13+ /// A slice (range with step size).
14+ ///
15+ /// ## Examples
16+ ///
17+ /// `Slice(0, None, 1)` is the full range of an axis. It can also be created
18+ /// with `Slice::from(..)`. The Python equivalent is `[:]`.
19+ ///
20+ /// `Slice(a, Some(b), 2)` is every second element from `a` until `b`. It can
21+ /// also be created with `Slice::from(a..b).step(2)`. The Python equivalent is
22+ /// `[a:b:2]`.
23+ ///
24+ /// `Slice(a, None, -1)` is every element, from `a` until the end, in reverse
25+ /// order. It can also be created with `Slice::from(a..).step(-1)`. The Python
26+ /// equivalent is `[a::-1]`.
27+ #[ derive( Clone , Debug , PartialEq , Eq , Hash ) ]
28+ pub struct Slice ( pub Ixs , pub Option < Ixs > , pub Ixs ) ;
29+
30+ impl Slice {
31+ /// Returns a new `Slice` with the given step size.
32+ #[ inline]
33+ pub fn step ( self , step : Ixs ) -> Self {
34+ Slice ( self . 0 , self . 1 , step)
35+ }
36+ }
37+
38+ impl From < Range < Ixs > > for Slice {
39+ #[ inline]
40+ fn from ( r : Range < Ixs > ) -> Slice {
41+ Slice ( r. start , Some ( r. end ) , 1 )
42+ }
43+ }
44+
45+ impl From < RangeFrom < Ixs > > for Slice {
46+ #[ inline]
47+ fn from ( r : RangeFrom < Ixs > ) -> Slice {
48+ Slice ( r. start , None , 1 )
49+ }
50+ }
51+
52+ impl From < RangeTo < Ixs > > for Slice {
53+ #[ inline]
54+ fn from ( r : RangeTo < Ixs > ) -> Slice {
55+ Slice ( 0 , Some ( r. end ) , 1 )
56+ }
57+ }
58+
59+ impl From < RangeFull > for Slice {
60+ #[ inline]
61+ fn from ( _: RangeFull ) -> Slice {
62+ Slice ( 0 , None , 1 )
63+ }
64+ }
65+
1366/// A slice (range with step) or an index.
1467///
1568/// See also the [`s![]`](macro.s!.html) macro for a convenient way to create a
1669/// `&SliceInfo<[SliceOrIndex; n], D>`.
1770///
1871/// ## Examples
1972///
73+ /// `SliceOrIndex::Index(a)` is the index `a`. It can also be created with
74+ /// `SliceOrIndex::from(a)`. The Python equivalent is `[a]`. The macro
75+ /// equivalent is `s![a]`.
76+ ///
2077/// `SliceOrIndex::Slice(0, None, 1)` is the full range of an axis. It can also
2178/// be created with `SliceOrIndex::from(..)`. The Python equivalent is `[:]`.
2279/// The macro equivalent is `s![..]`.
@@ -89,6 +146,13 @@ impl fmt::Display for SliceOrIndex {
89146 }
90147}
91148
149+ impl From < Slice > for SliceOrIndex {
150+ #[ inline]
151+ fn from ( s : Slice ) -> SliceOrIndex {
152+ SliceOrIndex :: Slice ( s. 0 , s. 1 , s. 2 )
153+ }
154+ }
155+
92156impl From < Range < Ixs > > for SliceOrIndex {
93157 #[ inline]
94158 fn from ( r : Range < Ixs > ) -> SliceOrIndex {
@@ -261,6 +325,12 @@ pub trait SliceNextDim<D1, D2> {
261325 fn next_dim ( & self , PhantomData < D1 > ) -> PhantomData < D2 > ;
262326}
263327
328+ impl < D1 : Dimension > SliceNextDim < D1 , D1 :: Larger > for Slice {
329+ fn next_dim ( & self , _: PhantomData < D1 > ) -> PhantomData < D1 :: Larger > {
330+ PhantomData
331+ }
332+ }
333+
264334impl < D1 : Dimension > SliceNextDim < D1 , D1 :: Larger > for Range < Ixs > {
265335 fn next_dim ( & self , _: PhantomData < D1 > ) -> PhantomData < D1 :: Larger > {
266336 PhantomData
@@ -293,26 +363,31 @@ impl<D1: Dimension> SliceNextDim<D1, D1> for Ixs {
293363
294364/// Slice argument constructor.
295365///
296- /// `s![]` takes a list of ranges/indices, separated by comma, with optional
297- /// step sizes that are separated from the range by a semicolon. It is
366+ /// `s![]` takes a list of ranges/slices/ indices, separated by comma, with
367+ /// optional step sizes that are separated from the range by a semicolon. It is
298368/// converted into a [`&SliceInfo`] instance.
299369///
300370/// [`&SliceInfo`]: struct.SliceInfo.html
301371///
302- /// Each range/index uses signed indices, where a negative value is counted
303- /// from the end of the axis. Step sizes are also signed and may be negative,
304- /// but must not be zero.
372+ /// Each range/slice/ index uses signed indices, where a negative value is
373+ /// counted from the end of the axis. Step sizes are also signed and may be
374+ /// negative, but must not be zero.
305375///
306376/// The syntax is `s![` *[ axis-slice-or-index [, axis-slice-or-index [ , ... ]
307377/// ] ]* `]`, where *axis-slice-or-index* is any of the following:
308378///
309379/// * *index*: an index to use for taking a subview with respect to that axis
310380/// * *range*: a range with step size 1 to use for slicing that axis
311381/// * *range* `;` *step*: a range with step size *step* to use for slicing that axis
382+ /// * *slice*: a [`Slice`] instance to use for slicing that axis
383+ /// * *slice* `;` *step*: a range constructed from the start and end of a [`Slice`]
384+ /// instance, with new step size *step*, to use for slicing that axis
385+ ///
386+ /// [`Slice`]: struct.Slice.html
312387///
313388/// The number of *axis-slice-or-index* must match the number of axes in the
314- /// array. *index*, *range*, and *step* can be expressions. *index* and *step *
315- /// must be of type [`Ixs`]. *range* can be of type `Range<Ixs>`,
389+ /// array. *index*, *range*, *slice*, and *step* can be expressions. *index*
390+ /// and *step* must be of type [`Ixs`]. *range* can be of type `Range<Ixs>`,
316391/// `RangeTo<Ixs>`, `RangeFrom<Ixs>`, or `RangeFull`.
317392///
318393/// [`Ixs`]: type.Ixs.html
0 commit comments