diff --git a/unittest/CMakeLists.txt b/unittest/CMakeLists.txt index 2c6942d738d1ef1f8582b85e5b728308ca60cad3..38b9adc4b4b797141d0f36a3b9fcbd4812e993de 100644 --- a/unittest/CMakeLists.txt +++ b/unittest/CMakeLists.txt @@ -1,6 +1,6 @@ # # Copyright (c) 2014-2019 CNRS -# Copyright (c) 2018-2019 INRIA +# Copyright (c) 2018-2020 INRIA # MACRO(ADD_LIB_UNIT_TEST test PKGS) @@ -31,12 +31,14 @@ ENDMACRO(ADD_LIB_UNIT_TEST) ADD_LIB_UNIT_TEST(matrix "eigen3") ADD_LIB_UNIT_TEST(geometry "eigen3") +ADD_LIB_UNIT_TEST(complex "eigen3") IF(NOT ${EIGEN3_VERSION} VERSION_LESS "3.2.0") ADD_LIB_UNIT_TEST(ref "eigen3") ENDIF() ADD_PYTHON_UNIT_TEST("py-matrix" "unittest/python/test_matrix.py" "unittest") ADD_PYTHON_UNIT_TEST("py-geometry" "unittest/python/test_geometry.py" "unittest") +ADD_PYTHON_UNIT_TEST("py-complex" "unittest/python/test_complex.py" "unittest") ADD_PYTHON_UNIT_TEST("py-switch" "unittest/python/test_switch.py" "python/eigenpy") SET_TESTS_PROPERTIES("py-switch" PROPERTIES DEPENDS ${PYWRAP}) diff --git a/unittest/complex.cpp b/unittest/complex.cpp new file mode 100644 index 0000000000000000000000000000000000000000..53048bcb022285499423fa88a91c673a936fe4c5 --- /dev/null +++ b/unittest/complex.cpp @@ -0,0 +1,79 @@ +/* + * Copyright 2020 INRIA + */ + +#include "eigenpy/eigenpy.hpp" + +namespace Eigen +{ + #define EIGEN_MAKE_TYPEDEFS(Type, TypeSuffix, Size, SizeSuffix) \ + /** \ingroup matrixtypedefs */ \ + typedef Matrix<Type, Size, Size> Matrix##SizeSuffix##TypeSuffix; \ + /** \ingroup matrixtypedefs */ \ + typedef Matrix<Type, Size, 1> Vector##SizeSuffix##TypeSuffix; \ + /** \ingroup matrixtypedefs */ \ + typedef Matrix<Type, 1, Size> RowVector##SizeSuffix##TypeSuffix; + + #define EIGEN_MAKE_FIXED_TYPEDEFS(Type, TypeSuffix, Size) \ + /** \ingroup matrixtypedefs */ \ + typedef Matrix<Type, Size, Dynamic> Matrix##Size##X##TypeSuffix; \ + /** \ingroup matrixtypedefs */ \ + typedef Matrix<Type, Dynamic, Size> Matrix##X##Size##TypeSuffix; + + #define EIGEN_MAKE_TYPEDEFS_ALL_SIZES(Type, TypeSuffix) \ + EIGEN_MAKE_TYPEDEFS(Type, TypeSuffix, 2, 2) \ + EIGEN_MAKE_TYPEDEFS(Type, TypeSuffix, 3, 3) \ + EIGEN_MAKE_TYPEDEFS(Type, TypeSuffix, 4, 4) \ + EIGEN_MAKE_TYPEDEFS(Type, TypeSuffix, Dynamic, X) \ + EIGEN_MAKE_FIXED_TYPEDEFS(Type, TypeSuffix, 2) \ + EIGEN_MAKE_FIXED_TYPEDEFS(Type, TypeSuffix, 3) \ + EIGEN_MAKE_FIXED_TYPEDEFS(Type, TypeSuffix, 4) + + EIGEN_MAKE_TYPEDEFS_ALL_SIZES(long double, ld) + EIGEN_MAKE_TYPEDEFS_ALL_SIZES(std::complex<long double>, cld) + + #undef EIGEN_MAKE_TYPEDEFS_ALL_SIZES + #undef EIGEN_MAKE_TYPEDEFS + #undef EIGEN_MAKE_FIXED_TYPEDEFS +} + +template<typename ComplexMatrix> +typename Eigen::Matrix<typename ComplexMatrix::RealScalar,ComplexMatrix::RowsAtCompileTime,ComplexMatrix::ColsAtCompileTime,ComplexMatrix::Options> +real(const Eigen::MatrixBase<ComplexMatrix> & complex_mat) +{ + return complex_mat.real(); +} + +template<typename ComplexMatrix> +typename Eigen::Matrix<typename ComplexMatrix::RealScalar,ComplexMatrix::RowsAtCompileTime,ComplexMatrix::ColsAtCompileTime,ComplexMatrix::Options> +imag(const Eigen::MatrixBase<ComplexMatrix> & complex_mat) +{ + return complex_mat.imag(); +} + +template<typename Scalar, int Rows, int Cols, int Options> +Eigen::Matrix<std::complex<Scalar>,Rows,Cols,Options> +ascomplex(const Eigen::Matrix<Scalar,Rows,Cols,Options> & mat) +{ + typedef Eigen::Matrix<std::complex<Scalar>,Rows,Cols,Options> ReturnType; + return ReturnType(mat); +} + +BOOST_PYTHON_MODULE(complex) +{ + using namespace Eigen; + namespace bp = boost::python; + eigenpy::enableEigenPy(); + + bp::def("ascomplex", ascomplex<float,Eigen::Dynamic,Eigen::Dynamic,0>); + bp::def("ascomplex", ascomplex<double,Eigen::Dynamic,Eigen::Dynamic,0>); + bp::def("ascomplex", ascomplex<long double,Eigen::Dynamic,Eigen::Dynamic,0>); + + bp::def("real", (MatrixXf (*)(const Eigen::MatrixBase<MatrixXcf> &))&real<MatrixXcf>); + bp::def("real", (MatrixXd (*)(const Eigen::MatrixBase<MatrixXcd> &))&real<MatrixXcd>); + bp::def("real", (MatrixXld (*)(const Eigen::MatrixBase<MatrixXcld> &))&real<MatrixXcld>); + + bp::def("imag", (MatrixXf (*)(const Eigen::MatrixBase<MatrixXcf> &))&imag<MatrixXcf>); + bp::def("imag", (MatrixXd (*)(const Eigen::MatrixBase<MatrixXcd> &))&imag<MatrixXcd>); + bp::def("imag", (MatrixXld (*)(const Eigen::MatrixBase<MatrixXcld> &))&imag<MatrixXcld>); +} diff --git a/unittest/python/test_complex.py b/unittest/python/test_complex.py new file mode 100644 index 0000000000000000000000000000000000000000..40ef195414912c7e605f2baf7d4404105eeacad9 --- /dev/null +++ b/unittest/python/test_complex.py @@ -0,0 +1,31 @@ +from __future__ import print_function + +import numpy as np +from complex import * + +switchToNumpyArray() + +rows = 10 +cols = 20 + +def test(dtype): + Z = np.zeros((rows,cols),dtype=dtype) + Z.real = np.random.rand(rows,cols) + Z.imag = np.random.rand(rows,cols) + + Z_real = real(Z) + assert (Z_real == Z.real).all() + Z_imag = imag(Z) + assert (Z_imag == Z.imag).all() + + Y = np.ones((rows,cols)) + Y_complex = ascomplex(Y) + assert (Y_complex.real == Y).all() + assert (Y_complex.imag == np.zeros((rows,cols))).all() + +# Float +test(np.csingle) +# Double +test(np.cdouble) +# Long Double +test(np.clongdouble)