1- //! Implements conversion utitlities.
2- /// alias of Complex32
1+ use crate :: npyffi:: { NpyTypes , PyArray_Descr , NPY_TYPES , PY_ARRAY_API } ;
32pub use num_complex:: Complex32 as c32;
4- /// alias of Complex64
53pub use num_complex:: Complex64 as c64;
4+ use pyo3:: ffi;
5+ use pyo3:: prelude:: * ;
6+ use pyo3:: types:: PyType ;
7+ use pyo3:: { AsPyPointer , PyNativeType } ;
8+ use std:: os:: raw:: c_int;
69
7- use super :: npyffi:: NPY_TYPES ;
10+ /// Binding of [`numpy.dtype`](https://numpy.org/doc/stable/reference/generated/numpy.dtype.html).
11+ ///
12+ /// # Example
13+ /// ```
14+ /// use pyo3::types::IntoPyDict;
15+ /// pyo3::Python::with_gil(|py| {
16+ /// let locals = [("np", numpy::get_array_module(py).unwrap())].into_py_dict(py);
17+ /// let dtype: &numpy::PyArrayDescr = py
18+ /// .eval("np.array([1, 2, 3.0]).dtype", Some(locals), None)
19+ /// .unwrap()
20+ /// .downcast()
21+ /// .unwrap();
22+ /// assert_eq!(dtype.get_datatype().unwrap(), numpy::DataType::Float64);
23+ /// });
24+ /// ```
25+ pub struct PyArrayDescr ( PyAny ) ;
26+
27+ pyobject_native_type_core ! (
28+ PyArrayDescr ,
29+ PyArray_Descr ,
30+ * PY_ARRAY_API . get_type_object( NpyTypes :: PyArrayDescr_Type ) ,
31+ Some ( "numpy" ) ,
32+ arraydescr_check
33+ ) ;
34+
35+ pyobject_native_type_fmt ! ( PyArrayDescr ) ;
36+
37+ unsafe fn arraydescr_check ( op : * mut ffi:: PyObject ) -> c_int {
38+ ffi:: PyObject_TypeCheck (
39+ op,
40+ PY_ARRAY_API . get_type_object ( NpyTypes :: PyArrayDescr_Type ) ,
41+ )
42+ }
43+
44+ impl PyArrayDescr {
45+ /// Returns `self` as `*mut PyArray_Descr`.
46+ pub fn as_dtype_ptr ( & self ) -> * mut PyArray_Descr {
47+ self . as_ptr ( ) as _
48+ }
849
9- /// An enum type represents numpy data type.
50+ /// Returns the internal `PyType` that this `dtype` holds.
51+ ///
52+ /// # Example
53+ /// ```
54+ /// pyo3::Python::with_gil(|py| {
55+ /// let array = numpy::PyArray::from_vec(py, vec![0.0, 1.0, 2.0f64]);
56+ /// let dtype = array.dtype();
57+ /// assert_eq!(dtype.get_type().name().to_string(), "numpy.float64");
58+ /// });
59+ /// ```
60+ pub fn get_type ( & self ) -> & PyType {
61+ let dtype_type_ptr = unsafe { * self . as_dtype_ptr ( ) } . typeobj ;
62+ unsafe { PyType :: from_type_ptr ( self . py ( ) , dtype_type_ptr) }
63+ }
64+
65+ /// Returns the data type as `DataType` enum.
66+ pub fn get_datatype ( & self ) -> Option < DataType > {
67+ DataType :: from_typenum ( self . get_typenum ( ) )
68+ }
69+
70+ fn from_npy_type ( py : Python , npy_type : NPY_TYPES ) -> & Self {
71+ unsafe {
72+ let descr = PY_ARRAY_API . PyArray_DescrFromType ( npy_type as i32 ) ;
73+ py. from_owned_ptr ( descr as _ )
74+ }
75+ }
76+
77+ fn get_typenum ( & self ) -> std:: os:: raw:: c_int {
78+ unsafe { * self . as_dtype_ptr ( ) } . type_num
79+ }
80+ }
81+
82+ /// Represents numpy data type.
1083///
11- /// This type is mainly for displaying error, and user don't have to use it directly.
84+ /// This is an incomplete counterpart of
85+ /// [Enumerated Types](https://numpy.org/doc/stable/reference/c-api/dtype.html#enumerated-types)
86+ /// in numpy C-API.
1287#[ derive( Clone , Debug , Eq , PartialEq ) ]
1388pub enum DataType {
1489 Bool ,
@@ -28,8 +103,10 @@ pub enum DataType {
28103}
29104
30105impl DataType {
31- pub ( crate ) fn from_i32 ( npy_t : i32 ) -> Option < Self > {
32- Some ( match npy_t {
106+ /// Construct `DataType` from
107+ /// [Enumerated Types](https://numpy.org/doc/stable/reference/c-api/dtype.html#enumerated-types).
108+ pub fn from_typenum ( typenum : c_int ) -> Option < Self > {
109+ Some ( match typenum {
33110 x if x == NPY_TYPES :: NPY_BOOL as i32 => DataType :: Bool ,
34111 x if x == NPY_TYPES :: NPY_BYTE as i32 => DataType :: Int8 ,
35112 x if x == NPY_TYPES :: NPY_SHORT as i32 => DataType :: Int16 ,
@@ -49,6 +126,28 @@ impl DataType {
49126 _ => return None ,
50127 } )
51128 }
129+
130+ /// Convert `self` into
131+ /// [Enumerated Types](https://numpy.org/doc/stable/reference/c-api/dtype.html#enumerated-types).
132+ pub fn into_ctype ( self ) -> NPY_TYPES {
133+ match self {
134+ DataType :: Bool => NPY_TYPES :: NPY_BOOL ,
135+ DataType :: Int8 => NPY_TYPES :: NPY_BYTE ,
136+ DataType :: Int16 => NPY_TYPES :: NPY_SHORT ,
137+ DataType :: Int32 => NPY_TYPES :: NPY_INT ,
138+ DataType :: Int64 => NPY_TYPES :: NPY_LONGLONG ,
139+ DataType :: Uint8 => NPY_TYPES :: NPY_UBYTE ,
140+ DataType :: Uint16 => NPY_TYPES :: NPY_USHORT ,
141+ DataType :: Uint32 => NPY_TYPES :: NPY_UINT ,
142+ DataType :: Uint64 => NPY_TYPES :: NPY_ULONGLONG ,
143+ DataType :: Float32 => NPY_TYPES :: NPY_FLOAT ,
144+ DataType :: Float64 => NPY_TYPES :: NPY_DOUBLE ,
145+ DataType :: Complex32 => NPY_TYPES :: NPY_CFLOAT ,
146+ DataType :: Complex64 => NPY_TYPES :: NPY_CDOUBLE ,
147+ DataType :: Object => NPY_TYPES :: NPY_OBJECT ,
148+ }
149+ }
150+
52151 #[ inline( always) ]
53152 fn from_clong ( is_usize : bool ) -> Option < Self > {
54153 if cfg ! ( any( target_pointer_width = "32" , windows) ) {
@@ -67,43 +166,35 @@ impl DataType {
67166 None
68167 }
69168 }
70- #[ inline]
71- pub fn into_ffi_dtype ( self ) -> NPY_TYPES {
72- match self {
73- DataType :: Bool => NPY_TYPES :: NPY_BOOL ,
74- DataType :: Int8 => NPY_TYPES :: NPY_BYTE ,
75- DataType :: Int16 => NPY_TYPES :: NPY_SHORT ,
76- DataType :: Int32 => NPY_TYPES :: NPY_INT ,
77- DataType :: Int64 => NPY_TYPES :: NPY_LONGLONG ,
78- DataType :: Uint8 => NPY_TYPES :: NPY_UBYTE ,
79- DataType :: Uint16 => NPY_TYPES :: NPY_USHORT ,
80- DataType :: Uint32 => NPY_TYPES :: NPY_UINT ,
81- DataType :: Uint64 => NPY_TYPES :: NPY_ULONGLONG ,
82- DataType :: Float32 => NPY_TYPES :: NPY_FLOAT ,
83- DataType :: Float64 => NPY_TYPES :: NPY_DOUBLE ,
84- DataType :: Complex32 => NPY_TYPES :: NPY_CFLOAT ,
85- DataType :: Complex64 => NPY_TYPES :: NPY_CDOUBLE ,
86- DataType :: Object => NPY_TYPES :: NPY_OBJECT ,
87- }
88- }
89169}
90170
91171/// Represents that a type can be an element of `PyArray`.
92172pub trait Element : Clone {
173+ /// `DataType` corresponding to this type.
93174 const DATA_TYPE : DataType ;
94- fn is_same_type ( other : i32 ) -> bool ;
175+
176+ /// Returns if the give `dtype` is convertible to `Self` in Rust.
177+ fn is_same_type ( dtype : & PyArrayDescr ) -> bool ;
178+
179+ /// Returns the corresponding
180+ /// [Enumerated Type](https://numpy.org/doc/stable/reference/c-api/dtype.html#enumerated-types).
95181 #[ inline]
96- fn ffi_dtype ( ) -> NPY_TYPES {
97- Self :: DATA_TYPE . into_ffi_dtype ( )
182+ fn npy_type ( ) -> NPY_TYPES {
183+ Self :: DATA_TYPE . into_ctype ( )
184+ }
185+
186+ /// Create `dtype`.
187+ fn get_dtype ( py : Python ) -> & PyArrayDescr {
188+ PyArrayDescr :: from_npy_type ( py, Self :: npy_type ( ) )
98189 }
99190}
100191
101192macro_rules! impl_num_element {
102193 ( $t: ty, $npy_dat_t: ident $( , $npy_types: ident) +) => {
103194 impl Element for $t {
104195 const DATA_TYPE : DataType = DataType :: $npy_dat_t;
105- fn is_same_type( other : i32 ) -> bool {
106- $( other == NPY_TYPES :: $npy_types as i32 ||) + false
196+ fn is_same_type( dtype : & PyArrayDescr ) -> bool {
197+ $( dtype . get_typenum ( ) == NPY_TYPES :: $npy_types as i32 ||) + false
107198 }
108199 }
109200 } ;
0 commit comments