numpy.hpp
Go to the documentation of this file.
1 /*
2  * Copyright 2020-2024 INRIA
3  */
4 
5 #ifndef __eigenpy_numpy_hpp__
6 #define __eigenpy_numpy_hpp__
7 
8 #include "eigenpy/config.hpp"
9 
10 #ifndef PY_ARRAY_UNIQUE_SYMBOL
11 #define PY_ARRAY_UNIQUE_SYMBOL EIGENPY_ARRAY_API
12 #endif
13 
14 // For compatibility with Numpy 2.x. See:
15 // https://numpy.org/devdocs/reference/c-api/array.html#c.NPY_API_SYMBOL_ATTRIBUTE
16 #define NPY_API_SYMBOL_ATTRIBUTE EIGENPY_DLLAPI
17 
18 // When building with MSVC, Python headers use some pragma operator to link
19 // against the Python DLL.
20 // Unfortunately, it can link against the wrong build type of the library
21 // leading to some linking issue.
22 // Boost::Python provides a helper specifically dedicated to selecting the right
23 // Python library depending on build type, so let's make use of it.
24 // Numpy headers drags Python with them. As a result, it
25 // is necessary to include this helper before including Numpy.
26 // See: https://github.com/stack-of-tasks/eigenpy/pull/514
27 #include <boost/python/detail/wrap_python.hpp>
28 
29 #include <numpy/numpyconfig.h>
30 #ifdef NPY_1_8_API_VERSION
31 #define NPY_NO_DEPRECATED_API NPY_1_7_API_VERSION
32 #endif
33 
34 // Allow compiling against NumPy 1.x and 2.x. See:
35 // https://github.com/numpy/numpy/blob/afea8fd66f6bdbde855f5aff0b4e73eb0213c646/doc/source/reference/c-api/array.rst#L1224
36 #if NPY_ABI_VERSION < 0x02000000
37 #define PyArray_DescrProto PyArray_Descr
38 #endif
39 
40 #include <numpy/ndarrayobject.h>
41 #include <numpy/ufuncobject.h>
42 
43 #if NPY_ABI_VERSION < 0x02000000
44 static inline PyArray_ArrFuncs* PyDataType_GetArrFuncs(PyArray_Descr* descr) {
45  return descr->f;
46 }
47 #endif
48 
49 /* PEP 674 disallow using macros as l-values
50  see : https://peps.python.org/pep-0674/
51 */
52 #if PY_VERSION_HEX < 0x030900A4 && !defined(Py_SET_TYPE)
53 static inline void _Py_SET_TYPE(PyObject* o, PyTypeObject* type) {
54  Py_TYPE(o) = type;
55 }
56 #define Py_SET_TYPE(o, type) _Py_SET_TYPE((PyObject*)(o), type)
57 #endif
58 
59 #if defined _WIN32 || defined __CYGWIN__
60 #define EIGENPY_GET_PY_ARRAY_TYPE(array) \
61  call_PyArray_MinScalarType(array)->type_num
62 #else
63 #define EIGENPY_GET_PY_ARRAY_TYPE(array) PyArray_MinScalarType(array)->type_num
64 #endif
65 
66 #include <complex>
67 
68 namespace eigenpy {
69 void EIGENPY_DLLAPI import_numpy();
70 int EIGENPY_DLLAPI PyArray_TypeNum(PyTypeObject* type);
71 
72 // By default, the Scalar is considered as a Python object
73 template <typename Scalar, typename Enable = void>
75  enum { type_code = NPY_USERDEF };
76 };
77 
78 template <>
79 struct NumpyEquivalentType<bool> {
80  enum { type_code = NPY_BOOL };
81 };
82 
83 template <>
84 struct NumpyEquivalentType<char> {
85  enum { type_code = NPY_INT8 };
86 };
87 template <>
88 struct NumpyEquivalentType<unsigned char> {
89  enum { type_code = NPY_UINT8 };
90 };
91 template <>
93  enum { type_code = NPY_INT8 };
94 };
95 
96 template <>
98  enum { type_code = NPY_INT16 };
99 };
100 template <>
102  enum { type_code = NPY_UINT16 };
103 };
104 
105 template <>
107  enum { type_code = NPY_INT32 };
108 };
109 template <>
111  enum { type_code = NPY_UINT32 };
112 };
113 
114 // On Windows, long is a 32 bytes type but it's a different type than int
115 // See https://github.com/stack-of-tasks/eigenpy/pull/455
116 #if defined _WIN32 || defined __CYGWIN__
117 
118 template <>
119 struct NumpyEquivalentType<long> {
120  enum { type_code = NPY_INT32 };
121 };
122 template <>
123 struct NumpyEquivalentType<unsigned long> {
124  enum { type_code = NPY_UINT32 };
125 };
126 
127 #endif // WIN32
128 
129 template <>
131  enum { type_code = NPY_INT64 };
132 };
133 template <>
135  enum { type_code = NPY_UINT64 };
136 };
137 
138 // On Mac, long is a 64 bytes type but it's a different type than int64_t
139 // See https://github.com/stack-of-tasks/eigenpy/pull/455
140 #if defined __APPLE__
141 
142 template <>
143 struct NumpyEquivalentType<long> {
144  enum { type_code = NPY_INT64 };
145 };
146 template <>
147 struct NumpyEquivalentType<unsigned long> {
148  enum { type_code = NPY_UINT64 };
149 };
150 
151 #endif // MAC
152 
153 // On Linux, long long is a 64 bytes type but it's a different type than int64_t
154 // See https://github.com/stack-of-tasks/eigenpy/pull/455
155 #if defined __linux__
156 
157 #include <type_traits>
158 
159 template <typename Scalar>
160 struct NumpyEquivalentType<
161  Scalar,
162  typename std::enable_if<!std::is_same<int64_t, long long>::value &&
163  std::is_same<Scalar, long long>::value>::type> {
164  enum { type_code = NPY_LONGLONG };
165 };
166 template <typename Scalar>
167 struct NumpyEquivalentType<
168  Scalar, typename std::enable_if<
169  !std::is_same<uint64_t, unsigned long long>::value &&
170  std::is_same<Scalar, unsigned long long>::value>::type> {
171  enum { type_code = NPY_ULONGLONG };
172 };
173 
174 #endif // Linux
175 
176 template <>
177 struct NumpyEquivalentType<float> {
178  enum { type_code = NPY_FLOAT };
179 };
180 template <>
181 struct NumpyEquivalentType<double> {
182  enum { type_code = NPY_DOUBLE };
183 };
184 template <>
185 struct NumpyEquivalentType<long double> {
186  enum { type_code = NPY_LONGDOUBLE };
187 };
188 
189 template <>
190 struct NumpyEquivalentType<std::complex<float> > {
191  enum { type_code = NPY_CFLOAT };
192 };
193 template <>
194 struct NumpyEquivalentType<std::complex<double> > {
195  enum { type_code = NPY_CDOUBLE };
196 };
197 template <>
198 struct NumpyEquivalentType<std::complex<long double> > {
199  enum { type_code = NPY_CLONGDOUBLE };
200 };
201 
202 template <typename Scalar>
204  if ((int)NumpyEquivalentType<Scalar>::type_code == NPY_USERDEF) return false;
205  return true;
206 }
207 
208 } // namespace eigenpy
209 
210 namespace eigenpy {
211 #if defined _WIN32 || defined __CYGWIN__
212 EIGENPY_DLLAPI bool call_PyArray_Check(PyObject*);
213 
214 EIGENPY_DLLAPI PyObject* call_PyArray_SimpleNew(int nd, npy_intp* shape,
215  int np_type);
216 
217 EIGENPY_DLLAPI PyObject* call_PyArray_New(PyTypeObject* py_type_ptr, int nd,
218  npy_intp* shape, int np_type,
219  void* data_ptr, int options);
220 
221 EIGENPY_DLLAPI PyObject* call_PyArray_New(PyTypeObject* py_type_ptr, int nd,
222  npy_intp* shape, int np_type,
223  npy_intp* strides, void* data_ptr,
224  int options);
225 
226 EIGENPY_DLLAPI int call_PyArray_ObjectType(PyObject*, int);
227 
228 EIGENPY_DLLAPI PyTypeObject* getPyArrayType();
229 
230 EIGENPY_DLLAPI PyArray_Descr* call_PyArray_DescrFromType(int typenum);
231 
232 EIGENPY_DLLAPI void call_PyArray_InitArrFuncs(PyArray_ArrFuncs* funcs);
233 
234 EIGENPY_DLLAPI int call_PyArray_RegisterDataType(PyArray_DescrProto* dtype);
235 
236 EIGENPY_DLLAPI int call_PyArray_RegisterCanCast(PyArray_Descr* descr,
237  int totype,
238  NPY_SCALARKIND scalar);
239 
240 EIGENPY_DLLAPI PyArray_Descr* call_PyArray_MinScalarType(PyArrayObject* arr);
241 
242 EIGENPY_DLLAPI int call_PyArray_RegisterCastFunc(
243  PyArray_Descr* descr, int totype, PyArray_VectorUnaryFunc* castfunc);
244 #else
245 inline bool call_PyArray_Check(PyObject* py_obj) {
246  return PyArray_Check(py_obj);
247 }
248 
249 inline PyObject* call_PyArray_SimpleNew(int nd, npy_intp* shape, int np_type) {
250  return PyArray_SimpleNew(nd, shape, np_type);
251 }
252 
253 inline PyObject* call_PyArray_New(PyTypeObject* py_type_ptr, int nd,
254  npy_intp* shape, int np_type, void* data_ptr,
255  int options) {
256  return PyArray_New(py_type_ptr, nd, shape, np_type, NULL, data_ptr, 0,
257  options, NULL);
258 }
259 
260 inline PyObject* call_PyArray_New(PyTypeObject* py_type_ptr, int nd,
261  npy_intp* shape, int np_type,
262  npy_intp* strides, void* data_ptr,
263  int options) {
264  return PyArray_New(py_type_ptr, nd, shape, np_type, strides, data_ptr, 0,
265  options, NULL);
266 }
267 
268 inline int call_PyArray_ObjectType(PyObject* obj, int val) {
269  return PyArray_ObjectType(obj, val);
270 }
271 
272 inline PyTypeObject* getPyArrayType() { return &PyArray_Type; }
273 
274 inline PyArray_Descr* call_PyArray_DescrFromType(int typenum) {
275  return PyArray_DescrFromType(typenum);
276 }
277 
278 inline void call_PyArray_InitArrFuncs(PyArray_ArrFuncs* funcs) {
279  PyArray_InitArrFuncs(funcs);
280 }
281 
283  return PyArray_RegisterDataType(dtype);
284 }
285 
286 inline PyArray_Descr* call_PyArray_MinScalarType(PyArrayObject* arr) {
287  return PyArray_MinScalarType(arr);
288 }
289 
290 inline int call_PyArray_RegisterCanCast(PyArray_Descr* descr, int totype,
291  NPY_SCALARKIND scalar) {
292  return PyArray_RegisterCanCast(descr, totype, scalar);
293 }
294 
295 inline int call_PyArray_RegisterCastFunc(PyArray_Descr* descr, int totype,
296  PyArray_VectorUnaryFunc* castfunc) {
297  return PyArray_RegisterCastFunc(descr, totype, castfunc);
298 }
299 #endif
300 } // namespace eigenpy
301 
302 #endif // ifndef __eigenpy_numpy_hpp__
test_matrix.int32_t
int32_t
Definition: test_matrix.py:202
eigenpy::getPyArrayType
PyTypeObject * getPyArrayType()
Definition: numpy.hpp:272
eigenpy::PyArray_TypeNum
int EIGENPY_DLLAPI PyArray_TypeNum(PyTypeObject *type)
Definition: numpy.cpp:16
PyDataType_GetArrFuncs
static PyArray_ArrFuncs * PyDataType_GetArrFuncs(PyArray_Descr *descr)
Definition: numpy.hpp:44
eigenpy::call_PyArray_InitArrFuncs
void call_PyArray_InitArrFuncs(PyArray_ArrFuncs *funcs)
Definition: numpy.hpp:278
test_matrix.uint16_t
uint16_t
Definition: test_matrix.py:201
eigenpy::call_PyArray_DescrFromType
PyArray_Descr * call_PyArray_DescrFromType(int typenum)
Definition: numpy.hpp:274
eigenpy::isNumpyNativeType
bool isNumpyNativeType()
Definition: numpy.hpp:203
test_std_map.val
val
Definition: test_std_map.py:14
eigenpy::call_PyArray_RegisterDataType
int call_PyArray_RegisterDataType(PyArray_DescrProto *dtype)
Definition: numpy.hpp:282
test_matrix.uint32_t
uint32_t
Definition: test_matrix.py:203
eigenpy::import_numpy
void EIGENPY_DLLAPI import_numpy()
Definition: numpy.cpp:8
test_matrix.uint64_t
uint64_t
Definition: test_matrix.py:205
eigenpy::call_PyArray_Check
bool call_PyArray_Check(PyObject *py_obj)
Definition: numpy.hpp:245
eigenpy
Definition: alignment.hpp:14
eigenpy::call_PyArray_SimpleNew
PyObject * call_PyArray_SimpleNew(int nd, npy_intp *shape, int np_type)
Definition: numpy.hpp:249
eigenpy::call_PyArray_ObjectType
int call_PyArray_ObjectType(PyObject *obj, int val)
Definition: numpy.hpp:268
eigenpy::NumpyEquivalentType
Definition: numpy.hpp:74
test_matrix.int64_t
int64_t
Definition: test_matrix.py:204
eigenpy::call_PyArray_RegisterCanCast
int call_PyArray_RegisterCanCast(PyArray_Descr *descr, int totype, NPY_SCALARKIND scalar)
Definition: numpy.hpp:290
eigenpy::call_PyArray_MinScalarType
PyArray_Descr * call_PyArray_MinScalarType(PyArrayObject *arr)
Definition: numpy.hpp:286
eigenpy::call_PyArray_New
PyObject * call_PyArray_New(PyTypeObject *py_type_ptr, int nd, npy_intp *shape, int np_type, void *data_ptr, int options)
Definition: numpy.hpp:253
eigenpy::call_PyArray_RegisterCastFunc
int call_PyArray_RegisterCastFunc(PyArray_Descr *descr, int totype, PyArray_VectorUnaryFunc *castfunc)
Definition: numpy.hpp:295
test_matrix.int16_t
int16_t
Definition: test_matrix.py:200
eigenpy::NumpyEquivalentType::type_code
@ type_code
Definition: numpy.hpp:75
_Py_SET_TYPE
static void _Py_SET_TYPE(PyObject *o, PyTypeObject *type)
Definition: numpy.hpp:53
PyArray_DescrProto
#define PyArray_DescrProto
Definition: numpy.hpp:37
test_matrix.int8_t
int8_t
Definition: test_matrix.py:198


eigenpy
Author(s): Justin Carpentier, Nicolas Mansard
autogenerated on Fri Feb 14 2025 03:16:25