Verified Commit 1fe6a61c authored by Justin Carpentier's avatar Justin Carpentier
Browse files

core: handle const Eigen::Ref<const MatType>

parent b19eac2f
......@@ -297,6 +297,98 @@ namespace eigenpy
}
};
template<typename MatType, int Options, typename Stride>
struct EigenAllocator<const Eigen::Ref<const MatType,Options,Stride> >
{
typedef const Eigen::Ref<const MatType,Options,Stride> RefType;
typedef typename MatType::Scalar Scalar;
typedef typename ::boost::python::detail::referent_storage<RefType&>::StorageType StorageType;
static void allocate(PyArrayObject * pyArray,
bp::converter::rvalue_from_python_storage<RefType> * storage)
{
typedef typename StrideType<MatType,Eigen::internal::traits<RefType>::StrideType::InnerStrideAtCompileTime, Eigen::internal::traits<RefType>::StrideType::OuterStrideAtCompileTime >::type NumpyMapStride;
bool need_to_allocate = false;
const int pyArray_Type = EIGENPY_GET_PY_ARRAY_TYPE(pyArray);
if(pyArray_Type != NumpyEquivalentType<Scalar>::type_code)
need_to_allocate |= true;
if( (MatType::IsRowMajor && (PyArray_IS_C_CONTIGUOUS(pyArray) && !PyArray_IS_F_CONTIGUOUS(pyArray)))
|| (!MatType::IsRowMajor && (PyArray_IS_F_CONTIGUOUS(pyArray) && !PyArray_IS_C_CONTIGUOUS(pyArray)))
|| MatType::IsVectorAtCompileTime
|| (PyArray_IS_F_CONTIGUOUS(pyArray) && PyArray_IS_C_CONTIGUOUS(pyArray))) // no need to allocate
need_to_allocate |= false;
else
need_to_allocate |= true;
if(Options != Eigen::Unaligned) // we need to check whether the memory is correctly aligned and composed of a continuous segment
{
void * data_ptr = PyArray_DATA(pyArray);
if(!PyArray_ISONESEGMENT(pyArray) || !is_aligned(data_ptr,Options))
need_to_allocate |= true;
}
void * raw_ptr = storage->storage.bytes;
if(need_to_allocate)
{
MatType * mat_ptr;
mat_ptr = details::init_matrix_or_array<MatType>::run(pyArray);
RefType mat_ref(*mat_ptr);
new (raw_ptr) StorageType(mat_ref,pyArray,mat_ptr);
MatType & mat = *mat_ptr;
if(pyArray_Type == NumpyEquivalentType<Scalar>::type_code)
{
mat = MapNumpy<MatType,Scalar>::map(pyArray); // avoid useless cast
return;
}
switch(pyArray_Type)
{
case NPY_INT:
EIGENPY_CAST_FROM_PYARRAY_TO_EIGEN_MATRIX(MatType,int,Scalar,pyArray,mat);
break;
case NPY_LONG:
EIGENPY_CAST_FROM_PYARRAY_TO_EIGEN_MATRIX(MatType,long,Scalar,pyArray,mat);
break;
case NPY_FLOAT:
EIGENPY_CAST_FROM_PYARRAY_TO_EIGEN_MATRIX(MatType,float,Scalar,pyArray,mat);
break;
case NPY_CFLOAT:
EIGENPY_CAST_FROM_PYARRAY_TO_EIGEN_MATRIX(MatType,std::complex<float>,Scalar,pyArray,mat);
break;
case NPY_DOUBLE:
EIGENPY_CAST_FROM_PYARRAY_TO_EIGEN_MATRIX(MatType,double,Scalar,pyArray,mat);
break;
case NPY_CDOUBLE:
EIGENPY_CAST_FROM_PYARRAY_TO_EIGEN_MATRIX(MatType,std::complex<double>,Scalar,pyArray,mat);
break;
case NPY_LONGDOUBLE:
EIGENPY_CAST_FROM_PYARRAY_TO_EIGEN_MATRIX(MatType,long double,Scalar,pyArray,mat);
break;
case NPY_CLONGDOUBLE:
EIGENPY_CAST_FROM_PYARRAY_TO_EIGEN_MATRIX(MatType,std::complex<long double>,Scalar,pyArray,mat);
break;
default:
throw Exception("You asked for a conversion which is not implemented.");
}
}
else
{
assert(pyArray_Type == NumpyEquivalentType<Scalar>::type_code);
typename MapNumpy<MatType,Scalar,Options,NumpyMapStride>::EigenMap numpyMap = MapNumpy<MatType,Scalar,Options,NumpyMapStride>::map(pyArray);
RefType mat_ref(numpyMap);
new (raw_ptr) StorageType(mat_ref,pyArray);
}
}
static void copy(RefType const & ref, PyArrayObject * pyArray)
{
EigenAllocator<MatType>::copy(ref,pyArray);
}
};
template<typename MatType>
struct EigenAllocator< eigenpy::Ref<MatType> >
{
......
......@@ -97,6 +97,15 @@ namespace boost { namespace python { namespace detail {
::boost::python::detail::referent_size<StorageType&>::value
> type;
};
template<typename MatType, int Options, typename Stride>
struct referent_storage<const Eigen::Ref<const MatType,Options,Stride> &>
{
typedef ::eigenpy::details::referent_storage_eigen_ref<const MatType,Options,Stride> StorageType;
typedef aligned_storage<
::boost::python::detail::referent_size<StorageType&>::value
> type;
};
#endif
}}}
......@@ -167,7 +176,8 @@ namespace boost { namespace python { namespace converter {
#undef RVALUE_FROM_PYTHON_DATA_INIT
template<typename MatType, int Options, typename Stride>
struct rvalue_from_python_data<Eigen::Ref<MatType,Options,Stride> &> : rvalue_from_python_storage<Eigen::Ref<MatType,Options,Stride> &>
struct rvalue_from_python_data<Eigen::Ref<MatType,Options,Stride> &>
: rvalue_from_python_storage<Eigen::Ref<MatType,Options,Stride> &>
{
typedef Eigen::Ref<MatType,Options,Stride> T;
......@@ -202,6 +212,43 @@ namespace boost { namespace python { namespace converter {
}
};
template<typename MatType, int Options, typename Stride>
struct rvalue_from_python_data<const Eigen::Ref<const MatType,Options,Stride> &>
: rvalue_from_python_storage<const Eigen::Ref<const MatType,Options,Stride> &>
{
typedef const Eigen::Ref<const MatType,Options,Stride> T;
# if (!defined(__MWERKS__) || __MWERKS__ >= 0x3000) \
&& (!defined(__EDG_VERSION__) || __EDG_VERSION__ >= 245) \
&& (!defined(__DECCXX_VER) || __DECCXX_VER > 60590014) \
&& !defined(BOOST_PYTHON_SYNOPSIS) /* Synopsis' OpenCXX has trouble parsing this */
// This must always be a POD struct with m_data its first member.
BOOST_STATIC_ASSERT(BOOST_PYTHON_OFFSETOF(rvalue_from_python_storage<T>,stage1) == 0);
# endif
// The usual constructor
rvalue_from_python_data(rvalue_from_python_stage1_data const & _stage1)
{
this->stage1 = _stage1;
}
// This constructor just sets m_convertible -- used by
// implicitly_convertible<> to perform the final step of the
// conversion, where the construct() function is already known.
rvalue_from_python_data(void* convertible)
{
this->stage1.convertible = convertible;
}
// Destroys any object constructed in the storage.
~rvalue_from_python_data()
{
typedef ::eigenpy::details::referent_storage_eigen_ref<const MatType, Options,Stride> StorageType;
if (this->stage1.convertible == this->storage.bytes)
static_cast<StorageType *>((void *)this->storage.bytes)->~StorageType();
}
};
} } }
namespace eigenpy
......@@ -384,6 +431,10 @@ namespace eigenpy
// Add conversion to Eigen::Ref<MatType>
typedef Eigen::Ref<MatType> RefType;
EigenFromPy<RefType>::registration();
// Add conversion to Eigen::Ref<MatType>
typedef const Eigen::Ref<const MatType> ConstRefType;
EigenFromPy<ConstRefType>::registration();
#endif
}
};
......@@ -442,6 +493,26 @@ namespace eigenpy
}
};
template<typename MatType, int Options, typename Stride>
struct EigenFromPy<const Eigen::Ref<const MatType,Options,Stride> >
{
typedef const Eigen::Ref<const MatType,Options,Stride> ConstRefType;
typedef typename MatType::Scalar Scalar;
/// \brief Determine if pyObj can be converted into a MatType object
static void* convertible(PyArrayObject * pyArray)
{
return EigenFromPy<MatType>::convertible(pyArray);
}
static void registration()
{
bp::converter::registry::push_back
(reinterpret_cast<void *(*)(_object *)>(&EigenFromPy::convertible),
&eigen_from_py_construct<ConstRefType>,bp::type_id<ConstRefType>());
}
};
// Template specialization for Eigen::Ref
template<typename MatType>
struct EigenFromPyConverter< eigenpy::Ref<MatType> >
......
Supports Markdown
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