diff --git a/include/eigenpy/eigen-allocator.hpp b/include/eigenpy/eigen-allocator.hpp index dc6a84ce43a61a5afeaf3b55a08717e475ff448f..343f76811e353a42a7cd6dcada9992007633f3dc 100644 --- a/include/eigenpy/eigen-allocator.hpp +++ b/include/eigenpy/eigen-allocator.hpp @@ -66,6 +66,17 @@ namespace eigenpy } } }; + + template<typename MatType> + bool check_swap(PyArrayObject * pyArray, + const Eigen::MatrixBase<MatType> & mat) + { + if(PyArray_NDIM(pyArray) == 0) return false; + if(mat.rows() == PyArray_DIMS(pyArray)[0]) + return false; + else + return true; + } template<typename Scalar, typename NewScalar, bool cast_is_valid = FromTypeToType<Scalar,NewScalar>::value > struct cast_matrix_or_array @@ -75,10 +86,7 @@ namespace eigenpy const Eigen::MatrixBase<MatrixOut> & dest) { MatrixOut & dest_ = const_cast<MatrixOut &>(dest.derived()); - if(dest.rows() == input.rows()) - dest_ = input.template cast<NewScalar>(); - else - dest_ = input.transpose().template cast<NewScalar>(); + dest_ = input.template cast<NewScalar>(); } }; @@ -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<Scalar,NewScalar>::run(NumpyMap<MatType,Scalar>::map(pyArray),mat) + details::cast_matrix_or_array<Scalar,NewScalar>::run(NumpyMap<MatType,Scalar>::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<Scalar,NewScalar>::run(mat,NumpyMap<MatType,NewScalar>::map(pyArray)) - + details::cast_matrix_or_array<Scalar,NewScalar>::run(mat,NumpyMap<MatType,NewScalar>::map(pyArray,details::check_swap(pyArray,mat))) + template<typename MatType> struct EigenAllocator { @@ -119,7 +127,7 @@ namespace eigenpy const int Scalar_type_code = Register::getTypeCode<Scalar>(); if(pyArray_type_code == Scalar_type_code) { - mat = NumpyMap<MatType,Scalar>::map(pyArray); // avoid useless cast + mat = NumpyMap<MatType,Scalar>::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<MatType,Scalar>::map(pyArray); - if(mat.rows() == map_pyArray.rows()) - map_pyArray = mat; - else - map_pyArray = mat.transpose(); + MapType map_pyArray = NumpyMap<MatType,Scalar>::map(pyArray,details::check_swap(pyArray,mat)); + map_pyArray = mat; return; } @@ -252,7 +257,7 @@ namespace eigenpy RefType & mat = *reinterpret_cast<RefType*>(raw_ptr); if(pyArray_type_code == Scalar_type_code) { - mat = NumpyMap<MatType,Scalar>::map(pyArray); // avoid useless cast + mat = NumpyMap<MatType,Scalar>::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<MatType,Scalar>::map(pyArray); // avoid useless cast + mat = NumpyMap<MatType,Scalar>::map(pyArray,details::check_swap(pyArray,mat)); // avoid useless cast return; } diff --git a/include/eigenpy/fwd.hpp b/include/eigenpy/fwd.hpp index 50a796e4ab634c070d09ab9b81e00571ec64416f..506a1d93a2b055b7914a59f8b2a784cef1ab8560 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 85902af4c071a79989675fd92f9f74457ecbef0a..ed8d846297ab5781c361355aca2bb28382f461dd 100644 --- a/include/eigenpy/numpy-map.hpp +++ b/include/eigenpy/numpy-map.hpp @@ -22,7 +22,7 @@ namespace eigenpy typedef NumpyMapTraits<MatType, InputScalar, AlignmentValue, Stride> 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<InputScalar,MatType::RowsAtCompileTime,MatType::ColsAtCompileTime,MatType::Options> EquivalentInputMatrixType; typedef Eigen::Map<EquivalentInputMatrixType,AlignmentValue,Stride> 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<InputScalar,MatType::RowsAtCompileTime,MatType::ColsAtCompileTime,MatType::Options> EquivalentInputMatrixType; typedef Eigen::Map<EquivalentInputMatrixType,AlignmentValue,Stride> 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 MatType, typename InputScalar, int AlignmentValue, typename Stride> typename NumpyMap<MatType,InputScalar,AlignmentValue,Stride>::EigenMap - NumpyMap<MatType,InputScalar,AlignmentValue,Stride>::map(PyArrayObject * pyArray) + NumpyMap<MatType,InputScalar,AlignmentValue,Stride>::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 ece564da23f2125b5baafca9dfed57e1ead1a402..7181063e5dd21f7b2cdff398cda4de8518c813e8 100644 --- a/include/eigenpy/user-type.hpp +++ b/include/eigenpy/user-type.hpp @@ -191,12 +191,12 @@ namespace eigenpy PyArray_DotFunc * dotfunc = &internal::SpecialMethods<Scalar>::dotfunc; // PyArray_CastFunc * cast = &internal::SpecialMethods<Scalar>::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 b7cbc593d5703e85a2d1f70de6b7f8efa8468155..ce8a1c191aafb95e000b85e4eb3d111d04f70fd1 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<double,6,6> Matrix6; eigenpy::enableEigenPySpecific<Matrix6>(); + + // Non-square matrix + typedef Eigen::Matrix<double,4,6> Matrix46; + eigenpy::enableEigenPySpecific<Matrix46>(); Eigen::MatrixXd (*naturalsXX)(int,int,bool) = naturals; Eigen::VectorXd (*naturalsX)(int,bool) = naturals;