1
- //! Implements conversion utitlities.
2
- /// alias of Complex32
1
+ use crate :: npyffi:: { NpyTypes , PyArray_Descr , NPY_TYPES , PY_ARRAY_API } ;
3
2
pub use num_complex:: Complex32 as c32;
4
- /// alias of Complex64
5
3
pub 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;
6
9
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
+ }
8
49
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.
10
83
///
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.
12
87
#[ derive( Clone , Debug , Eq , PartialEq ) ]
13
88
pub enum DataType {
14
89
Bool ,
@@ -28,8 +103,10 @@ pub enum DataType {
28
103
}
29
104
30
105
impl 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 {
33
110
x if x == NPY_TYPES :: NPY_BOOL as i32 => DataType :: Bool ,
34
111
x if x == NPY_TYPES :: NPY_BYTE as i32 => DataType :: Int8 ,
35
112
x if x == NPY_TYPES :: NPY_SHORT as i32 => DataType :: Int16 ,
@@ -49,6 +126,28 @@ impl DataType {
49
126
_ => return None ,
50
127
} )
51
128
}
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
+
52
151
#[ inline( always) ]
53
152
fn from_clong ( is_usize : bool ) -> Option < Self > {
54
153
if cfg ! ( any( target_pointer_width = "32" , windows) ) {
@@ -67,43 +166,35 @@ impl DataType {
67
166
None
68
167
}
69
168
}
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
- }
89
169
}
90
170
91
171
/// Represents that a type can be an element of `PyArray`.
92
172
pub trait Element : Clone {
173
+ /// `DataType` corresponding to this type.
93
174
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).
95
181
#[ 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 ( ) )
98
189
}
99
190
}
100
191
101
192
macro_rules! impl_num_element {
102
193
( $t: ty, $npy_dat_t: ident $( , $npy_types: ident) +) => {
103
194
impl Element for $t {
104
195
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
107
198
}
108
199
}
109
200
} ;
0 commit comments