@@ -12,7 +12,7 @@ use std::{iter::ExactSizeIterator, marker::PhantomData};
12
12
use crate :: convert:: { IntoPyArray , NpyIndex , ToNpyDims , ToPyArray } ;
13
13
use crate :: error:: { FromVecError , NotContiguousError , ShapeError } ;
14
14
use crate :: slice_box:: SliceBox ;
15
- use crate :: types:: { NpyDataType , TypeNum } ;
15
+ use crate :: types:: Element ;
16
16
17
17
/// A safe, static-typed interface for
18
18
/// [NumPy ndarray](https://numpy.org/doc/stable/reference/arrays.ndarray.html).
@@ -46,7 +46,7 @@ use crate::types::{NpyDataType, TypeNum};
46
46
/// `PyArray` has 2 type parametes `T` and `D`. `T` represents its data type like
47
47
/// [`f32`](https://doc.rust-lang.org/std/primitive.f32.html), and `D` represents its dimension.
48
48
///
49
- /// All data types you can use implements [TypeNum ](../types/trait.TypeNum .html).
49
+ /// All data types you can use implements [Element ](../types/trait.Element .html).
50
50
///
51
51
/// Dimensions are represented by ndarray's
52
52
/// [Dimension](https://docs.rs/ndarray/latest/ndarray/trait.Dimension.html) trait.
@@ -117,7 +117,7 @@ impl<'a, T, D> std::convert::From<&'a PyArray<T, D>> for &'a PyAny {
117
117
}
118
118
}
119
119
120
- impl < ' a , T : TypeNum , D : Dimension > FromPyObject < ' a > for & ' a PyArray < T , D > {
120
+ impl < ' a , T : Element , D : Dimension > FromPyObject < ' a > for & ' a PyArray < T , D > {
121
121
// here we do type-check three times
122
122
// 1. Checks if the object is PyArray
123
123
// 2. Checks if the data type of the array is T
@@ -292,34 +292,27 @@ impl<T, D> PyArray<T, D> {
292
292
self . len ( ) == 0
293
293
}
294
294
295
- fn typenum ( & self ) -> i32 {
295
+ fn strides_usize ( & self ) -> & [ usize ] {
296
+ let n = self . ndim ( ) ;
297
+ let ptr = self . as_array_ptr ( ) ;
296
298
unsafe {
297
- let descr = ( * self . as_array_ptr ( ) ) . descr ;
298
- ( * descr ) . type_num
299
+ let p = ( * ptr ) . strides ;
300
+ slice :: from_raw_parts ( p as * const _ , n )
299
301
}
300
302
}
301
303
302
304
/// Returns the pointer to the first element of the inner array.
303
305
pub ( crate ) unsafe fn data ( & self ) -> * mut T {
304
306
let ptr = self . as_array_ptr ( ) ;
305
- ( * ptr) . data as * mut T
307
+ ( * ptr) . data as * mut _
306
308
}
307
309
308
310
pub ( crate ) unsafe fn copy_ptr ( & self , other : * const T , len : usize ) {
309
311
ptr:: copy_nonoverlapping ( other, self . data ( ) , len)
310
312
}
311
-
312
- fn strides_usize ( & self ) -> & [ usize ] {
313
- let n = self . ndim ( ) ;
314
- let ptr = self . as_array_ptr ( ) ;
315
- unsafe {
316
- let p = ( * ptr) . strides ;
317
- slice:: from_raw_parts ( p as * const _ , n)
318
- }
319
- }
320
313
}
321
314
322
- impl < T : TypeNum , D : Dimension > PyArray < T , D > {
315
+ impl < T : Element , D : Dimension > PyArray < T , D > {
323
316
/// Same as [shape](#method.shape), but returns `D`
324
317
#[ inline( always) ]
325
318
pub fn dims ( & self ) -> D {
@@ -369,7 +362,7 @@ impl<T: TypeNum, D: Dimension> PyArray<T, D> {
369
362
PY_ARRAY_API . get_type_object ( npyffi:: ArrayType :: PyArray_Type ) ,
370
363
dims. ndim_cint ( ) ,
371
364
dims. as_dims_ptr ( ) ,
372
- T :: typenum_default ( ) ,
365
+ T :: ffi_dtype ( ) as i32 ,
373
366
strides as * mut _ , // strides
374
367
ptr:: null_mut ( ) , // data
375
368
0 , // itemsize
@@ -398,7 +391,7 @@ impl<T: TypeNum, D: Dimension> PyArray<T, D> {
398
391
PY_ARRAY_API . get_type_object ( npyffi:: ArrayType :: PyArray_Type ) ,
399
392
dims. ndim_cint ( ) ,
400
393
dims. as_dims_ptr ( ) ,
401
- T :: typenum_default ( ) ,
394
+ T :: ffi_dtype ( ) as i32 ,
402
395
strides as * mut _ , // strides
403
396
data_ptr as _ , // data
404
397
mem:: size_of :: < T > ( ) as i32 , // itemsize
@@ -430,7 +423,7 @@ impl<T: TypeNum, D: Dimension> PyArray<T, D> {
430
423
{
431
424
let dims = dims. into_dimension ( ) ;
432
425
unsafe {
433
- let descr = PY_ARRAY_API . PyArray_DescrFromType ( T :: typenum_default ( ) ) ;
426
+ let descr = PY_ARRAY_API . PyArray_DescrFromType ( T :: ffi_dtype ( ) as i32 ) ;
434
427
let ptr = PY_ARRAY_API . PyArray_Zeros (
435
428
dims. ndim_cint ( ) ,
436
429
dims. as_dims_ptr ( ) ,
@@ -480,26 +473,6 @@ impl<T: TypeNum, D: Dimension> PyArray<T, D> {
480
473
}
481
474
}
482
475
483
- /// Construct PyArray from `ndarray::ArrayBase`.
484
- ///
485
- /// This method allocates memory in Python's heap via numpy api, and then copies all elements
486
- /// of the array there.
487
- ///
488
- /// # Example
489
- /// ```
490
- /// # #[macro_use] extern crate ndarray;
491
- /// use numpy::PyArray;
492
- /// let gil = pyo3::Python::acquire_gil();
493
- /// let pyarray = PyArray::from_array(gil.python(), &array![[1, 2], [3, 4]]);
494
- /// assert_eq!(pyarray.readonly().as_array(), array![[1, 2], [3, 4]]);
495
- /// ```
496
- pub fn from_array < ' py , S > ( py : Python < ' py > , arr : & ArrayBase < S , D > ) -> & ' py Self
497
- where
498
- S : Data < Elem = T > ,
499
- {
500
- ToPyArray :: to_pyarray ( arr, py)
501
- }
502
-
503
476
/// Construct PyArray from
504
477
/// [`ndarray::Array`](https://docs.rs/ndarray/latest/ndarray/type.Array.html).
505
478
///
@@ -518,25 +491,6 @@ impl<T: TypeNum, D: Dimension> PyArray<T, D> {
518
491
IntoPyArray :: into_pyarray ( arr, py)
519
492
}
520
493
521
- /// Get the immutable view of the internal data of `PyArray`, as
522
- /// [`ndarray::ArrayView`](https://docs.rs/ndarray/latest/ndarray/type.ArrayView.html).
523
- ///
524
- /// # Safety
525
- /// If the internal array is not readonly and can be mutated from Python code,
526
- /// holding the `ArrayView` might cause undefined behavior.
527
- pub unsafe fn as_array ( & self ) -> ArrayView < ' _ , T , D > {
528
- ArrayView :: from_shape_ptr ( self . ndarray_shape ( ) , self . data ( ) )
529
- }
530
-
531
- /// Returns the internal array as `ArrayViewMut`. See also [`as_array`](#method.as_array).
532
- ///
533
- /// # Safety
534
- /// If another reference to the internal data exists(e.g., `&[T]` or `ArrayView`),
535
- /// it might cause undefined behavior.
536
- pub unsafe fn as_array_mut ( & self ) -> ArrayViewMut < ' _ , T , D > {
537
- ArrayViewMut :: from_shape_ptr ( self . ndarray_shape ( ) , self . data ( ) )
538
- }
539
-
540
494
/// Get an immutable reference of a specified element, with checking the passed index is valid.
541
495
///
542
496
/// See [NpyIndex](../convert/trait.NpyIndex.html) for what types you can use as index.
@@ -608,7 +562,7 @@ impl<T: TypeNum, D: Dimension> PyArray<T, D> {
608
562
Idx : NpyIndex < Dim = D > ,
609
563
{
610
564
let offset = index. get_unchecked :: < T > ( self . strides ( ) ) ;
611
- & mut * ( self . data ( ) . offset ( offset) as * mut T )
565
+ & mut * ( self . data ( ) . offset ( offset) as * mut _ )
612
566
}
613
567
614
568
/// Get dynamic dimensioned array from fixed dimension array.
@@ -620,35 +574,14 @@ impl<T: TypeNum, D: Dimension> PyArray<T, D> {
620
574
}
621
575
622
576
fn type_check ( & self ) -> Result < ( ) , ShapeError > {
623
- let truth = self . typenum ( ) ;
577
+ let truth = unsafe { ( * ( * self . as_array_ptr ( ) ) . descr ) . type_num } ;
624
578
let dim = self . shape ( ) . len ( ) ;
625
- let dim_ok = D :: NDIM . map ( |n| n == dim) . unwrap_or ( true ) ;
626
- if T :: is_same_type ( truth) && dim_ok {
579
+ if T :: is_same_type ( truth) && D :: NDIM . map ( |n| n == dim) . unwrap_or ( true ) {
627
580
Ok ( ( ) )
628
581
} else {
629
- Err ( ShapeError :: new ( truth, dim, T :: npy_data_type ( ) , D :: NDIM ) )
582
+ Err ( ShapeError :: new ( truth, dim, T :: DATA_TYPE , D :: NDIM ) )
630
583
}
631
584
}
632
- }
633
-
634
- impl < T : Clone + TypeNum , D : Dimension > PyArray < T , D > {
635
- /// Get a copy of `PyArray` as
636
- /// [`ndarray::Array`](https://docs.rs/ndarray/latest/ndarray/type.Array.html).
637
- ///
638
- /// # Example
639
- /// ```
640
- /// # #[macro_use] extern crate ndarray;
641
- /// use numpy::PyArray;
642
- /// let gil = pyo3::Python::acquire_gil();
643
- /// let py_array = PyArray::arange(gil.python(), 0, 4, 1).reshape([2, 2]).unwrap();
644
- /// assert_eq!(
645
- /// py_array.to_owned_array(),
646
- /// array![[0, 1], [2, 3]]
647
- /// )
648
- /// ```
649
- pub fn to_owned_array ( & self ) -> Array < T , D > {
650
- unsafe { self . as_array ( ) } . to_owned ( )
651
- }
652
585
653
586
/// Returns the copy of the internal data of `PyArray` to `Vec`.
654
587
///
@@ -672,9 +605,66 @@ impl<T: Clone + TypeNum, D: Dimension> PyArray<T, D> {
672
605
pub fn to_vec ( & self ) -> Result < Vec < T > , NotContiguousError > {
673
606
unsafe { self . as_slice ( ) } . map ( ToOwned :: to_owned)
674
607
}
608
+
609
+ /// Construct PyArray from `ndarray::ArrayBase`.
610
+ ///
611
+ /// This method allocates memory in Python's heap via numpy api, and then copies all elements
612
+ /// of the array there.
613
+ ///
614
+ /// # Example
615
+ /// ```
616
+ /// # #[macro_use] extern crate ndarray;
617
+ /// use numpy::PyArray;
618
+ /// let gil = pyo3::Python::acquire_gil();
619
+ /// let pyarray = PyArray::from_array(gil.python(), &array![[1, 2], [3, 4]]);
620
+ /// assert_eq!(pyarray.readonly().as_array(), array![[1, 2], [3, 4]]);
621
+ /// ```
622
+ pub fn from_array < ' py , S > ( py : Python < ' py > , arr : & ArrayBase < S , D > ) -> & ' py Self
623
+ where
624
+ S : Data < Elem = T > ,
625
+ {
626
+ ToPyArray :: to_pyarray ( arr, py)
627
+ }
628
+
629
+ /// Get the immutable view of the internal data of `PyArray`, as
630
+ /// [`ndarray::ArrayView`](https://docs.rs/ndarray/latest/ndarray/type.ArrayView.html).
631
+ ///
632
+ /// # Safety
633
+ /// If the internal array is not readonly and can be mutated from Python code,
634
+ /// holding the `ArrayView` might cause undefined behavior.
635
+ pub unsafe fn as_array ( & self ) -> ArrayView < ' _ , T , D > {
636
+ ArrayView :: from_shape_ptr ( self . ndarray_shape ( ) , self . data ( ) )
637
+ }
638
+
639
+ /// Returns the internal array as `ArrayViewMut`. See also [`as_array`](#method.as_array).
640
+ ///
641
+ /// # Safety
642
+ /// If another reference to the internal data exists(e.g., `&[T]` or `ArrayView`),
643
+ /// it might cause undefined behavior.
644
+ pub unsafe fn as_array_mut ( & self ) -> ArrayViewMut < ' _ , T , D > {
645
+ ArrayViewMut :: from_shape_ptr ( self . ndarray_shape ( ) , self . data ( ) )
646
+ }
647
+
648
+ /// Get a copy of `PyArray` as
649
+ /// [`ndarray::Array`](https://docs.rs/ndarray/latest/ndarray/type.Array.html).
650
+ ///
651
+ /// # Example
652
+ /// ```
653
+ /// # #[macro_use] extern crate ndarray;
654
+ /// use numpy::PyArray;
655
+ /// let gil = pyo3::Python::acquire_gil();
656
+ /// let py_array = PyArray::arange(gil.python(), 0, 4, 1).reshape([2, 2]).unwrap();
657
+ /// assert_eq!(
658
+ /// py_array.to_owned_array(),
659
+ /// array![[0, 1], [2, 3]]
660
+ /// )
661
+ /// ```
662
+ pub fn to_owned_array ( & self ) -> Array < T , D > {
663
+ unsafe { self . as_array ( ) } . to_owned ( )
664
+ }
675
665
}
676
666
677
- impl < T : TypeNum > PyArray < T , Ix1 > {
667
+ impl < T : Element > PyArray < T , Ix1 > {
678
668
/// Construct one-dimension PyArray from slice.
679
669
///
680
670
/// # Example
@@ -808,7 +798,7 @@ impl<T: TypeNum> PyArray<T, Ix1> {
808
798
}
809
799
}
810
800
811
- impl < T : TypeNum > PyArray < T , Ix2 > {
801
+ impl < T : Element > PyArray < T , Ix2 > {
812
802
/// Construct a two-dimension PyArray from `Vec<Vec<T>>`.
813
803
///
814
804
/// This function checks all dimension of inner vec, and if there's any vec
@@ -824,10 +814,7 @@ impl<T: TypeNum> PyArray<T, Ix2> {
824
814
/// assert_eq!(pyarray.readonly().as_array(), array![[1, 2, 3], [1, 2, 3]]);
825
815
/// assert!(PyArray::from_vec2(gil.python(), &[vec![1], vec![2, 3]]).is_err());
826
816
/// ```
827
- pub fn from_vec2 < ' py > ( py : Python < ' py > , v : & [ Vec < T > ] ) -> Result < & ' py Self , FromVecError >
828
- where
829
- T : Clone ,
830
- {
817
+ pub fn from_vec2 < ' py > ( py : Python < ' py > , v : & [ Vec < T > ] ) -> Result < & ' py Self , FromVecError > {
831
818
let last_len = v. last ( ) . map_or ( 0 , |v| v. len ( ) ) ;
832
819
if v. iter ( ) . any ( |v| v. len ( ) != last_len) {
833
820
return Err ( FromVecError :: new ( v. len ( ) , last_len) ) ;
@@ -837,15 +824,15 @@ impl<T: TypeNum> PyArray<T, Ix2> {
837
824
unsafe {
838
825
for ( y, vy) in v. iter ( ) . enumerate ( ) {
839
826
for ( x, vyx) in vy. iter ( ) . enumerate ( ) {
840
- * array. uget_mut ( [ y, x] ) = * vyx;
827
+ * array. uget_mut ( [ y, x] ) = vyx. clone ( ) ;
841
828
}
842
829
}
843
830
}
844
831
Ok ( array)
845
832
}
846
833
}
847
834
848
- impl < T : TypeNum > PyArray < T , Ix3 > {
835
+ impl < T : Element > PyArray < T , Ix3 > {
849
836
/// Construct a three-dimension PyArray from `Vec<Vec<Vec<T>>>`.
850
837
///
851
838
/// This function checks all dimension of inner vec, and if there's any vec
@@ -864,10 +851,7 @@ impl<T: TypeNum> PyArray<T, Ix3> {
864
851
/// );
865
852
/// assert!(PyArray::from_vec3(gil.python(), &[vec![vec![1], vec![]]]).is_err());
866
853
/// ```
867
- pub fn from_vec3 < ' py > ( py : Python < ' py > , v : & [ Vec < Vec < T > > ] ) -> Result < & ' py Self , FromVecError >
868
- where
869
- T : Clone ,
870
- {
854
+ pub fn from_vec3 < ' py > ( py : Python < ' py > , v : & [ Vec < Vec < T > > ] ) -> Result < & ' py Self , FromVecError > {
871
855
let len2 = v. last ( ) . map_or ( 0 , |v| v. len ( ) ) ;
872
856
if v. iter ( ) . any ( |v| v. len ( ) != len2) {
873
857
return Err ( FromVecError :: new ( v. len ( ) , len2) ) ;
@@ -882,7 +866,7 @@ impl<T: TypeNum> PyArray<T, Ix3> {
882
866
for ( z, vz) in v. iter ( ) . enumerate ( ) {
883
867
for ( y, vzy) in vz. iter ( ) . enumerate ( ) {
884
868
for ( x, vzyx) in vzy. iter ( ) . enumerate ( ) {
885
- * array. uget_mut ( [ z, y, x] ) = * vzyx;
869
+ * array. uget_mut ( [ z, y, x] ) = vzyx. clone ( ) ;
886
870
}
887
871
}
888
872
}
@@ -891,12 +875,7 @@ impl<T: TypeNum> PyArray<T, Ix3> {
891
875
}
892
876
}
893
877
894
- impl < T : TypeNum , D > PyArray < T , D > {
895
- /// Returns the scalar type of the array.
896
- pub fn data_type ( & self ) -> NpyDataType {
897
- NpyDataType :: from_i32 ( self . typenum ( ) )
898
- }
899
-
878
+ impl < T : Element , D > PyArray < T , D > {
900
879
/// Copies self into `other`, performing a data-type conversion if necessary.
901
880
/// # Example
902
881
/// ```
@@ -907,7 +886,7 @@ impl<T: TypeNum, D> PyArray<T, D> {
907
886
/// assert!(pyarray_f.copy_to(pyarray_i).is_ok());
908
887
/// assert_eq!(pyarray_i.readonly().as_slice().unwrap(), &[2, 3, 4]);
909
888
/// ```
910
- pub fn copy_to < U : TypeNum > ( & self , other : & PyArray < U , D > ) -> PyResult < ( ) > {
889
+ pub fn copy_to < U : Element > ( & self , other : & PyArray < U , D > ) -> PyResult < ( ) > {
911
890
let self_ptr = self . as_array_ptr ( ) ;
912
891
let other_ptr = other. as_array_ptr ( ) ;
913
892
let result = unsafe { PY_ARRAY_API . PyArray_CopyInto ( other_ptr, self_ptr) } ;
@@ -926,9 +905,9 @@ impl<T: TypeNum, D> PyArray<T, D> {
926
905
/// let pyarray_f = PyArray::arange(gil.python(), 2.0, 5.0, 1.0);
927
906
/// let pyarray_i = pyarray_f.cast::<i32>(false).unwrap();
928
907
/// assert_eq!(pyarray_i.readonly().as_slice().unwrap(), &[2, 3, 4]);
929
- pub fn cast < ' py , U : TypeNum > ( & ' py self , is_fortran : bool ) -> PyResult < & ' py PyArray < U , D > > {
908
+ pub fn cast < ' py , U : Element > ( & ' py self , is_fortran : bool ) -> PyResult < & ' py PyArray < U , D > > {
930
909
let ptr = unsafe {
931
- let descr = PY_ARRAY_API . PyArray_DescrFromType ( U :: typenum_default ( ) ) ;
910
+ let descr = PY_ARRAY_API . PyArray_DescrFromType ( U :: ffi_dtype ( ) as i32 ) ;
932
911
PY_ARRAY_API . PyArray_CastToType (
933
912
self . as_array_ptr ( ) ,
934
913
descr,
@@ -995,7 +974,7 @@ impl<T: TypeNum, D> PyArray<T, D> {
995
974
}
996
975
}
997
976
998
- impl < T : TypeNum + AsPrimitive < f64 > > PyArray < T , Ix1 > {
977
+ impl < T : Element + AsPrimitive < f64 > > PyArray < T , Ix1 > {
999
978
/// Return evenly spaced values within a given interval.
1000
979
/// Same as [numpy.arange](https://numpy.org/doc/stable/reference/generated/numpy.arange.html).
1001
980
///
@@ -1015,7 +994,7 @@ impl<T: TypeNum + AsPrimitive<f64>> PyArray<T, Ix1> {
1015
994
start. as_ ( ) ,
1016
995
stop. as_ ( ) ,
1017
996
step. as_ ( ) ,
1018
- T :: typenum_default ( ) ,
997
+ T :: ffi_dtype ( ) as i32 ,
1019
998
) ;
1020
999
Self :: from_owned_ptr ( py, ptr)
1021
1000
}
0 commit comments