@@ -13,7 +13,7 @@ use std::ops::{Add, Sub, Mul, AddAssign, SubAssign, MulAssign};
13
13
14
14
use itertools:: { enumerate, zip} ;
15
15
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 } ;
17
17
use IntoDimension ;
18
18
use RemoveAxis ;
19
19
use { ArrayView1 , ArrayViewMut1 } ;
@@ -41,21 +41,25 @@ pub trait Dimension : Clone + Eq + Debug + Send + Sync + Default +
41
41
MulAssign + for < ' x > MulAssign < & ' x Self > + MulAssign < usize >
42
42
43
43
{
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 > ;
44
48
/// `SliceArg` is the type which is used to specify slicing for this
45
49
/// dimension.
46
50
///
47
51
/// For the fixed size dimensions it is a fixed size array of the correct
48
52
/// size, which you pass by reference. For the dynamic dimension it is
49
53
/// a slice.
50
54
///
51
- /// - For `Ix1`: `[Si ; 1]`
52
- /// - For `Ix2`: `[Si ; 2]`
55
+ /// - For `Ix1`: `[SliceOrIndex ; 1]`
56
+ /// - For `Ix2`: `[SliceOrIndex ; 2]`
53
57
/// - and so on..
54
- /// - For `IxDyn`: `[Si ]`
58
+ /// - For `IxDyn`: `[SliceOrIndex ]`
55
59
///
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 ] > ;
59
63
/// Pattern matching friendly form of the dimension value.
60
64
///
61
65
/// - For `Ix1`: `usize`,
@@ -152,6 +156,15 @@ pub trait Dimension : Clone + Eq + Debug + Send + Sync + Default +
152
156
Self :: default ( )
153
157
}
154
158
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
+
155
168
#[ doc( hidden) ]
156
169
#[ inline]
157
170
fn first_index ( & self ) -> Option < Self > {
@@ -239,69 +252,6 @@ pub trait Dimension : Clone + Eq + Debug + Send + Sync + Default +
239
252
self . slice_mut ( ) [ nd - 1 ] = i;
240
253
}
241
254
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
-
305
255
#[ doc( hidden) ]
306
256
fn is_contiguous ( dim : & Self , strides : & Self ) -> bool {
307
257
let defaults = dim. default_strides ( ) ;
@@ -398,18 +348,6 @@ pub trait Dimension : Clone + Eq + Debug + Send + Sync + Default +
398
348
private_decl ! { }
399
349
}
400
350
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
-
413
351
// Dimension impls
414
352
415
353
macro_rules! impl_insert_axis_array(
@@ -425,7 +363,8 @@ macro_rules! impl_insert_axis_array(
425
363
) ;
426
364
427
365
impl Dimension for Dim < [ Ix ; 0 ] > {
428
- type SliceArg = [ Si ; 0 ] ;
366
+ const NDIM : Option < usize > = Some ( 0 ) ;
367
+ type SliceArg = [ SliceOrIndex ; 0 ] ;
429
368
type Pattern = ( ) ;
430
369
type Smaller = Self ;
431
370
type Larger = Ix1 ;
@@ -441,6 +380,11 @@ impl Dimension for Dim<[Ix; 0]> {
441
380
#[ inline]
442
381
fn into_pattern ( self ) -> Self :: Pattern { }
443
382
#[ inline]
383
+ fn zero_index_with_ndim ( ndim : usize ) -> Self {
384
+ assert_eq ! ( ndim, 0 ) ;
385
+ Self :: default ( )
386
+ }
387
+ #[ inline]
444
388
fn next_for ( & self , _index : Self ) -> Option < Self > {
445
389
None
446
390
}
@@ -456,7 +400,8 @@ impl Dimension for Dim<[Ix; 0]> {
456
400
457
401
458
402
impl Dimension for Dim < [ Ix ; 1 ] > {
459
- type SliceArg = [ Si ; 1 ] ;
403
+ const NDIM : Option < usize > = Some ( 1 ) ;
404
+ type SliceArg = [ SliceOrIndex ; 1 ] ;
460
405
type Pattern = Ix ;
461
406
type Smaller = Ix0 ;
462
407
type Larger = Ix2 ;
@@ -471,6 +416,11 @@ impl Dimension for Dim<[Ix; 1]> {
471
416
get ! ( & self , 0 )
472
417
}
473
418
#[ inline]
419
+ fn zero_index_with_ndim ( ndim : usize ) -> Self {
420
+ assert_eq ! ( ndim, 1 ) ;
421
+ Self :: default ( )
422
+ }
423
+ #[ inline]
474
424
fn next_for ( & self , mut index : Self ) -> Option < Self > {
475
425
getm ! ( index, 0 ) += 1 ;
476
426
if get ! ( & index, 0 ) < get ! ( self , 0 ) {
@@ -544,7 +494,8 @@ impl Dimension for Dim<[Ix; 1]> {
544
494
}
545
495
546
496
impl Dimension for Dim < [ Ix ; 2 ] > {
547
- type SliceArg = [ Si ; 2 ] ;
497
+ const NDIM : Option < usize > = Some ( 2 ) ;
498
+ type SliceArg = [ SliceOrIndex ; 2 ] ;
548
499
type Pattern = ( Ix , Ix ) ;
549
500
type Smaller = Ix1 ;
550
501
type Larger = Ix3 ;
@@ -559,6 +510,11 @@ impl Dimension for Dim<[Ix; 2]> {
559
510
#[ inline]
560
511
fn slice_mut ( & mut self ) -> & mut [ Ix ] { self . ixm ( ) }
561
512
#[ inline]
513
+ fn zero_index_with_ndim ( ndim : usize ) -> Self {
514
+ assert_eq ! ( ndim, 2 ) ;
515
+ Self :: default ( )
516
+ }
517
+ #[ inline]
562
518
fn next_for ( & self , index : Self ) -> Option < Self > {
563
519
let mut i = get ! ( & index, 0 ) ;
564
520
let mut j = get ! ( & index, 1 ) ;
@@ -674,7 +630,8 @@ impl Dimension for Dim<[Ix; 2]> {
674
630
}
675
631
676
632
impl Dimension for Dim < [ Ix ; 3 ] > {
677
- type SliceArg = [ Si ; 3 ] ;
633
+ const NDIM : Option < usize > = Some ( 3 ) ;
634
+ type SliceArg = [ SliceOrIndex ; 3 ] ;
678
635
type Pattern = ( Ix , Ix , Ix ) ;
679
636
type Smaller = Ix2 ;
680
637
type Larger = Ix4 ;
@@ -697,6 +654,12 @@ impl Dimension for Dim<[Ix; 3]> {
697
654
m as usize * n as usize * o as usize
698
655
}
699
656
657
+ #[ inline]
658
+ fn zero_index_with_ndim ( ndim : usize ) -> Self {
659
+ assert_eq ! ( ndim, 3 ) ;
660
+ Self :: default ( )
661
+ }
662
+
700
663
#[ inline]
701
664
fn next_for ( & self , index : Self ) -> Option < Self > {
702
665
let mut i = get ! ( & index, 0 ) ;
@@ -785,7 +748,8 @@ impl Dimension for Dim<[Ix; 3]> {
785
748
macro_rules! large_dim {
786
749
( $n: expr, $name: ident, $pattern: ty, $larger: ty, { $( $insert_axis: tt) * } ) => (
787
750
impl Dimension for Dim <[ Ix ; $n] > {
788
- type SliceArg = [ Si ; $n] ;
751
+ const NDIM : Option <usize > = Some ( $n) ;
752
+ type SliceArg = [ SliceOrIndex ; $n] ;
789
753
type Pattern = $pattern;
790
754
type Smaller = Dim <[ Ix ; $n - 1 ] >;
791
755
type Larger = $larger;
@@ -800,6 +764,11 @@ macro_rules! large_dim {
800
764
#[ inline]
801
765
fn slice_mut( & mut self ) -> & mut [ Ix ] { self . ixm( ) }
802
766
#[ inline]
767
+ fn zero_index_with_ndim( ndim: usize ) -> Self {
768
+ assert_eq!( ndim, $n) ;
769
+ Self :: default ( )
770
+ }
771
+ #[ inline]
803
772
$( $insert_axis) *
804
773
#[ inline]
805
774
fn try_remove_axis( & self , axis: Axis ) -> Self :: Smaller {
@@ -831,7 +800,8 @@ large_dim!(6, Ix6, (Ix, Ix, Ix, Ix, Ix, Ix), IxDyn, {
831
800
/// and memory wasteful, but it allows an arbitrary and dynamic number of axes.
832
801
impl Dimension for IxDyn
833
802
{
834
- type SliceArg = [ Si ] ;
803
+ const NDIM : Option < usize > = None ;
804
+ type SliceArg = [ SliceOrIndex ] ;
835
805
type Pattern = Self ;
836
806
type Smaller = Self ;
837
807
type Larger = Self ;
@@ -851,6 +821,11 @@ impl Dimension for IxDyn
851
821
IxDyn :: zeros ( self . ndim ( ) )
852
822
}
853
823
824
+ #[ inline]
825
+ fn zero_index_with_ndim ( ndim : usize ) -> Self {
826
+ IxDyn :: zeros ( ndim)
827
+ }
828
+
854
829
#[ inline]
855
830
fn insert_axis ( & self , axis : Axis ) -> Self :: Larger {
856
831
debug_assert ! ( axis. index( ) <= self . ndim( ) ) ;
0 commit comments