88#include " eigenpy/fwd.hpp"
99#include " eigenpy/map.hpp"
1010#include " eigenpy/scalar-conversion.hpp"
11+ #include " eigenpy/utils/is-aligned.hpp"
1112
1213namespace eigenpy
1314{
@@ -17,7 +18,7 @@ namespace eigenpy
1718 template <typename MatType, bool IsVectorAtCompileTime = MatType::IsVectorAtCompileTime>
1819 struct init_matrix_or_array
1920 {
20- static MatType * run (PyArrayObject * pyArray, void * storage)
21+ static MatType * run (PyArrayObject * pyArray, void * storage = NULL )
2122 {
2223 assert (PyArray_NDIM (pyArray) == 1 || PyArray_NDIM (pyArray) == 2 );
2324
@@ -33,25 +34,34 @@ namespace eigenpy
3334 cols = 1 ;
3435 }
3536
36- return new (storage) MatType (rows,cols);
37+ if (storage)
38+ return new (storage) MatType (rows,cols);
39+ else
40+ return new MatType (rows,cols);
3741 }
3842 };
3943
4044 template <typename MatType>
4145 struct init_matrix_or_array <MatType,true >
4246 {
43- static MatType * run (PyArrayObject * pyArray, void * storage)
47+ static MatType * run (PyArrayObject * pyArray, void * storage = NULL )
4448 {
4549 if (PyArray_NDIM (pyArray) == 1 )
4650 {
4751 const int rows_or_cols = (int )PyArray_DIMS (pyArray)[0 ];
48- return new (storage) MatType (rows_or_cols);
52+ if (storage)
53+ return new (storage) MatType (rows_or_cols);
54+ else
55+ return new MatType (rows_or_cols);
4956 }
5057 else
5158 {
5259 const int rows = (int )PyArray_DIMS (pyArray)[0 ];
5360 const int cols = (int )PyArray_DIMS (pyArray)[1 ];
54- return new (storage) MatType (rows,cols);
61+ if (storage)
62+ return new (storage) MatType (rows,cols);
63+ else
64+ return new MatType (rows,cols);
5565 }
5666 }
5767 };
@@ -79,7 +89,7 @@ namespace eigenpy
7989 const Eigen::MatrixBase<MatrixOut> & /* dest*/ )
8090 {
8191 // do nothing
82- assert (" Must never happened" );
92+ assert (false && " Must never happened" );
8393 }
8494 };
8595
@@ -97,9 +107,11 @@ namespace eigenpy
97107 typedef MatType Type;
98108 typedef typename MatType::Scalar Scalar;
99109
100- static void allocate (PyArrayObject * pyArray, void * storage)
110+ static void allocate (PyArrayObject * pyArray,
111+ bp::converter::rvalue_from_python_storage<MatType> * storage)
101112 {
102- Type * mat_ptr = details::init_matrix_or_array<Type>::run (pyArray,storage);
113+ void * raw_ptr = storage->storage .bytes ;
114+ Type * mat_ptr = details::init_matrix_or_array<Type>::run (pyArray,raw_ptr);
103115 Type & mat = *mat_ptr;
104116
105117 const int pyArray_Type = EIGENPY_GET_PY_ARRAY_TYPE (pyArray);
@@ -193,6 +205,190 @@ namespace eigenpy
193205 };
194206
195207#if EIGEN_VERSION_AT_LEAST(3,2,0)
208+ template <typename MatType, int Options, typename Stride>
209+ struct EigenAllocator <Eigen::Ref<MatType,Options,Stride> >
210+ {
211+ typedef Eigen::Ref<MatType,Options,Stride> RefType;
212+ typedef typename MatType::Scalar Scalar;
213+
214+ typedef typename ::boost::python::detail::referent_storage<RefType&>::StorageType StorageType;
215+
216+ static void allocate (PyArrayObject * pyArray,
217+ bp::converter::rvalue_from_python_storage<RefType> * storage)
218+ {
219+ typedef typename StrideType<MatType,Eigen::internal::traits<RefType>::StrideType::InnerStrideAtCompileTime, Eigen::internal::traits<RefType>::StrideType::OuterStrideAtCompileTime >::type NumpyMapStride;
220+
221+ bool need_to_allocate = false ;
222+ const int pyArray_Type = EIGENPY_GET_PY_ARRAY_TYPE (pyArray);
223+ if (pyArray_Type != NumpyEquivalentType<Scalar>::type_code)
224+ need_to_allocate |= true ;
225+ if ( (MatType::IsRowMajor && (PyArray_IS_C_CONTIGUOUS (pyArray) && !PyArray_IS_F_CONTIGUOUS (pyArray)))
226+ || (!MatType::IsRowMajor && (PyArray_IS_F_CONTIGUOUS (pyArray) && !PyArray_IS_C_CONTIGUOUS (pyArray)))
227+ || MatType::IsVectorAtCompileTime
228+ || (PyArray_IS_F_CONTIGUOUS (pyArray) && PyArray_IS_C_CONTIGUOUS (pyArray))) // no need to allocate
229+ need_to_allocate |= false ;
230+ else
231+ need_to_allocate |= true ;
232+ if (Options != Eigen::Unaligned) // we need to check whether the memory is correctly aligned and composed of a continuous segment
233+ {
234+ void * data_ptr = PyArray_DATA (pyArray);
235+ if (!PyArray_ISONESEGMENT (pyArray) || !is_aligned (data_ptr,Options))
236+ need_to_allocate |= true ;
237+ }
238+
239+ void * raw_ptr = storage->storage .bytes ;
240+ if (need_to_allocate)
241+ {
242+ MatType * mat_ptr;
243+ mat_ptr = details::init_matrix_or_array<MatType>::run (pyArray);
244+ RefType mat_ref (*mat_ptr);
245+
246+ new (raw_ptr) StorageType (mat_ref,pyArray,mat_ptr);
247+
248+ RefType & mat = *reinterpret_cast <RefType*>(raw_ptr);
249+ if (pyArray_Type == NumpyEquivalentType<Scalar>::type_code)
250+ {
251+ mat = MapNumpy<MatType,Scalar>::map (pyArray); // avoid useless cast
252+ return ;
253+ }
254+
255+ switch (pyArray_Type)
256+ {
257+ case NPY_INT:
258+ EIGENPY_CAST_FROM_PYARRAY_TO_EIGEN_MATRIX (MatType,int ,Scalar,pyArray,mat);
259+ break ;
260+ case NPY_LONG:
261+ EIGENPY_CAST_FROM_PYARRAY_TO_EIGEN_MATRIX (MatType,long ,Scalar,pyArray,mat);
262+ break ;
263+ case NPY_FLOAT:
264+ EIGENPY_CAST_FROM_PYARRAY_TO_EIGEN_MATRIX (MatType,float ,Scalar,pyArray,mat);
265+ break ;
266+ case NPY_CFLOAT:
267+ EIGENPY_CAST_FROM_PYARRAY_TO_EIGEN_MATRIX (MatType,std::complex <float >,Scalar,pyArray,mat);
268+ break ;
269+ case NPY_DOUBLE:
270+ EIGENPY_CAST_FROM_PYARRAY_TO_EIGEN_MATRIX (MatType,double ,Scalar,pyArray,mat);
271+ break ;
272+ case NPY_CDOUBLE:
273+ EIGENPY_CAST_FROM_PYARRAY_TO_EIGEN_MATRIX (MatType,std::complex <double >,Scalar,pyArray,mat);
274+ break ;
275+ case NPY_LONGDOUBLE:
276+ EIGENPY_CAST_FROM_PYARRAY_TO_EIGEN_MATRIX (MatType,long double ,Scalar,pyArray,mat);
277+ break ;
278+ case NPY_CLONGDOUBLE:
279+ EIGENPY_CAST_FROM_PYARRAY_TO_EIGEN_MATRIX (MatType,std::complex <long double >,Scalar,pyArray,mat);
280+ break ;
281+ default :
282+ throw Exception (" You asked for a conversion which is not implemented." );
283+ }
284+ }
285+ else
286+ {
287+ assert (pyArray_Type == NumpyEquivalentType<Scalar>::type_code);
288+ typename MapNumpy<MatType,Scalar,Options,NumpyMapStride>::EigenMap numpyMap = MapNumpy<MatType,Scalar,Options,NumpyMapStride>::map (pyArray);
289+ RefType mat_ref (numpyMap);
290+ new (raw_ptr) StorageType (mat_ref,pyArray);
291+ }
292+ }
293+
294+ static void copy (RefType const & ref, PyArrayObject * pyArray)
295+ {
296+ EigenAllocator<MatType>::copy (ref,pyArray);
297+ }
298+ };
299+
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+
196392 template <typename MatType>
197393 struct EigenAllocator < eigenpy::Ref<MatType> >
198394 {
0 commit comments