Skip to content

Commit 1fe6a61

Browse files
committed
core: handle const Eigen::Ref<const MatType>
1 parent b19eac2 commit 1fe6a61

File tree

2 files changed

+164
-1
lines changed

2 files changed

+164
-1
lines changed

include/eigenpy/eigen-allocator.hpp

Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -297,6 +297,98 @@ namespace eigenpy
297297
}
298298
};
299299

300+
template<typename MatType, int Options, typename Stride>
301+
struct EigenAllocator<const Eigen::Ref<const MatType,Options,Stride> >
302+
{
303+
typedef const Eigen::Ref<const MatType,Options,Stride> RefType;
304+
typedef typename MatType::Scalar Scalar;
305+
306+
typedef typename ::boost::python::detail::referent_storage<RefType&>::StorageType StorageType;
307+
308+
static void allocate(PyArrayObject * pyArray,
309+
bp::converter::rvalue_from_python_storage<RefType> * storage)
310+
{
311+
typedef typename StrideType<MatType,Eigen::internal::traits<RefType>::StrideType::InnerStrideAtCompileTime, Eigen::internal::traits<RefType>::StrideType::OuterStrideAtCompileTime >::type NumpyMapStride;
312+
313+
bool need_to_allocate = false;
314+
const int pyArray_Type = EIGENPY_GET_PY_ARRAY_TYPE(pyArray);
315+
if(pyArray_Type != NumpyEquivalentType<Scalar>::type_code)
316+
need_to_allocate |= true;
317+
if( (MatType::IsRowMajor && (PyArray_IS_C_CONTIGUOUS(pyArray) && !PyArray_IS_F_CONTIGUOUS(pyArray)))
318+
|| (!MatType::IsRowMajor && (PyArray_IS_F_CONTIGUOUS(pyArray) && !PyArray_IS_C_CONTIGUOUS(pyArray)))
319+
|| MatType::IsVectorAtCompileTime
320+
|| (PyArray_IS_F_CONTIGUOUS(pyArray) && PyArray_IS_C_CONTIGUOUS(pyArray))) // no need to allocate
321+
need_to_allocate |= false;
322+
else
323+
need_to_allocate |= true;
324+
if(Options != Eigen::Unaligned) // we need to check whether the memory is correctly aligned and composed of a continuous segment
325+
{
326+
void * data_ptr = PyArray_DATA(pyArray);
327+
if(!PyArray_ISONESEGMENT(pyArray) || !is_aligned(data_ptr,Options))
328+
need_to_allocate |= true;
329+
}
330+
331+
void * raw_ptr = storage->storage.bytes;
332+
if(need_to_allocate)
333+
{
334+
MatType * mat_ptr;
335+
mat_ptr = details::init_matrix_or_array<MatType>::run(pyArray);
336+
RefType mat_ref(*mat_ptr);
337+
338+
new (raw_ptr) StorageType(mat_ref,pyArray,mat_ptr);
339+
340+
MatType & mat = *mat_ptr;
341+
if(pyArray_Type == NumpyEquivalentType<Scalar>::type_code)
342+
{
343+
mat = MapNumpy<MatType,Scalar>::map(pyArray); // avoid useless cast
344+
return;
345+
}
346+
347+
switch(pyArray_Type)
348+
{
349+
case NPY_INT:
350+
EIGENPY_CAST_FROM_PYARRAY_TO_EIGEN_MATRIX(MatType,int,Scalar,pyArray,mat);
351+
break;
352+
case NPY_LONG:
353+
EIGENPY_CAST_FROM_PYARRAY_TO_EIGEN_MATRIX(MatType,long,Scalar,pyArray,mat);
354+
break;
355+
case NPY_FLOAT:
356+
EIGENPY_CAST_FROM_PYARRAY_TO_EIGEN_MATRIX(MatType,float,Scalar,pyArray,mat);
357+
break;
358+
case NPY_CFLOAT:
359+
EIGENPY_CAST_FROM_PYARRAY_TO_EIGEN_MATRIX(MatType,std::complex<float>,Scalar,pyArray,mat);
360+
break;
361+
case NPY_DOUBLE:
362+
EIGENPY_CAST_FROM_PYARRAY_TO_EIGEN_MATRIX(MatType,double,Scalar,pyArray,mat);
363+
break;
364+
case NPY_CDOUBLE:
365+
EIGENPY_CAST_FROM_PYARRAY_TO_EIGEN_MATRIX(MatType,std::complex<double>,Scalar,pyArray,mat);
366+
break;
367+
case NPY_LONGDOUBLE:
368+
EIGENPY_CAST_FROM_PYARRAY_TO_EIGEN_MATRIX(MatType,long double,Scalar,pyArray,mat);
369+
break;
370+
case NPY_CLONGDOUBLE:
371+
EIGENPY_CAST_FROM_PYARRAY_TO_EIGEN_MATRIX(MatType,std::complex<long double>,Scalar,pyArray,mat);
372+
break;
373+
default:
374+
throw Exception("You asked for a conversion which is not implemented.");
375+
}
376+
}
377+
else
378+
{
379+
assert(pyArray_Type == NumpyEquivalentType<Scalar>::type_code);
380+
typename MapNumpy<MatType,Scalar,Options,NumpyMapStride>::EigenMap numpyMap = MapNumpy<MatType,Scalar,Options,NumpyMapStride>::map(pyArray);
381+
RefType mat_ref(numpyMap);
382+
new (raw_ptr) StorageType(mat_ref,pyArray);
383+
}
384+
}
385+
386+
static void copy(RefType const & ref, PyArrayObject * pyArray)
387+
{
388+
EigenAllocator<MatType>::copy(ref,pyArray);
389+
}
390+
};
391+
300392
template<typename MatType>
301393
struct EigenAllocator< eigenpy::Ref<MatType> >
302394
{

include/eigenpy/eigen-from-python.hpp

Lines changed: 72 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,15 @@ namespace boost { namespace python { namespace detail {
9797
::boost::python::detail::referent_size<StorageType&>::value
9898
> type;
9999
};
100+
101+
template<typename MatType, int Options, typename Stride>
102+
struct referent_storage<const Eigen::Ref<const MatType,Options,Stride> &>
103+
{
104+
typedef ::eigenpy::details::referent_storage_eigen_ref<const MatType,Options,Stride> StorageType;
105+
typedef aligned_storage<
106+
::boost::python::detail::referent_size<StorageType&>::value
107+
> type;
108+
};
100109
#endif
101110
}}}
102111

@@ -167,7 +176,8 @@ namespace boost { namespace python { namespace converter {
167176
#undef RVALUE_FROM_PYTHON_DATA_INIT
168177

169178
template<typename MatType, int Options, typename Stride>
170-
struct rvalue_from_python_data<Eigen::Ref<MatType,Options,Stride> &> : rvalue_from_python_storage<Eigen::Ref<MatType,Options,Stride> &>
179+
struct rvalue_from_python_data<Eigen::Ref<MatType,Options,Stride> &>
180+
: rvalue_from_python_storage<Eigen::Ref<MatType,Options,Stride> &>
171181
{
172182
typedef Eigen::Ref<MatType,Options,Stride> T;
173183

@@ -202,6 +212,43 @@ namespace boost { namespace python { namespace converter {
202212
}
203213
};
204214

215+
template<typename MatType, int Options, typename Stride>
216+
struct rvalue_from_python_data<const Eigen::Ref<const MatType,Options,Stride> &>
217+
: rvalue_from_python_storage<const Eigen::Ref<const MatType,Options,Stride> &>
218+
{
219+
typedef const Eigen::Ref<const MatType,Options,Stride> T;
220+
221+
# if (!defined(__MWERKS__) || __MWERKS__ >= 0x3000) \
222+
&& (!defined(__EDG_VERSION__) || __EDG_VERSION__ >= 245) \
223+
&& (!defined(__DECCXX_VER) || __DECCXX_VER > 60590014) \
224+
&& !defined(BOOST_PYTHON_SYNOPSIS) /* Synopsis' OpenCXX has trouble parsing this */
225+
// This must always be a POD struct with m_data its first member.
226+
BOOST_STATIC_ASSERT(BOOST_PYTHON_OFFSETOF(rvalue_from_python_storage<T>,stage1) == 0);
227+
# endif
228+
229+
// The usual constructor
230+
rvalue_from_python_data(rvalue_from_python_stage1_data const & _stage1)
231+
{
232+
this->stage1 = _stage1;
233+
}
234+
235+
// This constructor just sets m_convertible -- used by
236+
// implicitly_convertible<> to perform the final step of the
237+
// conversion, where the construct() function is already known.
238+
rvalue_from_python_data(void* convertible)
239+
{
240+
this->stage1.convertible = convertible;
241+
}
242+
243+
// Destroys any object constructed in the storage.
244+
~rvalue_from_python_data()
245+
{
246+
typedef ::eigenpy::details::referent_storage_eigen_ref<const MatType, Options,Stride> StorageType;
247+
if (this->stage1.convertible == this->storage.bytes)
248+
static_cast<StorageType *>((void *)this->storage.bytes)->~StorageType();
249+
}
250+
};
251+
205252
} } }
206253

207254
namespace eigenpy
@@ -384,6 +431,10 @@ namespace eigenpy
384431
// Add conversion to Eigen::Ref<MatType>
385432
typedef Eigen::Ref<MatType> RefType;
386433
EigenFromPy<RefType>::registration();
434+
435+
// Add conversion to Eigen::Ref<MatType>
436+
typedef const Eigen::Ref<const MatType> ConstRefType;
437+
EigenFromPy<ConstRefType>::registration();
387438
#endif
388439
}
389440
};
@@ -442,6 +493,26 @@ namespace eigenpy
442493
}
443494
};
444495

496+
template<typename MatType, int Options, typename Stride>
497+
struct EigenFromPy<const Eigen::Ref<const MatType,Options,Stride> >
498+
{
499+
typedef const Eigen::Ref<const MatType,Options,Stride> ConstRefType;
500+
typedef typename MatType::Scalar Scalar;
501+
502+
/// \brief Determine if pyObj can be converted into a MatType object
503+
static void* convertible(PyArrayObject * pyArray)
504+
{
505+
return EigenFromPy<MatType>::convertible(pyArray);
506+
}
507+
508+
static void registration()
509+
{
510+
bp::converter::registry::push_back
511+
(reinterpret_cast<void *(*)(_object *)>(&EigenFromPy::convertible),
512+
&eigen_from_py_construct<ConstRefType>,bp::type_id<ConstRefType>());
513+
}
514+
};
515+
445516
// Template specialization for Eigen::Ref
446517
template<typename MatType>
447518
struct EigenFromPyConverter< eigenpy::Ref<MatType> >

0 commit comments

Comments
 (0)