Skip to content

Commit aa55845

Browse files
authored
Merge pull request #143 from jcarpent/devel
Support complex types + long double
2 parents 58f253a + 3d102a9 commit aa55845

File tree

6 files changed

+354
-52
lines changed

6 files changed

+354
-52
lines changed

include/eigenpy/details.hpp

Lines changed: 120 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
/*
22
* Copyright 2014-2019, CNRS
3-
* Copyright 2018-2019, INRIA
3+
* Copyright 2018-2020, INRIA
44
*/
55

66
#ifndef __eigenpy_details_hpp__
@@ -15,6 +15,7 @@
1515
#include "eigenpy/eigenpy.hpp"
1616
#include "eigenpy/registration.hpp"
1717
#include "eigenpy/map.hpp"
18+
#include "eigenpy/exception.hpp"
1819

1920
namespace boost { namespace python { namespace detail {
2021

@@ -99,11 +100,15 @@ struct implicit<MatType,Eigen::MatrixBase<MatType> >
99100
namespace 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

Comments
 (0)