diff --git a/include/eigenpy/eigen-allocator.hpp b/include/eigenpy/eigen-allocator.hpp index dc6a84ce4..343f76811 100644 --- a/include/eigenpy/eigen-allocator.hpp +++ b/include/eigenpy/eigen-allocator.hpp @@ -66,6 +66,17 @@ namespace eigenpy } } }; + + template + bool check_swap(PyArrayObject * pyArray, + const Eigen::MatrixBase & mat) + { + if(PyArray_NDIM(pyArray) == 0) return false; + if(mat.rows() == PyArray_DIMS(pyArray)[0]) + return false; + else + return true; + } template::value > struct cast_matrix_or_array @@ -75,10 +86,7 @@ namespace eigenpy const Eigen::MatrixBase & dest) { MatrixOut & dest_ = const_cast(dest.derived()); - if(dest.rows() == input.rows()) - dest_ = input.template cast(); - else - dest_ = input.transpose().template cast(); + dest_ = input.template cast(); } }; @@ -97,11 +105,11 @@ namespace eigenpy } // namespace details #define EIGENPY_CAST_FROM_PYARRAY_TO_EIGEN_MATRIX(MatType,Scalar,NewScalar,pyArray,mat) \ - details::cast_matrix_or_array::run(NumpyMap::map(pyArray),mat) + details::cast_matrix_or_array::run(NumpyMap::map(pyArray,details::check_swap(pyArray,mat)),mat) #define EIGENPY_CAST_FROM_EIGEN_MATRIX_TO_PYARRAY(MatType,Scalar,NewScalar,mat,pyArray) \ - details::cast_matrix_or_array::run(mat,NumpyMap::map(pyArray)) - + details::cast_matrix_or_array::run(mat,NumpyMap::map(pyArray,details::check_swap(pyArray,mat))) + template struct EigenAllocator { @@ -119,7 +127,7 @@ namespace eigenpy const int Scalar_type_code = Register::getTypeCode(); if(pyArray_type_code == Scalar_type_code) { - mat = NumpyMap::map(pyArray); // avoid useless cast + mat = NumpyMap::map(pyArray,details::check_swap(pyArray,mat)); // avoid useless cast return; } @@ -167,11 +175,8 @@ namespace eigenpy if(pyArray_type_code == Scalar_type_code) // no cast needed { - MapType map_pyArray = NumpyMap::map(pyArray); - if(mat.rows() == map_pyArray.rows()) - map_pyArray = mat; - else - map_pyArray = mat.transpose(); + MapType map_pyArray = NumpyMap::map(pyArray,details::check_swap(pyArray,mat)); + map_pyArray = mat; return; } @@ -252,7 +257,7 @@ namespace eigenpy RefType & mat = *reinterpret_cast(raw_ptr); if(pyArray_type_code == Scalar_type_code) { - mat = NumpyMap::map(pyArray); // avoid useless cast + mat = NumpyMap::map(pyArray,details::check_swap(pyArray,mat)); // avoid useless cast return; } @@ -346,7 +351,7 @@ namespace eigenpy MatType & mat = *mat_ptr; if(pyArray_type_code == Scalar_type_code) { - mat = NumpyMap::map(pyArray); // avoid useless cast + mat = NumpyMap::map(pyArray,details::check_swap(pyArray,mat)); // avoid useless cast return; } diff --git a/include/eigenpy/fwd.hpp b/include/eigenpy/fwd.hpp index 50a796e4a..506a1d93a 100644 --- a/include/eigenpy/fwd.hpp +++ b/include/eigenpy/fwd.hpp @@ -22,6 +22,8 @@ #define EIGENPY_NO_ALIGNMENT_VALUE Eigen::Unaligned +#define EIGENPY_UNUSED_VARIABLE(var) (void)(var) + #include "eigenpy/expose.hpp" namespace eigenpy diff --git a/include/eigenpy/numpy-map.hpp b/include/eigenpy/numpy-map.hpp index 85902af4c..ed8d84629 100644 --- a/include/eigenpy/numpy-map.hpp +++ b/include/eigenpy/numpy-map.hpp @@ -22,7 +22,7 @@ namespace eigenpy typedef NumpyMapTraits Impl; typedef typename Impl::EigenMap EigenMap; - static EigenMap map(PyArrayObject* pyArray); + static EigenMap map(PyArrayObject* pyArray, bool swap_dimensions = false); }; } // namespace eigenpy @@ -39,7 +39,7 @@ namespace eigenpy typedef Eigen::Matrix EquivalentInputMatrixType; typedef Eigen::Map EigenMap; - static EigenMap mapImpl(PyArrayObject* pyArray) + static EigenMap mapImpl(PyArrayObject* pyArray, bool swap_dimensions = false) { enum { OuterStrideAtCompileTime = Stride::OuterStrideAtCompileTime, @@ -77,11 +77,22 @@ namespace eigenpy assert( (PyArray_DIMS(pyArray)[0] < INT_MAX) && (PyArray_STRIDE(pyArray,0) < INT_MAX)); - rows = (int)PyArray_DIMS(pyArray)[0]; - cols = 1; - - inner_stride = (int)PyArray_STRIDE(pyArray, 0) / (int)itemsize; - outer_stride = 0; + if(!swap_dimensions) + { + rows = (int)PyArray_DIMS(pyArray)[0]; + cols = 1; + + inner_stride = (int)PyArray_STRIDE(pyArray, 0) / (int)itemsize; + outer_stride = 0; + } + else + { + rows = 1; + cols = (int)PyArray_DIMS(pyArray)[0]; + + inner_stride = 0; + outer_stride = (int)PyArray_STRIDE(pyArray, 0) / (int)itemsize; + } } // Specific care for Eigen::Stride<-1,0> @@ -113,8 +124,9 @@ namespace eigenpy typedef Eigen::Matrix EquivalentInputMatrixType; typedef Eigen::Map EigenMap; - static EigenMap mapImpl(PyArrayObject* pyArray) + static EigenMap mapImpl(PyArrayObject* pyArray, bool swap_dimensions = false) { + EIGENPY_UNUSED_VARIABLE(swap_dimensions); assert( PyArray_NDIM(pyArray) <= 2 ); int rowMajor; @@ -141,9 +153,9 @@ namespace eigenpy template typename NumpyMap::EigenMap - NumpyMap::map(PyArrayObject * pyArray) + NumpyMap::map(PyArrayObject * pyArray, bool swap_dimensions) { - return Impl::mapImpl(pyArray); + return Impl::mapImpl(pyArray,swap_dimensions); } } // namespace eigenpy diff --git a/include/eigenpy/user-type.hpp b/include/eigenpy/user-type.hpp index ece564da2..7181063e5 100644 --- a/include/eigenpy/user-type.hpp +++ b/include/eigenpy/user-type.hpp @@ -191,12 +191,12 @@ namespace eigenpy PyArray_DotFunc * dotfunc = &internal::SpecialMethods::dotfunc; // PyArray_CastFunc * cast = &internal::SpecialMethods::cast; - int code = Register::registerNewType(py_type_ptr, - &typeid(Scalar), - sizeof(Scalar), - getitem, setitem, nonzero, - copyswap, copyswapn, - dotfunc); + int code = Register::registerNewType(py_type_ptr, + &typeid(Scalar), + sizeof(Scalar), + getitem, setitem, nonzero, + copyswap, copyswapn, + dotfunc); return code; } diff --git a/unittest/matrix.cpp b/unittest/matrix.cpp index b7cbc593d..ce8a1c191 100644 --- a/unittest/matrix.cpp +++ b/unittest/matrix.cpp @@ -94,8 +94,13 @@ BOOST_PYTHON_MODULE(matrix) namespace bp = boost::python; eigenpy::enableEigenPy(); + // Square matrix typedef Eigen::Matrix Matrix6; eigenpy::enableEigenPySpecific(); + + // Non-square matrix + typedef Eigen::Matrix Matrix46; + eigenpy::enableEigenPySpecific(); Eigen::MatrixXd (*naturalsXX)(int,int,bool) = naturals; Eigen::VectorXd (*naturalsX)(int,bool) = naturals;