1 #ifndef MAHOTAS_NUMPYPP_NUMPY_HPP_INCLUDE_GUARD_LPC_
2 #define MAHOTAS_NUMPYPP_NUMPY_HPP_INCLUDE_GUARD_LPC_
3 /* Copyright 2010-2014 (C)
4 * Luis Pedro Coelho <luis@luispedro.org>
5 * License: MIT
6 */
7
8 #include <complex>
9
10 #include <Python.h>
11 #include <numpy/ndarrayobject.h>
12
13 namespace numpy {
14
15 template <typename T>
16 inline
17 npy_intp dtype_code();
18
19 #define DECLARE_DTYPE_CODE(type, constant) \
20 template <> inline \
21 npy_intp dtype_code<type>() { return constant; } \
22 \
23 template <> inline \
24 npy_intp dtype_code<const type>() { return constant; } \
25 \
26 template <> inline \
27 npy_intp dtype_code<volatile type>() { return constant; } \
28 \
29 template <> inline \
30 npy_intp dtype_code<volatile const type>() { return constant; }
31
DECLARE_DTYPE_CODE(bool,NPY_BOOL)32 DECLARE_DTYPE_CODE(bool, NPY_BOOL)
33 DECLARE_DTYPE_CODE(float, NPY_FLOAT)
34 DECLARE_DTYPE_CODE(char, NPY_BYTE)
35 DECLARE_DTYPE_CODE(unsigned char, NPY_UBYTE)
36 DECLARE_DTYPE_CODE(short, NPY_SHORT)
37 DECLARE_DTYPE_CODE(unsigned short, NPY_USHORT)
38 DECLARE_DTYPE_CODE(int, NPY_INT)
39 DECLARE_DTYPE_CODE(long, NPY_LONG)
40 DECLARE_DTYPE_CODE(unsigned long, NPY_ULONG)
41 DECLARE_DTYPE_CODE(long long, NPY_LONGLONG)
42 DECLARE_DTYPE_CODE(unsigned long long, NPY_ULONGLONG)
43 DECLARE_DTYPE_CODE(double, NPY_DOUBLE)
44 #if defined(NPY_FLOAT128)
45 DECLARE_DTYPE_CODE(npy_float128, NPY_FLOAT128)
46 #endif /* NPY_FLOAT128 */
47 DECLARE_DTYPE_CODE(std::complex<float>, NPY_CFLOAT)
48 DECLARE_DTYPE_CODE(std::complex<double>, NPY_CDOUBLE)
49 DECLARE_DTYPE_CODE(unsigned int, NPY_UINT)
50
51 template<typename T>
52 bool check_type(PyArrayObject* a) { return !!PyArray_EquivTypenums(PyArray_TYPE(a), dtype_code<T>()); }
53
54 template<typename T>
check_type(PyObject * a)55 bool check_type(PyObject* a) { return check_type<T>(reinterpret_cast<PyArrayObject*>(a)); }
56
57
58 template<typename T>
59 struct no_ptr { typedef T type; };
60 template<typename T>
61 struct no_ptr<T*> { typedef T type; };
62 template<typename T>
63 struct no_ptr<const T*> { typedef T type; };
64
65 template<typename T>
ndarray_cast(PyArrayObject * a)66 T ndarray_cast(PyArrayObject* a) {
67 assert(check_type<typename no_ptr<T>::type>(a));
68 assert(PyArray_ISALIGNED(a));
69 // The reason for the intermediate ``as_voidp`` variable is the following:
70 // around version 1.7.0, numpy played with having ``PyArray_DATA`` return
71 // ``char*`` as opposed to ``void*``. ``reinterpret_cast`` from void* was
72 // actually against the standard in C++ pre C++11 (although G++ accepts
73 // it).
74 //
75 // This roundabout way works on all these versions.
76 void* as_voidp = PyArray_DATA(a);
77 return const_cast<T>(static_cast<T>(as_voidp));
78 }
79 template<typename T>
ndarray_cast(PyObject * pa)80 T ndarray_cast(PyObject* pa) {
81 assert(PyArray_Check(pa));
82 return ndarray_cast<T>((PyArrayObject*)pa);
83 }
84
85 }
86
87 #endif // MAHOTAS_NUMPYPP_NUMPY_HPP_INCLUDE_GUARD_LPC_
88