11/*
22 * Copyright 2014-2019, CNRS
3- * Copyright 2018-2019 , INRIA
3+ * Copyright 2018-2020 , INRIA
44 */
55
66#ifndef __eigenpy_details_hpp__
1515#include " eigenpy/eigenpy.hpp"
1616#include " eigenpy/registration.hpp"
1717#include " eigenpy/map.hpp"
18+ #include " eigenpy/exception.hpp"
1819
1920namespace boost { namespace python { namespace detail {
2021
@@ -99,11 +100,15 @@ struct implicit<MatType,Eigen::MatrixBase<MatType> >
99100namespace eigenpy
100101{
101102 template <typename SCALAR> struct NumpyEquivalentType {};
103+ template <> struct NumpyEquivalentType <float > { enum { type_code = NPY_FLOAT };};
104+ template <> struct NumpyEquivalentType < std::complex <float > > { enum { type_code = NPY_CFLOAT };};
102105 template <> struct NumpyEquivalentType <double > { enum { type_code = NPY_DOUBLE };};
106+ template <> struct NumpyEquivalentType < std::complex <double > > { enum { type_code = NPY_CDOUBLE };};
107+ template <> struct NumpyEquivalentType <long double > { enum { type_code = NPY_LONGDOUBLE };};
108+ template <> struct NumpyEquivalentType < std::complex <long double > > { enum { type_code = NPY_CLONGDOUBLE };};
103109 template <> struct NumpyEquivalentType <int > { enum { type_code = NPY_INT };};
104110 template <> struct NumpyEquivalentType <long > { enum { type_code = NPY_LONG };};
105- template <> struct NumpyEquivalentType <float > { enum { type_code = NPY_FLOAT };};
106-
111+
107112 template <typename SCALAR1, typename SCALAR2>
108113 struct FromTypeToType : public boost ::false_type {};
109114
@@ -112,12 +117,28 @@ namespace eigenpy
112117
113118 template <> struct FromTypeToType <int ,long > : public boost::true_type {};
114119 template <> struct FromTypeToType <int ,float > : public boost::true_type {};
120+ template <> struct FromTypeToType <int ,std::complex <float > > : public boost::true_type {};
115121 template <> struct FromTypeToType <int ,double > : public boost::true_type {};
122+ template <> struct FromTypeToType <int ,std::complex <double > > : public boost::true_type {};
123+ template <> struct FromTypeToType <int ,long double > : public boost::true_type {};
124+ template <> struct FromTypeToType <int ,std::complex <long double > > : public boost::true_type {};
116125
117126 template <> struct FromTypeToType <long ,float > : public boost::true_type {};
127+ template <> struct FromTypeToType <long ,std::complex <float > > : public boost::true_type {};
118128 template <> struct FromTypeToType <long ,double > : public boost::true_type {};
129+ template <> struct FromTypeToType <long ,std::complex <double > > : public boost::true_type {};
130+ template <> struct FromTypeToType <long ,long double > : public boost::true_type {};
131+ template <> struct FromTypeToType <long ,std::complex <long double > > : public boost::true_type {};
119132
133+ template <> struct FromTypeToType <float ,std::complex <float > > : public boost::true_type {};
120134 template <> struct FromTypeToType <float ,double > : public boost::true_type {};
135+ template <> struct FromTypeToType <float ,std::complex <double > > : public boost::true_type {};
136+ template <> struct FromTypeToType <float ,long double > : public boost::true_type {};
137+ template <> struct FromTypeToType <float ,std::complex <long double > > : public boost::true_type {};
138+
139+ template <> struct FromTypeToType <double ,std::complex <double > > : public boost::true_type {};
140+ template <> struct FromTypeToType <double ,long double > : public boost::true_type {};
141+ template <> struct FromTypeToType <double ,std::complex <long double > > : public boost::true_type {};
121142
122143 namespace bp = boost::python;
123144
@@ -282,6 +303,34 @@ namespace eigenpy
282303 }
283304 }
284305 };
306+
307+ template <typename Scalar, typename NewScalar, bool cast_is_valid = FromTypeToType<Scalar,NewScalar>::value >
308+ struct CastMatToMat
309+ {
310+ template <typename MatrixIn, typename MatrixOut>
311+ static void run (const Eigen::MatrixBase<MatrixIn> & input, const Eigen::MatrixBase<MatrixOut> & dest)
312+ {
313+ MatrixOut & dest_ = const_cast <MatrixOut &>(dest.derived ());
314+ dest_ = input.template cast <NewScalar>();
315+ }
316+ };
317+
318+ template <typename Scalar, typename NewScalar>
319+ struct CastMatToMat <Scalar,NewScalar,false >
320+ {
321+ template <typename MatrixIn, typename MatrixOut>
322+ static void run (const Eigen::MatrixBase<MatrixIn> & /* input*/ ,
323+ const Eigen::MatrixBase<MatrixOut> & /* dest*/ )
324+ {
325+ // do nothing
326+ }
327+ };
328+
329+ #define EIGENPY_CAST_FROM_PYARRAY_TO_EIGEN_MATRIX (MatType,Scalar,NewScalar,pyArray,mat ) \
330+ CastMatToMat<Scalar,NewScalar>::run(MapNumpy<MatType,Scalar>::map(pyArray),mat)
331+
332+ #define EIGENPY_CAST_FROM_EIGEN_MATRIX_TO_PYARRAY (MatType,Scalar,NewScalar,mat,pyArray ) \
333+ CastMatToMat<Scalar,NewScalar>::run(mat,MapNumpy<MatType,NewScalar>::map(pyArray))
285334
286335 template <typename MatType>
287336 struct EigenObjectAllocator
@@ -292,35 +341,43 @@ namespace eigenpy
292341 static void allocate (PyArrayObject * pyArray, void * storage)
293342 {
294343 Type * mat_ptr = initEigenObject<Type>::run (pyArray,storage);
344+ Type & mat = *mat_ptr;
295345
296- if (NumpyEquivalentType<Scalar>::type_code == GET_PY_ARRAY_TYPE (pyArray))
297- {
298- *mat_ptr = MapNumpy<MatType,Scalar>::map (pyArray); // avoid useless cast
299- return ;
300- }
301-
302- if (GET_PY_ARRAY_TYPE (pyArray) == NPY_INT)
346+ const int pyArray_Type = GET_PY_ARRAY_TYPE (pyArray);
347+ if (pyArray_Type == NumpyEquivalentType<Scalar>::type_code)
303348 {
304- *mat_ptr = MapNumpy<MatType,int >::map (pyArray). template cast <Scalar>();
349+ mat = MapNumpy<MatType,Scalar >::map (pyArray); // avoid useless cast
305350 return ;
306351 }
307352
308- if ( GET_PY_ARRAY_TYPE (pyArray) == NPY_LONG )
353+ switch (pyArray_Type )
309354 {
310- *mat_ptr = MapNumpy<MatType,long >::map (pyArray).template cast <Scalar>();
311- return ;
312- }
313-
314- if (GET_PY_ARRAY_TYPE (pyArray) == NPY_FLOAT)
315- {
316- *mat_ptr = MapNumpy<MatType,float >::map (pyArray).template cast <Scalar>();
317- return ;
318- }
319-
320- if (GET_PY_ARRAY_TYPE (pyArray) == NPY_DOUBLE)
321- {
322- *mat_ptr = MapNumpy<MatType,double >::map (pyArray).template cast <Scalar>();
323- return ;
355+ case NPY_INT:
356+ EIGENPY_CAST_FROM_PYARRAY_TO_EIGEN_MATRIX (MatType,int ,Scalar,pyArray,mat);
357+ break ;
358+ case NPY_LONG:
359+ EIGENPY_CAST_FROM_PYARRAY_TO_EIGEN_MATRIX (MatType,long ,Scalar,pyArray,mat);
360+ break ;
361+ case NPY_FLOAT:
362+ EIGENPY_CAST_FROM_PYARRAY_TO_EIGEN_MATRIX (MatType,float ,Scalar,pyArray,mat);
363+ break ;
364+ case NPY_CFLOAT:
365+ EIGENPY_CAST_FROM_PYARRAY_TO_EIGEN_MATRIX (MatType,std::complex <float >,Scalar,pyArray,mat);
366+ break ;
367+ case NPY_DOUBLE:
368+ EIGENPY_CAST_FROM_PYARRAY_TO_EIGEN_MATRIX (MatType,double ,Scalar,pyArray,mat);
369+ break ;
370+ case NPY_CDOUBLE:
371+ EIGENPY_CAST_FROM_PYARRAY_TO_EIGEN_MATRIX (MatType,std::complex <double >,Scalar,pyArray,mat);
372+ break ;
373+ case NPY_LONGDOUBLE:
374+ EIGENPY_CAST_FROM_PYARRAY_TO_EIGEN_MATRIX (MatType,long double ,Scalar,pyArray,mat);
375+ break ;
376+ case NPY_CLONGDOUBLE:
377+ EIGENPY_CAST_FROM_PYARRAY_TO_EIGEN_MATRIX (MatType,std::complex <long double >,Scalar,pyArray,mat);
378+ break ;
379+ default :
380+ throw Exception (" You asked for a conversion which is not implemented." );
324381 }
325382 }
326383
@@ -330,35 +387,42 @@ namespace eigenpy
330387 PyArrayObject * pyArray)
331388 {
332389 const MatrixDerived & mat = const_cast <const MatrixDerived &>(mat_.derived ());
390+ const int pyArray_Type = GET_PY_ARRAY_TYPE (pyArray);
333391
334- if (NumpyEquivalentType<Scalar>::type_code == GET_PY_ARRAY_TYPE (pyArray) )
392+ if (pyArray_Type == NumpyEquivalentType<Scalar>::type_code)
335393 {
336394 MapNumpy<MatType,Scalar>::map (pyArray) = mat; // no cast needed
337395 return ;
338396 }
339397
340- if (GET_PY_ARRAY_TYPE (pyArray) == NPY_INT)
341- {
342- MapNumpy<MatType,int >::map (pyArray) = mat.template cast <int >();
343- return ;
344- }
345-
346- if (GET_PY_ARRAY_TYPE (pyArray) == NPY_LONG)
347- {
348- MapNumpy<MatType,long >::map (pyArray) = mat.template cast <long >();
349- return ;
350- }
351-
352- if (GET_PY_ARRAY_TYPE (pyArray) == NPY_FLOAT)
353- {
354- MapNumpy<MatType,float >::map (pyArray) = mat.template cast <float >();
355- return ;
356- }
357-
358- if (GET_PY_ARRAY_TYPE (pyArray) == NPY_DOUBLE)
398+ switch (pyArray_Type)
359399 {
360- MapNumpy<MatType,double >::map (pyArray) = mat.template cast <double >();
361- return ;
400+ case NPY_INT:
401+ EIGENPY_CAST_FROM_EIGEN_MATRIX_TO_PYARRAY (MatType,Scalar,int ,mat,pyArray);
402+ break ;
403+ case NPY_LONG:
404+ EIGENPY_CAST_FROM_EIGEN_MATRIX_TO_PYARRAY (MatType,Scalar,long ,mat,pyArray);
405+ break ;
406+ case NPY_FLOAT:
407+ EIGENPY_CAST_FROM_EIGEN_MATRIX_TO_PYARRAY (MatType,Scalar,float ,mat,pyArray);
408+ break ;
409+ case NPY_CFLOAT:
410+ EIGENPY_CAST_FROM_EIGEN_MATRIX_TO_PYARRAY (MatType,Scalar,std::complex <float >,mat,pyArray);
411+ break ;
412+ case NPY_DOUBLE:
413+ EIGENPY_CAST_FROM_EIGEN_MATRIX_TO_PYARRAY (MatType,Scalar,double ,mat,pyArray);
414+ break ;
415+ case NPY_CDOUBLE:
416+ EIGENPY_CAST_FROM_EIGEN_MATRIX_TO_PYARRAY (MatType,Scalar,std::complex <double >,mat,pyArray);
417+ break ;
418+ case NPY_LONGDOUBLE:
419+ EIGENPY_CAST_FROM_EIGEN_MATRIX_TO_PYARRAY (MatType,Scalar,long double ,mat,pyArray);
420+ break ;
421+ case NPY_CLONGDOUBLE:
422+ EIGENPY_CAST_FROM_EIGEN_MATRIX_TO_PYARRAY (MatType,Scalar,std::complex <long double >,mat,pyArray);
423+ break ;
424+ default :
425+ throw Exception (" You asked for a conversion which is not implemented." );
362426 }
363427 }
364428 };
@@ -437,8 +501,16 @@ namespace eigenpy
437501 return FromTypeToType<long ,typename MatType::Scalar>::value;
438502 case NPY_FLOAT:
439503 return FromTypeToType<float ,typename MatType::Scalar>::value;
504+ case NPY_CFLOAT:
505+ return FromTypeToType<std::complex <float >,typename MatType::Scalar>::value;
440506 case NPY_DOUBLE:
441507 return FromTypeToType<double ,typename MatType::Scalar>::value;
508+ case NPY_CDOUBLE:
509+ return FromTypeToType<std::complex <double >,typename MatType::Scalar>::value;
510+ case NPY_LONGDOUBLE:
511+ return FromTypeToType<long double ,typename MatType::Scalar>::value;
512+ case NPY_CLONGDOUBLE:
513+ return FromTypeToType<std::complex <long double >,typename MatType::Scalar>::value;
442514 default :
443515 return false ;
444516 }
0 commit comments