Commit ff7cb4da authored by Justin Carpentier's avatar Justin Carpentier Committed by GitHub

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
......@@ -119,6 +119,28 @@ namespace eigenpy
{
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:
NumpyType()
......@@ -150,6 +172,39 @@ namespace eigenpy
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>
struct EigenObjectAllocator
......@@ -159,10 +214,7 @@ namespace eigenpy
static void allocate(PyArrayObject * pyArray, void * storage)
{
const int rows = (int)PyArray_DIMS(pyArray)[0];
const int cols = (int)PyArray_DIMS(pyArray)[1];
Type * mat_ptr = new (storage) Type(rows,cols);
Type * mat_ptr = initEigenObject<Type>::run(pyArray,storage);
if(NumpyEquivalentType<Scalar>::type_code == GET_PY_ARRAY_TYPE(pyArray))
{
......@@ -294,124 +346,113 @@ namespace eigenpy
template<typename MatType>
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
static void* convertible(PyArrayObject* pyArray)
{
if(!PyArray_Check(pyArray))
return 0;
if(!isScalarConvertible(GET_PY_ARRAY_TYPE(pyArray)))
return 0;
if(MatType::IsVectorAtCompileTime)
{
// 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)
switch(PyArray_NDIM(pyArray))
{
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
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
return 0;
}
if(((PyArray_DIMS(pyArray)[0] == 1) && (MatType::ColsAtCompileTime == 1))
|| ((PyArray_DIMS(pyArray)[1] == 1) && (MatType::RowsAtCompileTime == 1)))
{
return 0;
}
if(((PyArray_DIMS(pyArray)[0] == 1) && (MatType::ColsAtCompileTime == 1))
|| ((PyArray_DIMS(pyArray)[1] == 1) && (MatType::RowsAtCompileTime == 1)))
{
#ifndef NDEBUG
if(MatType::ColsAtCompileTime == 1)
std::cerr << "The object is not a column vector" << std::endl;
else
std::cerr << "The object is not a row vector" << std::endl;
if(MatType::ColsAtCompileTime == 1)
std::cerr << "The object is not a column vector" << std::endl;
else
std::cerr << "The object is not a row vector" << std::endl;
#endif
return 0;
return 0;
}
break;
}
default:
return 0;
}
}
if(PyArray_NDIM(pyArray) != 2)
else // this is a matrix
{
if ( (PyArray_NDIM(pyArray) !=1) || (! MatType::IsVectorAtCompileTime) )
if(PyArray_NDIM(pyArray) != 2)
{
if ( (PyArray_NDIM(pyArray) !=1) || (! MatType::IsVectorAtCompileTime) )
{
#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
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)
&& (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)
if(PyArray_NDIM(pyArray) == 2)
{
#ifndef NDEBUG
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;
#endif
return 0;
const int R = (int)PyArray_DIMS(pyArray)[0];
const int C = (int)PyArray_DIMS(pyArray)[1];
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
if(!(PyArray_FLAGS(pyArray)))
#else
if(!(PyArray_FLAGS(pyArray) & NPY_ALIGNED))
#endif
{
{
#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
return 0;
}
return 0;
}
return pyArray;
}
......
......@@ -102,7 +102,8 @@ namespace eigenpy
};
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);
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment