@@ -10,13 +10,70 @@ use std::fmt;
10
10
use std:: marker:: PhantomData ;
11
11
use super :: { Dimension , Ixs } ;
12
12
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( Copy , 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
+
13
66
/// A slice (range with step) or an index.
14
67
///
15
68
/// See also the [`s![]`](macro.s!.html) macro for a convenient way to create a
16
69
/// `&SliceInfo<[SliceOrIndex; n], D>`.
17
70
///
18
71
/// ## Examples
19
72
///
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
+ ///
20
77
/// `SliceOrIndex::Slice(0, None, 1)` is the full range of an axis. It can also
21
78
/// be created with `SliceOrIndex::from(..)`. The Python equivalent is `[:]`.
22
79
/// The macro equivalent is `s![..]`.
@@ -89,6 +146,13 @@ impl fmt::Display for SliceOrIndex {
89
146
}
90
147
}
91
148
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
+
92
156
impl From < Range < Ixs > > for SliceOrIndex {
93
157
#[ inline]
94
158
fn from ( r : Range < Ixs > ) -> SliceOrIndex {
@@ -261,6 +325,12 @@ pub trait SliceNextDim<D1, D2> {
261
325
fn next_dim ( & self , PhantomData < D1 > ) -> PhantomData < D2 > ;
262
326
}
263
327
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
+
264
334
impl < D1 : Dimension > SliceNextDim < D1 , D1 :: Larger > for Range < Ixs > {
265
335
fn next_dim ( & self , _: PhantomData < D1 > ) -> PhantomData < D1 :: Larger > {
266
336
PhantomData
@@ -293,26 +363,31 @@ impl<D1: Dimension> SliceNextDim<D1, D1> for Ixs {
293
363
294
364
/// Slice argument constructor.
295
365
///
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
298
368
/// converted into a [`&SliceInfo`] instance.
299
369
///
300
370
/// [`&SliceInfo`]: struct.SliceInfo.html
301
371
///
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.
305
375
///
306
376
/// The syntax is `s![` *[ axis-slice-or-index [, axis-slice-or-index [ , ... ]
307
377
/// ] ]* `]`, where *axis-slice-or-index* is any of the following:
308
378
///
309
379
/// * *index*: an index to use for taking a subview with respect to that axis
310
380
/// * *range*: a range with step size 1 to use for slicing that axis
311
381
/// * *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
312
387
///
313
388
/// 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>`,
316
391
/// `RangeTo<Ixs>`, `RangeFrom<Ixs>`, or `RangeFull`.
317
392
///
318
393
/// [`Ixs`]: type.Ixs.html
0 commit comments