Synced with commit b30d90bf70 (diff-43bc6d5065b2331de9923fd47b8c5d56)
parent
c77997fbb1
commit
eb5d026a4a
|
@ -12,8 +12,17 @@
|
||||||
#ifndef NUMPY_EIGEN_CONVERTER_HPP
|
#ifndef NUMPY_EIGEN_CONVERTER_HPP
|
||||||
#define NUMPY_EIGEN_CONVERTER_HPP
|
#define NUMPY_EIGEN_CONVERTER_HPP
|
||||||
|
|
||||||
#include "boost_python_headers.hpp"
|
#include <numpy_eigen/boost_python_headers.hpp>
|
||||||
#include <iostream>
|
//#include <iostream>
|
||||||
|
|
||||||
|
#include "numpy/numpyconfig.h"
|
||||||
|
#ifdef NPY_1_7_API_VERSION
|
||||||
|
#define NPY_NO_DEPRECATED_API NPY_1_7_API_VERSION
|
||||||
|
#define NPE_PY_ARRAY_OBJECT PyArrayObject
|
||||||
|
#else
|
||||||
|
//TODO Remove this as soon as support for Numpy version before 1.7 is dropped
|
||||||
|
#define NPE_PY_ARRAY_OBJECT PyObject
|
||||||
|
#endif
|
||||||
|
|
||||||
#define PY_ARRAY_UNIQUE_SYMBOL NP_Eigen_AS
|
#define PY_ARRAY_UNIQUE_SYMBOL NP_Eigen_AS
|
||||||
#include <numpy/arrayobject.h>
|
#include <numpy/arrayobject.h>
|
||||||
|
@ -93,7 +102,7 @@ struct NumpyEigenConverter
|
||||||
npy_intp dimensions[1];
|
npy_intp dimensions[1];
|
||||||
dimensions[0] = M.size();
|
dimensions[0] = M.size();
|
||||||
P = PyArray_SimpleNew(1, dimensions, TypeToNumPy<scalar_t>::NpyType);
|
P = PyArray_SimpleNew(1, dimensions, TypeToNumPy<scalar_t>::NpyType);
|
||||||
numpyTypeDemuxer< CopyEigenToNumpyVector<const matrix_t> >(&M,P);
|
numpyTypeDemuxer< CopyEigenToNumpyVector<const matrix_t> >(&M, reinterpret_cast<NPE_PY_ARRAY_OBJECT*>(P));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -102,7 +111,7 @@ struct NumpyEigenConverter
|
||||||
dimensions[0] = M.rows();
|
dimensions[0] = M.rows();
|
||||||
dimensions[1] = M.cols();
|
dimensions[1] = M.cols();
|
||||||
P = PyArray_SimpleNew(2, dimensions, TypeToNumPy<scalar_t>::NpyType);
|
P = PyArray_SimpleNew(2, dimensions, TypeToNumPy<scalar_t>::NpyType);
|
||||||
numpyTypeDemuxer< CopyEigenToNumpyMatrix<const matrix_t> >(&M,P);
|
numpyTypeDemuxer< CopyEigenToNumpyMatrix<const matrix_t> >(&M, reinterpret_cast<NPE_PY_ARRAY_OBJECT*>(P));
|
||||||
}
|
}
|
||||||
|
|
||||||
// incrementing the reference seems to cause a memory leak.
|
// incrementing the reference seems to cause a memory leak.
|
||||||
|
@ -131,7 +140,7 @@ struct NumpyEigenConverter
|
||||||
return valid;
|
return valid;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void checkMatrixSizes(PyObject * obj_ptr)
|
static void checkMatrixSizes(NPE_PY_ARRAY_OBJECT * obj_ptr)
|
||||||
{
|
{
|
||||||
int rows = PyArray_DIM(obj_ptr, 0);
|
int rows = PyArray_DIM(obj_ptr, 0);
|
||||||
int cols = PyArray_DIM(obj_ptr, 1);
|
int cols = PyArray_DIM(obj_ptr, 1);
|
||||||
|
@ -145,7 +154,7 @@ struct NumpyEigenConverter
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void checkRowVectorSizes(PyObject * obj_ptr, int cols)
|
static void checkRowVectorSizes(NPE_PY_ARRAY_OBJECT * obj_ptr, int cols)
|
||||||
{
|
{
|
||||||
if(!isDimensionValid(cols, ColsAtCompileTime, MaxColsAtCompileTime))
|
if(!isDimensionValid(cols, ColsAtCompileTime, MaxColsAtCompileTime))
|
||||||
{
|
{
|
||||||
|
@ -154,7 +163,7 @@ struct NumpyEigenConverter
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void checkColumnVectorSizes(PyObject * obj_ptr, int rows)
|
static void checkColumnVectorSizes(NPE_PY_ARRAY_OBJECT * obj_ptr, int rows)
|
||||||
{
|
{
|
||||||
// Check if the type can accomidate one column.
|
// Check if the type can accomidate one column.
|
||||||
if(ColsAtCompileTime == Eigen::Dynamic || ColsAtCompileTime == 1)
|
if(ColsAtCompileTime == Eigen::Dynamic || ColsAtCompileTime == 1)
|
||||||
|
@ -173,7 +182,7 @@ struct NumpyEigenConverter
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void checkVectorSizes(PyObject * obj_ptr)
|
static void checkVectorSizes(NPE_PY_ARRAY_OBJECT * obj_ptr)
|
||||||
{
|
{
|
||||||
int size = PyArray_DIM(obj_ptr, 0);
|
int size = PyArray_DIM(obj_ptr, 0);
|
||||||
|
|
||||||
|
@ -206,8 +215,10 @@ struct NumpyEigenConverter
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
NPE_PY_ARRAY_OBJECT * array_ptr = reinterpret_cast<NPE_PY_ARRAY_OBJECT*>(obj_ptr);
|
||||||
|
|
||||||
// Check the type of the array.
|
// Check the type of the array.
|
||||||
int npyType = PyArray_ObjectType(obj_ptr, 0);
|
int npyType = getNpyType(array_ptr);
|
||||||
|
|
||||||
if(!TypeToNumPy<scalar_t>::canConvert(npyType))
|
if(!TypeToNumPy<scalar_t>::canConvert(npyType))
|
||||||
{
|
{
|
||||||
|
@ -219,7 +230,7 @@ struct NumpyEigenConverter
|
||||||
|
|
||||||
|
|
||||||
// Check the array dimensions.
|
// Check the array dimensions.
|
||||||
int nd = PyArray_NDIM(obj_ptr);
|
int nd = PyArray_NDIM(array_ptr);
|
||||||
|
|
||||||
if(nd != 1 && nd != 2)
|
if(nd != 1 && nd != 2)
|
||||||
{
|
{
|
||||||
|
@ -228,12 +239,12 @@ struct NumpyEigenConverter
|
||||||
|
|
||||||
if(nd == 1)
|
if(nd == 1)
|
||||||
{
|
{
|
||||||
checkVectorSizes(obj_ptr);
|
checkVectorSizes(array_ptr);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Two-dimensional matrix type.
|
// Two-dimensional matrix type.
|
||||||
checkMatrixSizes(obj_ptr);
|
checkMatrixSizes(array_ptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -265,10 +276,17 @@ struct NumpyEigenConverter
|
||||||
|
|
||||||
matrix_t & M = *Mp;
|
matrix_t & M = *Mp;
|
||||||
|
|
||||||
int nd = PyArray_NDIM(obj_ptr);
|
if (!PyArray_Check(obj_ptr))
|
||||||
|
{
|
||||||
|
THROW_TYPE_ERROR("construct is only defined for numpy array and matrix types");
|
||||||
|
}
|
||||||
|
|
||||||
|
NPE_PY_ARRAY_OBJECT * array_ptr = reinterpret_cast<NPE_PY_ARRAY_OBJECT*>(obj_ptr);
|
||||||
|
|
||||||
|
int nd = PyArray_NDIM(array_ptr);
|
||||||
if(nd == 1)
|
if(nd == 1)
|
||||||
{
|
{
|
||||||
int size = PyArray_DIM(obj_ptr, 0);
|
int size = PyArray_DIM(array_ptr, 0);
|
||||||
// This is a vector type
|
// This is a vector type
|
||||||
if(RowsAtCompileTime == 1)
|
if(RowsAtCompileTime == 1)
|
||||||
{
|
{
|
||||||
|
@ -280,15 +298,15 @@ struct NumpyEigenConverter
|
||||||
// Column Vector
|
// Column Vector
|
||||||
M.resize(size,1);
|
M.resize(size,1);
|
||||||
}
|
}
|
||||||
numpyTypeDemuxer< CopyNumpyToEigenVector<matrix_t> >(&M,obj_ptr);
|
numpyTypeDemuxer< CopyNumpyToEigenVector<matrix_t> >(&M, array_ptr);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
int rows = PyArray_DIM(obj_ptr, 0);
|
int rows = PyArray_DIM(array_ptr, 0);
|
||||||
int cols = PyArray_DIM(obj_ptr, 1);
|
int cols = PyArray_DIM(array_ptr, 1);
|
||||||
|
|
||||||
M.resize(rows,cols);
|
M.resize(rows,cols);
|
||||||
numpyTypeDemuxer< CopyNumpyToEigenMatrix<matrix_t> >(&M,obj_ptr);
|
numpyTypeDemuxer< CopyNumpyToEigenMatrix<matrix_t> >(&M, array_ptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -9,16 +9,16 @@ struct CopyNumpyToEigenMatrix
|
||||||
typedef typename matrix_t::Scalar scalar_t;
|
typedef typename matrix_t::Scalar scalar_t;
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
void exec(EIGEN_T * M_, PyObject * P_)
|
void exec(EIGEN_T * M_, NPE_PY_ARRAY_OBJECT * P_)
|
||||||
{
|
{
|
||||||
// Assumes M is already initialized.
|
// Assumes M is already initialized.
|
||||||
for(int r = 0; r < M_->rows(); r++)
|
for(int r = 0; r < M_->rows(); r++)
|
||||||
{
|
{
|
||||||
for(int c = 0; c < M_->cols(); c++)
|
for(int c = 0; c < M_->cols(); c++)
|
||||||
{
|
{
|
||||||
T * p = static_cast<T*>(PyArray_GETPTR2(P_, r, c));
|
T * p = static_cast<T*>(PyArray_GETPTR2(P_, r, c));
|
||||||
(*M_)(r,c) = static_cast<scalar_t>(*p);
|
(*M_)(r,c) = static_cast<scalar_t>(*p);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -31,16 +31,16 @@ struct CopyEigenToNumpyMatrix
|
||||||
typedef typename matrix_t::Scalar scalar_t;
|
typedef typename matrix_t::Scalar scalar_t;
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
void exec(EIGEN_T * M_, PyObject * P_)
|
void exec(EIGEN_T * M_, NPE_PY_ARRAY_OBJECT * P_)
|
||||||
{
|
{
|
||||||
// Assumes M is already initialized.
|
// Assumes M is already initialized.
|
||||||
for(int r = 0; r < M_->rows(); r++)
|
for(int r = 0; r < M_->rows(); r++)
|
||||||
{
|
{
|
||||||
for(int c = 0; c < M_->cols(); c++)
|
for(int c = 0; c < M_->cols(); c++)
|
||||||
{
|
{
|
||||||
T * p = static_cast<T*>(PyArray_GETPTR2(P_, r, c));
|
T * p = static_cast<T*>(PyArray_GETPTR2(P_, r, c));
|
||||||
*p = static_cast<T>((*M_)(r,c));
|
*p = static_cast<T>((*M_)(r,c));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -53,13 +53,13 @@ struct CopyEigenToNumpyVector
|
||||||
typedef typename matrix_t::Scalar scalar_t;
|
typedef typename matrix_t::Scalar scalar_t;
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
void exec(EIGEN_T * M_, PyObject * P_)
|
void exec(EIGEN_T * M_, NPE_PY_ARRAY_OBJECT * P_)
|
||||||
{
|
{
|
||||||
// Assumes M is already initialized.
|
// Assumes M is already initialized.
|
||||||
for(int i = 0; i < M_->size(); i++)
|
for(int i = 0; i < M_->size(); i++)
|
||||||
{
|
{
|
||||||
T * p = static_cast<T*>(PyArray_GETPTR1(P_, i));
|
T * p = static_cast<T*>(PyArray_GETPTR1(P_, i));
|
||||||
*p = static_cast<T>((*M_)(i));
|
*p = static_cast<T>((*M_)(i));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -73,13 +73,13 @@ struct CopyNumpyToEigenVector
|
||||||
typedef typename matrix_t::Scalar scalar_t;
|
typedef typename matrix_t::Scalar scalar_t;
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
void exec(EIGEN_T * M_, PyObject * P_)
|
void exec(EIGEN_T * M_, NPE_PY_ARRAY_OBJECT * P_)
|
||||||
{
|
{
|
||||||
// Assumes M is already initialized.
|
// Assumes M is already initialized.
|
||||||
for(int i = 0; i < M_->size(); i++)
|
for(int i = 0; i < M_->size(); i++)
|
||||||
{
|
{
|
||||||
T * p = static_cast<T*>(PyArray_GETPTR1(P_, i));
|
T * p = static_cast<T*>(PyArray_GETPTR1(P_, i));
|
||||||
(*M_)(i) = static_cast<scalar_t>(*p);
|
(*M_)(i) = static_cast<scalar_t>(*p);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -91,10 +91,11 @@ struct CopyNumpyToEigenVector
|
||||||
// Crazy syntax in this function was found here:
|
// Crazy syntax in this function was found here:
|
||||||
// http://stackoverflow.com/questions/1840253/c-template-member-function-of-template-class-called-from-template-function/1840318#1840318
|
// http://stackoverflow.com/questions/1840253/c-template-member-function-of-template-class-called-from-template-function/1840318#1840318
|
||||||
template< typename FUNCTOR_T>
|
template< typename FUNCTOR_T>
|
||||||
inline void numpyTypeDemuxer(typename FUNCTOR_T::matrix_t * M, PyObject * P)
|
inline void numpyTypeDemuxer(typename FUNCTOR_T::matrix_t * M, NPE_PY_ARRAY_OBJECT * P)
|
||||||
{
|
{
|
||||||
FUNCTOR_T f;
|
FUNCTOR_T f;
|
||||||
int npyType = PyArray_ObjectType(P, 0);
|
|
||||||
|
int npyType = getNpyType(P);
|
||||||
switch(npyType)
|
switch(npyType)
|
||||||
{
|
{
|
||||||
case NPY_BOOL:
|
case NPY_BOOL:
|
||||||
|
|
|
@ -1,12 +1,12 @@
|
||||||
#ifndef NUMPY_EIGEN_TYPE_TRAITS_HPP
|
#ifndef NUMPY_EIGEN_TYPE_TRAITS_HPP
|
||||||
#define NUMPY_EIGEN_TYPE_TRAITS_HPP
|
#define NUMPY_EIGEN_TYPE_TRAITS_HPP
|
||||||
|
|
||||||
#define THROW_TYPE_ERROR(msg) \
|
#define THROW_TYPE_ERROR(msg) \
|
||||||
{ \
|
{ \
|
||||||
std::stringstream type_error_ss; \
|
std::stringstream type_error_ss; \
|
||||||
type_error_ss << msg; \
|
type_error_ss << msg; \
|
||||||
PyErr_SetString(PyExc_TypeError, type_error_ss.str().c_str()); \
|
PyErr_SetString(PyExc_TypeError, type_error_ss.str().c_str()); \
|
||||||
throw boost::python::error_already_set(); \
|
throw boost::python::error_already_set(); \
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -99,6 +99,19 @@ template<> struct TypeToNumPy<double>
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
inline int getNpyType(PyObject * obj_ptr){
|
||||||
|
return PyArray_ObjectType(obj_ptr, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef NPY_1_7_API_VERSION
|
||||||
|
inline int getNpyType(PyArrayObject * obj_ptr){
|
||||||
|
PyArray_Descr * descr = PyArray_MinScalarType(obj_ptr);
|
||||||
|
if (descr == NULL){
|
||||||
|
THROW_TYPE_ERROR("Unsupported type: PyArray_MinScalarType returned null!");
|
||||||
|
}
|
||||||
|
return descr->type_num;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
inline const char * npyTypeToString(int npyType)
|
inline const char * npyTypeToString(int npyType)
|
||||||
{
|
{
|
||||||
|
@ -157,18 +170,18 @@ inline const char * npyTypeToString(int npyType)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
inline std::string npyArrayTypeString(PyObject * obj_ptr)
|
inline std::string npyArrayTypeString(NPE_PY_ARRAY_OBJECT * obj_ptr)
|
||||||
{
|
{
|
||||||
std::stringstream ss;
|
std::stringstream ss;
|
||||||
int nd = PyArray_NDIM(obj_ptr);
|
int nd = PyArray_NDIM(obj_ptr);
|
||||||
ss << "numpy.array<" << npyTypeToString(PyArray_ObjectType(obj_ptr, 0)) << ">[";
|
ss << "numpy.array<" << npyTypeToString(getNpyType(obj_ptr)) << ">[";
|
||||||
if(nd > 0)
|
if(nd > 0)
|
||||||
{
|
{
|
||||||
ss << PyArray_DIM(obj_ptr, 0);
|
ss << PyArray_DIM(obj_ptr, 0);
|
||||||
for(int i = 1; i < nd; i++)
|
for(int i = 1; i < nd; i++)
|
||||||
{
|
{
|
||||||
ss << ", " << PyArray_DIM(obj_ptr, i);
|
ss << ", " << PyArray_DIM(obj_ptr, i);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ss << "]";
|
ss << "]";
|
||||||
return ss.str();
|
return ss.str();
|
||||||
|
|
Loading…
Reference in New Issue