19 #define NPY_NO_DEPRECATED_API NPY_1_7_API_VERSION
21 #include "numpy/ndarrayobject.h"
26 namespace py = boost::python;
28 namespace boost {
namespace python {
namespace numpy {
32 namespace np = boost::python::numpy;
34 #if __cplusplus > 200000L
35 static_assert(np::MAX_DIM == NPY_MAXDIMS,
"MAX_DIMS should be equal to NPY_MAXDIMS");
44 static PyArray_Descr* descr;
46 static void Register()
48 int itemtype = np::getItemtype<T>();
49 descr = PyArray_DescrFromType(itemtype);
51 boost::python::converter::registry::push_back(
54 boost::python::type_id<T>());
57 static void* convertible(PyObject* obj_ptr)
59 if (!PyArray_CheckScalar(obj_ptr))
return NULL;
60 PyArray_Descr* objdescr = PyArray_DescrFromScalar(obj_ptr);
61 bool ok = PyArray_CanCastTypeTo(objdescr, descr, NPY_SAME_KIND_CASTING);
63 return ok ? obj_ptr : NULL;
66 static void construct(
68 boost::python::converter::rvalue_from_python_stage1_data* data)
70 void* storage = ((boost::python::converter::rvalue_from_python_storage<T>*)data)->storage.bytes;
71 data->convertible = storage;
76 unsigned char buffer[
sizeof(T)];
78 memset(buffer.buffer, 0,
sizeof(T));
80 PyArray_CastScalarToCtype(obj_ptr, buffer.buffer, descr);
81 new (storage) T(buffer.data);
95 static void Register()
97 boost::python::converter::registry::push_back(
100 boost::python::type_id<ArrayType>());
103 static void* convertible(PyObject* obj_ptr)
105 bool ok = PyArray_Check(obj_ptr);
106 ok &= np::isCompatibleType<T>(PyArray_TYPE((PyArrayObject*)obj_ptr));
107 return ok ? obj_ptr : 0;
110 static void construct(
112 boost::python::converter::rvalue_from_python_stage1_data* data)
114 void* storage = ((boost::python::converter::rvalue_from_python_storage<ArrayType>*)data)->storage.bytes;
115 data->convertible = storage;
117 new (storage)
arrayt<T>(py::object(py::borrowed(obj_ptr)));
126 static void Register()
128 boost::python::converter::registry::push_back(
131 boost::python::type_id<ArrayType>());
134 static void* convertible(PyObject* obj_ptr)
136 bool ok = PyArray_Check(obj_ptr);
137 return ok ? obj_ptr : 0;
140 static void construct(
142 boost::python::converter::rvalue_from_python_stage1_data* data)
144 void* storage = ((boost::python::converter::rvalue_from_python_storage<ArrayType>*)data)->storage.bytes;
145 data->convertible = storage;
146 new (storage)
arraytbase(py::object(py::borrowed(obj_ptr)));
155 static PyObject* convert(
const TheType& arr)
157 return py::incref(arr.getObject().ptr());
160 static void Register()
162 py::to_python_converter<TheType, from_arraytbase>();
171 static PyObject* convert(
const TheType& arr)
173 return py::incref(arr.getObject().ptr());
176 static void Register()
178 py::to_python_converter<TheType, from_arrayt<T> >();
184 void RegisterAllConvertersForType()
193 #define CAST_TO_PPYARRAYOBJECT(p) ((PyArrayObject*)(p))
201 mw_py_impl::RegisterAllConvertersForType<bool>();
202 mw_py_impl::RegisterAllConvertersForType<char>();
203 mw_py_impl::RegisterAllConvertersForType<short>();
204 mw_py_impl::RegisterAllConvertersForType<int>();
205 mw_py_impl::RegisterAllConvertersForType<long>();
206 mw_py_impl::RegisterAllConvertersForType<long long>();
208 mw_py_impl::RegisterAllConvertersForType<unsigned char>();
209 mw_py_impl::RegisterAllConvertersForType<unsigned short>();
210 mw_py_impl::RegisterAllConvertersForType<unsigned int>();
211 mw_py_impl::RegisterAllConvertersForType<unsigned long>();
212 mw_py_impl::RegisterAllConvertersForType<unsigned long long>();
214 mw_py_impl::RegisterAllConvertersForType<float>();
215 mw_py_impl::RegisterAllConvertersForType<double>();
217 mw_py_impl::to_toarraytbase::Register();
218 mw_py_impl::from_arraytbase::Register();
220 py::numeric::array::set_module_and_type(
"numpy",
"ndarray");
224 object zeros(
int rank,
const Py_ssize_t *dims,
int type)
226 npy_intp* tmp =
const_cast<npy_intp*
>(dims);
227 PyObject* p = PyArray_ZEROS(rank,tmp,type,
true);
228 return py::object(handle<>(p));
232 object empty(
int rank,
const Py_ssize_t *dims,
int type )
234 npy_intp* tmp =
const_cast<npy_intp*
>(dims);
235 PyObject* p = PyArray_EMPTY(rank, tmp, type,
true);
236 return py::object(handle<>(p));
243 if (PyArray_Check(a.ptr()))
245 const PyArrayObject* p = CAST_TO_PPYARRAYOBJECT(a.ptr());
246 int t = PyArray_TYPE(p);
254 arraytbase::arraytbase(
const object& a_) :
261 arraytbase::arraytbase(
const object& a_,
int typesize) :
265 construct(a_, typesize);
269 void arraytbase::construct(
object const &a_,
int typesize)
272 if (obj.is_none())
return;
274 if (!PyArray_Check(obj.ptr()))
275 throw std::invalid_argument(
"arrayt: attempted construction with something that is not derived from ndarray");
279 bool is_behaved = PyArray_ISBEHAVED(CAST_TO_PPYARRAYOBJECT(objptr));
281 throw std::invalid_argument(
"arrayt: numpy array is not behaved");
283 if (typesize>0 && typesize != itemsize())
284 throw std::invalid_argument(
"arrayt: array itemsize does not match template argument");
288 int arraytbase::itemtype()
const
290 return PyArray_TYPE(CAST_TO_PPYARRAYOBJECT(objptr));
293 int arraytbase::itemsize()
const
295 return PyArray_ITEMSIZE(CAST_TO_PPYARRAYOBJECT(objptr));
298 int arraytbase::rank()
const
300 return PyArray_NDIM(CAST_TO_PPYARRAYOBJECT(objptr));
303 const Py_ssize_t* arraytbase::shape()
const
305 return PyArray_DIMS(CAST_TO_PPYARRAYOBJECT(objptr));
309 const Py_ssize_t* arraytbase::strides()
const
311 return PyArray_STRIDES(CAST_TO_PPYARRAYOBJECT(objptr));
315 bool arraytbase::isCContiguous()
const
317 return PyArray_IS_C_CONTIGUOUS(CAST_TO_PPYARRAYOBJECT(objptr));
321 bool arraytbase::isWriteable()
const
323 return PyArray_ISWRITEABLE(CAST_TO_PPYARRAYOBJECT(objptr));
327 bool arraytbase::isFContiguous()
const
329 return PyArray_IS_F_CONTIGUOUS(CAST_TO_PPYARRAYOBJECT(objptr));
333 char* arraytbase::bytes()
335 return PyArray_BYTES(CAST_TO_PPYARRAYOBJECT(objptr));
346 #define DEF_TYPE_COMPATIBILITY1(T, npyT1) \
347 template<> bool isCompatibleType<T>(int id) { return id == npyT1; }
348 #define DEF_TYPE_COMPATIBILITY2(T, npyT1, npyT2) \
349 template<> bool isCompatibleType<T>(int id) { return id == npyT1 || id == npyT2; }
350 #define DEF_TYPE_COMPATIBILITY3(T, npyT1, npyT2, npyT3) \
351 template<> bool isCompatibleType<T>(int id) { return id == npyT1 || id == npyT2 || id == npyT3; }
352 #define DEF_TYPE_COMPATIBILITY4(T, npyT1, npyT2, npyT3, npyT4) \
353 template<> bool isCompatibleType<T>(int id) { return id == npyT1 || id == npyT2 || id == npyT3 || id == npyT4; }
356 DEF_TYPE_COMPATIBILITY1(PyObject*, NPY_OBJECT)
357 DEF_TYPE_COMPATIBILITY1(
bool, NPY_BOOL)
358 DEF_TYPE_COMPATIBILITY3(
char, NPY_INT8, NPY_BYTE, NPY_BOOL)
359 DEF_TYPE_COMPATIBILITY3(
unsigned char, NPY_UINT8, NPY_UBYTE, NPY_BOOL)
360 DEF_TYPE_COMPATIBILITY2(
short, NPY_INT16, NPY_SHORT)
361 DEF_TYPE_COMPATIBILITY2(
unsigned short, NPY_UINT16, NPY_USHORT)
362 DEF_TYPE_COMPATIBILITY2(
int, NPY_INT32, NPY_INT)
363 DEF_TYPE_COMPATIBILITY2(
unsigned int, NPY_UINT32, NPY_UINT)
365 #if NPY_BITSOF_LONG == 64 // defined in npy_common.h
366 DEF_TYPE_COMPATIBILITY3(
unsigned long, NPY_UINT64, NPY_ULONG, NPY_ULONGLONG)
367 DEF_TYPE_COMPATIBILITY3(
long, NPY_INT64, NPY_LONG, NPY_LONGLONG)
368 #elif NPY_BITSOF_LONG == 32
369 DEF_TYPE_COMPATIBILITY2(
unsigned long, NPY_UINT32, NPY_UINT)
370 DEF_TYPE_COMPATIBILITY2(
long, NPY_INT32, NPY_INT)
372 DEF_TYPE_COMPATIBILITY3(
long long, NPY_INT64, NPY_LONG, NPY_LONGLONG)
373 DEF_TYPE_COMPATIBILITY3(
unsigned long long, NPY_UINT64, NPY_ULONG, NPY_ULONGLONG)
374 DEF_TYPE_COMPATIBILITY1(
float, NPY_FLOAT32)
375 DEF_TYPE_COMPATIBILITY2(
double, NPY_FLOAT64, NPY_DOUBLE)
377 #define DEF_ARRY_TYPE2ID(t,id)\
378 template<> int getItemtype<t>() {\
382 DEF_ARRY_TYPE2ID(PyObject*, NPY_OBJECT);
383 DEF_ARRY_TYPE2ID(
float,NPY_FLOAT32);
384 DEF_ARRY_TYPE2ID(
double,NPY_FLOAT64);
385 DEF_ARRY_TYPE2ID(
int,NPY_INT);
386 DEF_ARRY_TYPE2ID(
long,NPY_LONG);
387 DEF_ARRY_TYPE2ID(
long long ,NPY_LONGLONG);
388 DEF_ARRY_TYPE2ID(
short,NPY_SHORT);
389 DEF_ARRY_TYPE2ID(
char,NPY_BYTE);
390 DEF_ARRY_TYPE2ID(
bool,NPY_BOOL);
391 DEF_ARRY_TYPE2ID(
unsigned int,NPY_UINT);
392 DEF_ARRY_TYPE2ID(
unsigned long,NPY_ULONG);
393 DEF_ARRY_TYPE2ID(
unsigned short,NPY_USHORT);
394 DEF_ARRY_TYPE2ID(
unsigned char,NPY_UBYTE);
395 DEF_ARRY_TYPE2ID(
unsigned long long ,NPY_ULONGLONG);
int getItemtype(const object &a)
Obtain numpy's data type number from an boost-python object which should hold a ndarray.
This is the base class from which type specific variants are derived.
object empty(int rank, const Py_ssize_t *dims, int type)
Create a new ndarray with uninitialized memory.
void importNumpyAndRegisterTypes()
Initializes things.
This class defines operators () and [] to allow for direct memory access to array elements of type T...
bool isCompatibleType(int id)
Determines if a numpy data type identified by the type number id is binary compatible with the c-type...
object zeros(int rank, const Py_ssize_t *dims, int type)
Creates a new ndarray filled with zeros.