@@ -9,7 +9,7 @@ use std::{
9
9
10
10
use ndarray:: {
11
11
Array , ArrayBase , ArrayView , ArrayViewMut , Axis , Data , Dim , Dimension , IntoDimension , Ix0 , Ix1 ,
12
- Ix2 , Ix3 , Ix4 , Ix5 , Ix6 , IxDyn , RawArrayView , RawArrayViewMut , RawData , Shape , ShapeBuilder ,
12
+ Ix2 , Ix3 , Ix4 , Ix5 , Ix6 , IxDyn , RawArrayView , RawArrayViewMut , RawData , ShapeBuilder ,
13
13
StrideShape ,
14
14
} ;
15
15
use num_traits:: AsPrimitive ;
@@ -338,42 +338,19 @@ impl<T, D> PyArray<T, D> {
338
338
}
339
339
}
340
340
341
- /// Calcurates the total number of elements in the array.
341
+ /// Calculates the total number of elements in the array.
342
342
pub fn len ( & self ) -> usize {
343
343
self . shape ( ) . iter ( ) . product ( )
344
344
}
345
345
346
+ /// Returns `true` if the there are no elements in the array.
346
347
pub fn is_empty ( & self ) -> bool {
347
- self . len ( ) == 0
348
+ self . shape ( ) . iter ( ) . any ( |dim| * dim == 0 )
348
349
}
349
350
350
- /// Returns the pointer to the first element of the inner array.
351
+ /// Returns the pointer to the first element of the array.
351
352
pub ( crate ) fn data ( & self ) -> * mut T {
352
- let ptr = self . as_array_ptr ( ) ;
353
- unsafe { ( * ptr) . data as * mut _ }
354
- }
355
- }
356
-
357
- struct InvertedAxes ( u32 ) ;
358
-
359
- impl InvertedAxes {
360
- fn new ( len : usize ) -> Self {
361
- assert ! ( len <= 32 , "Only dimensionalities of up to 32 are supported" ) ;
362
- Self ( 0 )
363
- }
364
-
365
- fn push ( & mut self , axis : usize ) {
366
- debug_assert ! ( axis < 32 ) ;
367
- self . 0 |= 1 << axis;
368
- }
369
-
370
- fn invert < S : RawData , D : Dimension > ( mut self , array : & mut ArrayBase < S , D > ) {
371
- while self . 0 != 0 {
372
- let axis = self . 0 . trailing_zeros ( ) as usize ;
373
- self . 0 &= !( 1 << axis) ;
374
-
375
- array. invert_axis ( Axis ( axis) ) ;
376
- }
353
+ unsafe { ( * self . as_array_ptr ( ) ) . data as * mut _ }
377
354
}
378
355
}
379
356
@@ -384,38 +361,6 @@ impl<T: Element, D: Dimension> PyArray<T, D> {
384
361
D :: from_dimension ( & Dim ( self . shape ( ) ) ) . expect ( "mismatching dimensions" )
385
362
}
386
363
387
- fn ndarray_shape_ptr ( & self ) -> ( StrideShape < D > , * mut T , InvertedAxes ) {
388
- let shape = self . shape ( ) ;
389
- let strides = self . strides ( ) ;
390
-
391
- let mut new_strides = D :: zeros ( strides. len ( ) ) ;
392
- let mut data_ptr = self . data ( ) ;
393
- let mut inverted_axes = InvertedAxes :: new ( strides. len ( ) ) ;
394
-
395
- for i in 0 ..strides. len ( ) {
396
- // FIXME(kngwyu): Replace this hacky negative strides support with
397
- // a proper constructor, when it's implemented.
398
- // See https://github.com/rust-ndarray/ndarray/issues/842 for more.
399
- if strides[ i] < 0 {
400
- // Move the pointer to the start position
401
- let offset = strides[ i] * ( shape[ i] as isize - 1 ) / mem:: size_of :: < T > ( ) as isize ;
402
- unsafe {
403
- data_ptr = data_ptr. offset ( offset) ;
404
- }
405
- new_strides[ i] = ( -strides[ i] ) as usize / mem:: size_of :: < T > ( ) ;
406
-
407
- inverted_axes. push ( i) ;
408
- } else {
409
- new_strides[ i] = strides[ i] as usize / mem:: size_of :: < T > ( ) ;
410
- }
411
- }
412
-
413
- let shape = Shape :: from ( D :: from_dimension ( & Dim ( shape) ) . expect ( "mismatching dimensions" ) ) ;
414
- let new_strides = D :: from_dimension ( & Dim ( new_strides) ) . expect ( "mismatching dimensions" ) ;
415
-
416
- ( shape. strides ( new_strides) , data_ptr, inverted_axes)
417
- }
418
-
419
364
/// Creates a new uninitialized PyArray in python heap.
420
365
///
421
366
/// If `is_fortran == true`, returns Fortran-order array. Else, returns C-order array.
@@ -883,6 +828,63 @@ impl<T: Element, D: Dimension> PyArray<T, D> {
883
828
self . try_readwrite ( ) . unwrap ( )
884
829
}
885
830
831
+ fn as_view < S : RawData , F > ( & self , from_shape_ptr : F ) -> ArrayBase < S , D >
832
+ where
833
+ F : FnOnce ( StrideShape < D > , * mut T ) -> ArrayBase < S , D > ,
834
+ {
835
+ fn inner < D : Dimension > (
836
+ shape : & [ usize ] ,
837
+ strides : & [ isize ] ,
838
+ itemsize : usize ,
839
+ mut data_ptr : * mut u8 ,
840
+ ) -> ( StrideShape < D > , u32 , * mut u8 ) {
841
+ let shape = D :: from_dimension ( & Dim ( shape) ) . expect ( "mismatching dimensions" ) ;
842
+
843
+ assert ! (
844
+ strides. len( ) <= 32 ,
845
+ "Only dimensionalities of up to 32 are supported"
846
+ ) ;
847
+
848
+ let mut new_strides = D :: zeros ( strides. len ( ) ) ;
849
+ let mut inverted_axes = 0_u32 ;
850
+
851
+ for i in 0 ..strides. len ( ) {
852
+ // FIXME(kngwyu): Replace this hacky negative strides support with
853
+ // a proper constructor, when it's implemented.
854
+ // See https://github.com/rust-ndarray/ndarray/issues/842 for more.
855
+ if strides[ i] >= 0 {
856
+ new_strides[ i] = strides[ i] as usize / itemsize;
857
+ } else {
858
+ // Move the pointer to the start position.
859
+ data_ptr = unsafe { data_ptr. offset ( strides[ i] * ( shape[ i] as isize - 1 ) ) } ;
860
+
861
+ new_strides[ i] = ( -strides[ i] ) as usize / itemsize;
862
+ inverted_axes |= 1 << i;
863
+ }
864
+ }
865
+
866
+ ( shape. strides ( new_strides) , inverted_axes, data_ptr)
867
+ }
868
+
869
+ let ( shape, mut inverted_axes, data_ptr) = inner (
870
+ self . shape ( ) ,
871
+ self . strides ( ) ,
872
+ mem:: size_of :: < T > ( ) ,
873
+ self . data ( ) as _ ,
874
+ ) ;
875
+
876
+ let mut array = from_shape_ptr ( shape, data_ptr as _ ) ;
877
+
878
+ while inverted_axes != 0 {
879
+ let axis = inverted_axes. trailing_zeros ( ) as usize ;
880
+ inverted_axes &= !( 1 << axis) ;
881
+
882
+ array. invert_axis ( Axis ( axis) ) ;
883
+ }
884
+
885
+ array
886
+ }
887
+
886
888
/// Returns the internal array as [`ArrayView`].
887
889
///
888
890
/// See also [`PyReadonlyArray::as_array`].
@@ -891,10 +893,7 @@ impl<T: Element, D: Dimension> PyArray<T, D> {
891
893
///
892
894
/// The existence of an exclusive reference to the internal data, e.g. `&mut [T]` or `ArrayViewMut`, implies undefined behavior.
893
895
pub unsafe fn as_array ( & self ) -> ArrayView < ' _ , T , D > {
894
- let ( shape, ptr, inverted_axes) = self . ndarray_shape_ptr ( ) ;
895
- let mut res = ArrayView :: from_shape_ptr ( shape, ptr) ;
896
- inverted_axes. invert ( & mut res) ;
897
- res
896
+ self . as_view ( |shape, ptr| ArrayView :: from_shape_ptr ( shape, ptr) )
898
897
}
899
898
900
899
/// Returns the internal array as [`ArrayViewMut`].
@@ -905,26 +904,17 @@ impl<T: Element, D: Dimension> PyArray<T, D> {
905
904
///
906
905
/// The existence of another reference to the internal data, e.g. `&[T]` or `ArrayView`, implies undefined behavior.
907
906
pub unsafe fn as_array_mut ( & self ) -> ArrayViewMut < ' _ , T , D > {
908
- let ( shape, ptr, inverted_axes) = self . ndarray_shape_ptr ( ) ;
909
- let mut res = ArrayViewMut :: from_shape_ptr ( shape, ptr) ;
910
- inverted_axes. invert ( & mut res) ;
911
- res
907
+ self . as_view ( |shape, ptr| ArrayViewMut :: from_shape_ptr ( shape, ptr) )
912
908
}
913
909
914
910
/// Returns the internal array as [`RawArrayView`] enabling element access via raw pointers
915
911
pub fn as_raw_array ( & self ) -> RawArrayView < T , D > {
916
- let ( shape, ptr, inverted_axes) = self . ndarray_shape_ptr ( ) ;
917
- let mut res = unsafe { RawArrayView :: from_shape_ptr ( shape, ptr) } ;
918
- inverted_axes. invert ( & mut res) ;
919
- res
912
+ self . as_view ( |shape, ptr| unsafe { RawArrayView :: from_shape_ptr ( shape, ptr) } )
920
913
}
921
914
922
915
/// Returns the internal array as [`RawArrayViewMut`] enabling element access via raw pointers
923
916
pub fn as_raw_array_mut ( & self ) -> RawArrayViewMut < T , D > {
924
- let ( shape, ptr, inverted_axes) = self . ndarray_shape_ptr ( ) ;
925
- let mut res = unsafe { RawArrayViewMut :: from_shape_ptr ( shape, ptr) } ;
926
- inverted_axes. invert ( & mut res) ;
927
- res
917
+ self . as_view ( |shape, ptr| unsafe { RawArrayViewMut :: from_shape_ptr ( shape, ptr) } )
928
918
}
929
919
930
920
/// Get a copy of `PyArray` as
0 commit comments