Skip to content
Snippets Groups Projects
Unverified Commit ff7cb4da authored by Justin Carpentier's avatar Justin Carpentier Committed by GitHub
Browse files

Merge pull request #124 from jcarpent/devel

Allows to convert a np.array of dimension 1 into any Eigen::Vector Row or Col major
parents 77b2063e aa9b5716
No related branches found
No related tags found
No related merge requests found
...@@ -119,6 +119,28 @@ namespace eigenpy ...@@ -119,6 +119,28 @@ namespace eigenpy
{ {
return getInstance().CurrentNumpyType; return getInstance().CurrentNumpyType;
} }
static const PyTypeObject * getNumpyMatrixType()
{
return getInstance().NumpyMatrixType;
}
static const PyTypeObject * getNumpyArrayType()
{
return getInstance().NumpyArrayType;
}
static bool isMatrix()
{
return PyType_IsSubtype(reinterpret_cast<PyTypeObject*>(getInstance().CurrentNumpyType.ptr()),
getInstance().NumpyMatrixType);
}
static bool isArray()
{
return PyType_IsSubtype(reinterpret_cast<PyTypeObject*>(getInstance().CurrentNumpyType.ptr()),
getInstance().NumpyArrayType);
}
protected: protected:
NumpyType() NumpyType()
...@@ -150,6 +172,39 @@ namespace eigenpy ...@@ -150,6 +172,39 @@ namespace eigenpy
bp::object NumpyArrayObject; PyTypeObject * NumpyArrayType; bp::object NumpyArrayObject; PyTypeObject * NumpyArrayType;
}; };
template<typename MatType, bool IsVectorAtCompileTime = MatType::IsVectorAtCompileTime>
struct initEigenObject
{
static MatType * run(PyArrayObject * pyArray, void * storage)
{
assert(PyArray_NDIM(pyArray) == 2);
const int rows = (int)PyArray_DIMS(pyArray)[0];
const int cols = (int)PyArray_DIMS(pyArray)[1];
return new (storage) MatType(rows,cols);
}
};
template<typename MatType>
struct initEigenObject<MatType,true>
{
static MatType * run(PyArrayObject * pyArray, void * storage)
{
if(PyArray_NDIM(pyArray) == 1)
{
const int rows_or_cols = (int)PyArray_DIMS(pyArray)[0];
return new (storage) MatType(rows_or_cols);
}
else
{
const int rows = (int)PyArray_DIMS(pyArray)[0];
const int cols = (int)PyArray_DIMS(pyArray)[1];
return new (storage) MatType(rows,cols);
}
}
};
template<typename MatType> template<typename MatType>
struct EigenObjectAllocator struct EigenObjectAllocator
...@@ -159,10 +214,7 @@ namespace eigenpy ...@@ -159,10 +214,7 @@ namespace eigenpy
static void allocate(PyArrayObject * pyArray, void * storage) static void allocate(PyArrayObject * pyArray, void * storage)
{ {
const int rows = (int)PyArray_DIMS(pyArray)[0]; Type * mat_ptr = initEigenObject<Type>::run(pyArray,storage);
const int cols = (int)PyArray_DIMS(pyArray)[1];
Type * mat_ptr = new (storage) Type(rows,cols);
if(NumpyEquivalentType<Scalar>::type_code == GET_PY_ARRAY_TYPE(pyArray)) if(NumpyEquivalentType<Scalar>::type_code == GET_PY_ARRAY_TYPE(pyArray))
{ {
...@@ -294,124 +346,113 @@ namespace eigenpy ...@@ -294,124 +346,113 @@ namespace eigenpy
template<typename MatType> template<typename MatType>
struct EigenFromPy struct EigenFromPy
{ {
static bool isScalarConvertible(const int np_type)
{
if(NumpyEquivalentType<typename MatType::Scalar>::type_code == np_type)
return true;
switch(np_type)
{
case NPY_INT:
return FromTypeToType<int,typename MatType::Scalar>::value;
case NPY_LONG:
return FromTypeToType<long,typename MatType::Scalar>::value;
case NPY_FLOAT:
return FromTypeToType<float,typename MatType::Scalar>::value;
case NPY_DOUBLE:
return FromTypeToType<double,typename MatType::Scalar>::value;
default:
return false;
}
}
/// \brief Determine if pyObj can be converted into a MatType object /// \brief Determine if pyObj can be converted into a MatType object
static void* convertible(PyArrayObject* pyArray) static void* convertible(PyArrayObject* pyArray)
{ {
if(!PyArray_Check(pyArray)) if(!PyArray_Check(pyArray))
return 0; return 0;
if(!isScalarConvertible(GET_PY_ARRAY_TYPE(pyArray)))
return 0;
if(MatType::IsVectorAtCompileTime) if(MatType::IsVectorAtCompileTime)
{ {
// Special care of scalar matrix of dimension 1x1. switch(PyArray_NDIM(pyArray))
if(PyArray_DIMS(pyArray)[0] == 1 && PyArray_DIMS(pyArray)[1] == 1)
return pyArray;
if(PyArray_DIMS(pyArray)[0] > 1 && PyArray_DIMS(pyArray)[1] > 1)
{ {
case 0:
return 0;
case 1:
return pyArray;
case 2:
{
// Special care of scalar matrix of dimension 1x1.
if(PyArray_DIMS(pyArray)[0] == 1 && PyArray_DIMS(pyArray)[1] == 1)
return pyArray;
if(PyArray_DIMS(pyArray)[0] > 1 && PyArray_DIMS(pyArray)[1] > 1)
{
#ifndef NDEBUG #ifndef NDEBUG
std::cerr << "The number of dimension of the object does not correspond to a vector" << std::endl; std::cerr << "The number of dimension of the object does not correspond to a vector" << std::endl;
#endif #endif
return 0; return 0;
} }
if(((PyArray_DIMS(pyArray)[0] == 1) && (MatType::ColsAtCompileTime == 1)) if(((PyArray_DIMS(pyArray)[0] == 1) && (MatType::ColsAtCompileTime == 1))
|| ((PyArray_DIMS(pyArray)[1] == 1) && (MatType::RowsAtCompileTime == 1))) || ((PyArray_DIMS(pyArray)[1] == 1) && (MatType::RowsAtCompileTime == 1)))
{ {
#ifndef NDEBUG #ifndef NDEBUG
if(MatType::ColsAtCompileTime == 1) if(MatType::ColsAtCompileTime == 1)
std::cerr << "The object is not a column vector" << std::endl; std::cerr << "The object is not a column vector" << std::endl;
else else
std::cerr << "The object is not a row vector" << std::endl; std::cerr << "The object is not a row vector" << std::endl;
#endif #endif
return 0; return 0;
}
break;
}
default:
return 0;
} }
} }
else // this is a matrix
if(PyArray_NDIM(pyArray) != 2)
{ {
if ( (PyArray_NDIM(pyArray) !=1) || (! MatType::IsVectorAtCompileTime) ) if(PyArray_NDIM(pyArray) != 2)
{ {
if ( (PyArray_NDIM(pyArray) !=1) || (! MatType::IsVectorAtCompileTime) )
{
#ifndef NDEBUG #ifndef NDEBUG
std::cerr << "The number of dimension of the object is not correct." << std::endl; std::cerr << "The number of dimension of the object is not correct." << std::endl;
#endif #endif
return 0; return 0;
}
} }
}
if(PyArray_NDIM(pyArray) == 2)
{
const int R = (int)PyArray_DIMS(pyArray)[0];
const int C = (int)PyArray_DIMS(pyArray)[1];
if( (MatType::RowsAtCompileTime!=R) if(PyArray_NDIM(pyArray) == 2)
&& (MatType::RowsAtCompileTime!=Eigen::Dynamic) )
return 0;
if( (MatType::ColsAtCompileTime!=C)
&& (MatType::ColsAtCompileTime!=Eigen::Dynamic) )
return 0;
}
// Check if the Scalar type of the obj_ptr is compatible with the Scalar type of MatType
if(GET_PY_ARRAY_TYPE(pyArray) == NPY_INT)
{
if(!FromTypeToType<int,typename MatType::Scalar>::value)
{ {
#ifndef NDEBUG const int R = (int)PyArray_DIMS(pyArray)[0];
std::cerr << "The Python matrix scalar type (int) cannot be converted into the scalar type of the Eigen matrix. Loss of arithmetic precision" << std::endl; const int C = (int)PyArray_DIMS(pyArray)[1];
#endif
return 0; if( (MatType::RowsAtCompileTime!=R)
&& (MatType::RowsAtCompileTime!=Eigen::Dynamic) )
return 0;
if( (MatType::ColsAtCompileTime!=C)
&& (MatType::ColsAtCompileTime!=Eigen::Dynamic) )
return 0;
} }
} }
else if(GET_PY_ARRAY_TYPE(pyArray) == NPY_LONG)
{
if(!FromTypeToType<long,typename MatType::Scalar>::value)
{
#ifndef NDEBUG
std::cerr << "The Python matrix scalar type (long) cannot be converted into the scalar type of the Eigen matrix. Loss of arithmetic precision" << std::endl;
#endif
return 0;
}
}
else if(GET_PY_ARRAY_TYPE(pyArray) == NPY_FLOAT)
{
if(!FromTypeToType<float,typename MatType::Scalar>::value)
{
#ifndef NDEBUG
std::cerr << "The Python matrix scalar type (float) cannot be converted into the scalar type of the Eigen matrix. Loss of arithmetic precision" << std::endl;
#endif
return 0;
}
}
else if(GET_PY_ARRAY_TYPE(pyArray) == NPY_DOUBLE)
{
if(!FromTypeToType<double,typename MatType::Scalar>::value)
{
#ifndef NDEBUG
std::cerr << "The Python matrix scalar (double) type cannot be converted into the scalar type of the Eigen matrix. Loss of arithmetic precision." << std::endl;
#endif
return 0;
}
}
else if(GET_PY_ARRAY_TYPE(pyArray) != NumpyEquivalentType<typename MatType::Scalar>::type_code)
{
#ifndef NDEBUG
std::cerr << "The internal type as no Eigen equivalent." << std::endl;
#endif
return 0;
}
#ifdef NPY_1_8_API_VERSION #ifdef NPY_1_8_API_VERSION
if(!(PyArray_FLAGS(pyArray))) if(!(PyArray_FLAGS(pyArray)))
#else #else
if(!(PyArray_FLAGS(pyArray) & NPY_ALIGNED)) if(!(PyArray_FLAGS(pyArray) & NPY_ALIGNED))
#endif #endif
{ {
#ifndef NDEBUG #ifndef NDEBUG
std::cerr << "NPY non-aligned matrices are not implemented." << std::endl; std::cerr << "NPY non-aligned matrices are not implemented." << std::endl;
#endif #endif
return 0; return 0;
} }
return pyArray; return pyArray;
} }
......
...@@ -102,7 +102,8 @@ namespace eigenpy ...@@ -102,7 +102,8 @@ namespace eigenpy
}; };
template<typename MatType, typename InputScalar> template<typename MatType, typename InputScalar>
typename MapNumpy<MatType,InputScalar>::EigenMap MapNumpy<MatType,InputScalar>::map( PyArrayObject* pyArray ) typename MapNumpy<MatType,InputScalar>::EigenMap
MapNumpy<MatType,InputScalar>::map(PyArrayObject * pyArray)
{ {
return Impl::mapImpl(pyArray); return Impl::mapImpl(pyArray);
} }
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment