@@ -19,7 +19,7 @@ use dimension;
19
19
use iterators;
20
20
use error:: { self , ShapeError , ErrorKind } ;
21
21
use dimension:: IntoDimension ;
22
- use dimension:: { axes_of, Axes , do_slice, merge_axes, stride_offset} ;
22
+ use dimension:: { abs_index , axes_of, Axes , do_slice, merge_axes, stride_offset} ;
23
23
use iterators:: {
24
24
new_lanes,
25
25
new_lanes_mut,
@@ -31,7 +31,8 @@ use zip::Zip;
31
31
32
32
use {
33
33
NdIndex ,
34
- Si ,
34
+ SliceInfo ,
35
+ SliceOrIndex
35
36
} ;
36
37
use iter:: {
37
38
AxisChunksIter ,
@@ -207,53 +208,111 @@ impl<A, S, D> ArrayBase<S, D> where S: Data<Elem=A>, D: Dimension
207
208
}
208
209
209
210
210
- /// Return a sliced array.
211
+ /// Return a sliced view of the array.
211
212
///
212
213
/// See [*Slicing*](#slicing) for full documentation.
213
- /// See also [`D::SliceArg`].
214
+ /// See also [`SliceInfo`] and [` D::SliceArg`].
214
215
///
216
+ /// [`SliceInfo`]: struct.SliceInfo.html
215
217
/// [`D::SliceArg`]: trait.Dimension.html#associatedtype.SliceArg
216
218
///
217
- /// **Panics** if an index is out of bounds or stride is zero.<br>
218
- /// (**Panics** if `D` is `IxDyn` and `indexes` does not match the number of array axes.)
219
- pub fn slice ( & self , indexes : & D :: SliceArg ) -> ArrayView < A , D > {
220
- let mut arr = self . view ( ) ;
221
- arr. slice_inplace ( indexes) ;
222
- arr
219
+ /// **Panics** if an index is out of bounds or step size is zero.<br>
220
+ /// (**Panics** if `D` is `IxDyn` and `info` does not match the number of array axes.)
221
+ pub fn slice < Do > ( & self , info : & SliceInfo < D :: SliceArg , Do > ) -> ArrayView < A , Do >
222
+ where
223
+ Do : Dimension ,
224
+ {
225
+ self . view ( ) . slice_move ( info)
223
226
}
224
227
225
228
/// Return a sliced read-write view of the array.
226
229
///
227
- /// See also [`D::SliceArg`].
230
+ /// See [*Slicing*](#slicing) for full documentation.
231
+ /// See also [`SliceInfo`] and [`D::SliceArg`].
228
232
///
233
+ /// [`SliceInfo`]: struct.SliceInfo.html
229
234
/// [`D::SliceArg`]: trait.Dimension.html#associatedtype.SliceArg
230
235
///
231
- /// **Panics** if an index is out of bounds or stride is zero.<br>
232
- /// (**Panics** if `D` is `IxDyn` and `indexes` does not match the number of array axes.)
233
- pub fn slice_mut ( & mut self , indexes : & D :: SliceArg ) -> ArrayViewMut < A , D >
234
- where S : DataMut
236
+ /// **Panics** if an index is out of bounds or step size is zero.<br>
237
+ /// (**Panics** if `D` is `IxDyn` and `info` does not match the number of array axes.)
238
+ pub fn slice_mut < Do > ( & mut self , info : & SliceInfo < D :: SliceArg , Do > ) -> ArrayViewMut < A , Do >
239
+ where
240
+ Do : Dimension ,
241
+ S : DataMut ,
242
+ {
243
+ self . view_mut ( ) . slice_move ( info)
244
+ }
245
+
246
+ /// Slice the array, possibly changing the number of dimensions.
247
+ ///
248
+ /// See [*Slicing*](#slicing) for full documentation.
249
+ /// See also [`SliceInfo`] and [`D::SliceArg`].
250
+ ///
251
+ /// [`SliceInfo`]: struct.SliceInfo.html
252
+ /// [`D::SliceArg`]: trait.Dimension.html#associatedtype.SliceArg
253
+ ///
254
+ /// **Panics** if an index is out of bounds or step size is zero.<br>
255
+ /// (**Panics** if `D` is `IxDyn` and `info` does not match the number of array axes.)
256
+ pub fn slice_move < Do > ( mut self , info : & SliceInfo < D :: SliceArg , Do > ) -> ArrayBase < S , Do >
257
+ where
258
+ Do : Dimension ,
235
259
{
236
- let mut arr = self . view_mut ( ) ;
237
- arr. slice_inplace ( indexes) ;
238
- arr
260
+ // Slice and subview in-place without changing the number of dimensions.
261
+ self . slice_inplace ( & * info) ;
262
+
263
+ let indices: & [ SliceOrIndex ] = ( * * info) . as_ref ( ) ;
264
+
265
+ // Copy the dim and strides that remain after removing the subview axes.
266
+ let out_ndim = info. out_ndim ( ) ;
267
+ let mut new_dim = Do :: zero_index_with_ndim ( out_ndim) ;
268
+ let mut new_strides = Do :: zero_index_with_ndim ( out_ndim) ;
269
+ izip ! ( self . dim. slice( ) , self . strides. slice( ) , indices)
270
+ . filter_map ( |( d, s, slice_or_index) | match slice_or_index {
271
+ & SliceOrIndex :: Slice ( ..) => Some ( ( d, s) ) ,
272
+ & SliceOrIndex :: Index ( _) => None ,
273
+ } )
274
+ . zip ( izip ! ( new_dim. slice_mut( ) , new_strides. slice_mut( ) ) )
275
+ . for_each ( |( ( d, s) , ( new_d, new_s) ) | {
276
+ * new_d = * d;
277
+ * new_s = * s;
278
+ } ) ;
279
+
280
+ ArrayBase {
281
+ ptr : self . ptr ,
282
+ data : self . data ,
283
+ dim : new_dim,
284
+ strides : new_strides,
285
+ }
239
286
}
240
287
241
- /// Slice the array’s view in place.
288
+ /// Slice the array in place without changing the number of dimensions.
289
+ ///
290
+ /// Note that [`&SliceInfo`](struct.SliceInfo.html) (produced by the
291
+ /// [`s![]`](macro.s!.html) macro) will usually coerce into `&D::SliceArg`
292
+ /// automatically, but in some cases (e.g. if `D` is `IxDyn`), you may need
293
+ /// to call `.as_ref()`.
242
294
///
295
+ /// See [*Slicing*](#slicing) for full documentation.
243
296
/// See also [`D::SliceArg`].
244
297
///
245
298
/// [`D::SliceArg`]: trait.Dimension.html#associatedtype.SliceArg
246
299
///
247
- /// **Panics** if an index is out of bounds or stride is zero.<br>
248
- /// (**Panics** if `D` is `IxDyn` and `indexes ` does not match the number of array axes.)
249
- pub fn slice_inplace ( & mut self , indexes : & D :: SliceArg ) {
250
- let indexes : & [ Si ] = indexes . as_ref ( ) ;
251
- assert_eq ! ( indexes . len( ) , self . ndim( ) ) ;
252
- indexes
300
+ /// **Panics** if an index is out of bounds or step size is zero.<br>
301
+ /// (**Panics** if `D` is `IxDyn` and `indices ` does not match the number of array axes.)
302
+ pub fn slice_inplace ( & mut self , indices : & D :: SliceArg ) {
303
+ let indices : & [ SliceOrIndex ] = indices . as_ref ( ) ;
304
+ assert_eq ! ( indices . len( ) , self . ndim( ) ) ;
305
+ indices
253
306
. iter ( )
254
307
. enumerate ( )
255
- . for_each ( |( axis, & Si ( start, end, step) ) | {
256
- self . slice_axis_inplace ( Axis ( axis) , start, end, step)
308
+ . for_each ( |( axis, slice_or_index) | match slice_or_index {
309
+ & SliceOrIndex :: Slice ( start, end, step) => {
310
+ self . slice_axis_inplace ( Axis ( axis) , start, end, step)
311
+ }
312
+ & SliceOrIndex :: Index ( index) => {
313
+ let i_usize = abs_index ( self . len_of ( Axis ( axis) ) , index) ;
314
+ self . subview_inplace ( Axis ( axis) , i_usize)
315
+ }
257
316
} ) ;
258
317
}
259
318
0 commit comments