Skip to content

Commit 115ed93

Browse files
committed
core: add support of Eigen::Ref to Python
1 parent 8b03257 commit 115ed93

File tree

3 files changed

+92
-5
lines changed

3 files changed

+92
-5
lines changed

include/eigenpy/details.hpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,13 @@ namespace eigenpy
7979
{
8080
if(check_registration<MatType>()) return;
8181

82+
// to-python
8283
EigenToPyConverter<MatType>::registration();
84+
#if EIGEN_VERSION_AT_LEAST(3,2,0)
85+
EigenToPyConverter< Eigen::Ref<MatType> >::registration();
86+
#endif
87+
88+
// from-python
8389
EigenFromPyConverter<MatType>::registration();
8490
}
8591

include/eigenpy/eigen-to-python.hpp

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,36 @@ namespace eigenpy
8282
}
8383
};
8484

85+
template<typename MatType, int Options, typename Stride>
86+
struct EigenToPy< Eigen::Ref<MatType,Options,Stride> >
87+
{
88+
static PyObject* convert(const Eigen::Ref<MatType,Options,Stride> & mat)
89+
{
90+
typedef Eigen::Ref<MatType,Options,Stride> EigenRef;
91+
92+
assert( (mat.rows()<INT_MAX) && (mat.cols()<INT_MAX)
93+
&& "Matrix range larger than int ... should never happen." );
94+
const npy_intp R = (npy_intp)mat.rows(), C = (npy_intp)mat.cols();
95+
96+
PyArrayObject* pyArray;
97+
// Allocate Python memory
98+
if( ( ((!(C == 1) != !(R == 1)) && !MatType::IsVectorAtCompileTime) || MatType::IsVectorAtCompileTime)
99+
&& NumpyType::getType() == ARRAY_TYPE) // Handle array with a single dimension
100+
{
101+
npy_intp shape[1] = { C == 1 ? R : C };
102+
pyArray = NumpyAllocator<EigenRef>::allocate(const_cast<EigenRef &>(mat),1,shape);
103+
}
104+
else
105+
{
106+
npy_intp shape[2] = { R,C };
107+
pyArray = NumpyAllocator<EigenRef>::allocate(const_cast<EigenRef &>(mat),2,shape);
108+
}
109+
110+
// Create an instance (either np.array or np.matrix)
111+
return NumpyType::make(pyArray).ptr();
112+
}
113+
};
114+
85115
template<typename MatType>
86116
struct EigenToPyConverter
87117
{

include/eigenpy/numpy-allocator.hpp

Lines changed: 56 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -57,16 +57,41 @@ namespace eigenpy
5757
}
5858
else
5959
{
60-
return NumpyAllocator<MatType>::allocate(mat.derived(),nd,shape);
60+
return NumpyAllocator<MatType>::allocate(mat,nd,shape);
6161
}
6262
}
6363
};
6464

6565
#if EIGEN_VERSION_AT_LEAST(3,2,0)
6666

6767
template<typename MatType, int Options, typename Stride>
68-
struct NumpyAllocator<Eigen::Ref<MatType,Options,Stride> > : NumpyAllocator<MatType &>
68+
struct NumpyAllocator<Eigen::Ref<MatType,Options,Stride> >
6969
{
70+
typedef Eigen::Ref<MatType,Options,Stride> RefType;
71+
72+
static PyArrayObject * allocate(RefType & mat,
73+
npy_intp nd, npy_intp * shape)
74+
{
75+
typedef typename RefType::Scalar Scalar;
76+
enum { NPY_ARRAY_MEMORY_CONTIGUOUS = RefType::IsRowMajor ? NPY_ARRAY_CARRAY : NPY_ARRAY_FARRAY };
77+
78+
if(NumpyType::sharedMemory())
79+
{
80+
const int Scalar_type_code = Register::getTypeCode<Scalar>();
81+
PyArrayObject * pyArray = (PyArrayObject*) call_PyArray_New(getPyArrayType(),
82+
static_cast<int>(nd),
83+
shape,
84+
Scalar_type_code,
85+
mat.data(),
86+
NPY_ARRAY_MEMORY_CONTIGUOUS | NPY_ARRAY_ALIGNED);
87+
88+
return pyArray;
89+
}
90+
else
91+
{
92+
return NumpyAllocator<MatType>::allocate(mat,nd,shape);
93+
}
94+
}
7095
};
7196

7297
#endif
@@ -88,23 +113,49 @@ namespace eigenpy
88113
static_cast<int>(nd),
89114
shape,
90115
Scalar_type_code,
91-
const_cast<SimilarMatrixType &>(mat.derived()).data(),
116+
const_cast<Scalar *>(mat.data()),
92117
NPY_ARRAY_MEMORY_CONTIGUOUS_RO | NPY_ARRAY_ALIGNED);
93118

94119
return pyArray;
95120
}
96121
else
97122
{
98-
return NumpyAllocator<MatType>::allocate(mat.derived(),nd,shape);
123+
return NumpyAllocator<MatType>::allocate(mat,nd,shape);
99124
}
100125
}
101126
};
102127

103128
#if EIGEN_VERSION_AT_LEAST(3,2,0)
104129

105130
template<typename MatType, int Options, typename Stride>
106-
struct NumpyAllocator<const Eigen::Ref<const MatType,Options,Stride> > : NumpyAllocator<const MatType &>
131+
struct NumpyAllocator<const Eigen::Ref<const MatType,Options,Stride> >
107132
{
133+
typedef const Eigen::Ref<const MatType,Options,Stride> RefType;
134+
135+
template<typename SimilarMatrixType>
136+
static PyArrayObject * allocate(RefType & mat,
137+
npy_intp nd, npy_intp * shape)
138+
{
139+
typedef typename SimilarMatrixType::Scalar Scalar;
140+
enum { NPY_ARRAY_MEMORY_CONTIGUOUS_RO = SimilarMatrixType::IsRowMajor ? NPY_ARRAY_CARRAY_RO : NPY_ARRAY_FARRAY_RO };
141+
142+
if(NumpyType::sharedMemory())
143+
{
144+
const int Scalar_type_code = Register::getTypeCode<Scalar>();
145+
PyArrayObject * pyArray = (PyArrayObject*) call_PyArray_New(getPyArrayType(),
146+
static_cast<int>(nd),
147+
shape,
148+
Scalar_type_code,
149+
const_cast<Scalar *>(mat.data()),
150+
NPY_ARRAY_MEMORY_CONTIGUOUS_RO | NPY_ARRAY_ALIGNED);
151+
152+
return pyArray;
153+
}
154+
else
155+
{
156+
return NumpyAllocator<MatType>::allocate(mat,nd,shape);
157+
}
158+
}
108159
};
109160

110161
#endif

0 commit comments

Comments
 (0)