diff --git a/include/eigenpy/eigen-allocator.hpp b/include/eigenpy/eigen-allocator.hpp index 3cde4dd4de96b23b591070908a9e4627f6200cdf..1c4f8a647c1c6a273d29fbb6d12dcd24dcc11fe2 100644 --- a/include/eigenpy/eigen-allocator.hpp +++ b/include/eigenpy/eigen-allocator.hpp @@ -232,6 +232,22 @@ struct EigenAllocator { }; #if EIGEN_VERSION_AT_LEAST(3, 2, 0) +/// @brief Check if we need to allocate @tparam MatType to convert @param +/// pyArray. +/// @details do not allocate if: +/// want row-major & data C-contiguous OR +/// want col-major & data F-contiguous OR +/// you want a compile-time vector +/// in these cases, data layout fits desired view layout +template <typename MatType> +inline bool is_arr_layout_compatible_with_mat_type(PyArrayObject *pyArray) { + bool is_array_C_cont = PyArray_IS_C_CONTIGUOUS(pyArray); + bool is_array_F_cont = PyArray_IS_F_CONTIGUOUS(pyArray); + return (MatType::IsRowMajor && is_array_C_cont) || + (!MatType::IsRowMajor && is_array_F_cont) || + MatType::IsVectorAtCompileTime; +} + template <typename MatType, int Options, typename Stride> struct EigenAllocator<Eigen::Ref<MatType, Options, Stride> > { typedef Eigen::Ref<MatType, Options, Stride> RefType; @@ -255,14 +271,8 @@ struct EigenAllocator<Eigen::Ref<MatType, Options, Stride> > { const int pyArray_type_code = EIGENPY_GET_PY_ARRAY_TYPE(pyArray); const int Scalar_type_code = Register::getTypeCode<Scalar>(); if (pyArray_type_code != Scalar_type_code) need_to_allocate |= true; - if ((MatType::IsRowMajor && (PyArray_IS_C_CONTIGUOUS(pyArray) && - !PyArray_IS_F_CONTIGUOUS(pyArray))) || - (!MatType::IsRowMajor && (PyArray_IS_F_CONTIGUOUS(pyArray) && - !PyArray_IS_C_CONTIGUOUS(pyArray))) || - MatType::IsVectorAtCompileTime || - (PyArray_IS_F_CONTIGUOUS(pyArray) && - PyArray_IS_C_CONTIGUOUS(pyArray))) // no need to allocate - need_to_allocate |= false; + if (is_arr_layout_compatible_with_mat_type<MatType>(pyArray)) + need_to_allocate |= false; // no need to allocate else need_to_allocate |= true; if (Options != @@ -276,6 +286,10 @@ struct EigenAllocator<Eigen::Ref<MatType, Options, Stride> > { void *raw_ptr = storage->storage.bytes; if (need_to_allocate) { + PyObject *pyarr_transposed = PyArray_Transpose(pyArray, NULL); + allocate((PyArrayObject *)pyarr_transposed, storage); + /* + std::cout << " doing allocate\n"; MatType *mat_ptr; mat_ptr = details::init_matrix_or_array<MatType>::run(pyArray); RefType mat_ref(*mat_ptr); @@ -326,6 +340,7 @@ struct EigenAllocator<Eigen::Ref<MatType, Options, Stride> > { throw Exception( "You asked for a conversion which is not implemented."); } + */ } else { assert(pyArray_type_code == Scalar_type_code); typename NumpyMap<MatType, Scalar, Options, NumpyMapStride>::EigenMap @@ -365,14 +380,8 @@ struct EigenAllocator<const Eigen::Ref<const MatType, Options, Stride> > { const int Scalar_type_code = Register::getTypeCode<Scalar>(); if (pyArray_type_code != Scalar_type_code) need_to_allocate |= true; - if ((MatType::IsRowMajor && (PyArray_IS_C_CONTIGUOUS(pyArray) && - !PyArray_IS_F_CONTIGUOUS(pyArray))) || - (!MatType::IsRowMajor && (PyArray_IS_F_CONTIGUOUS(pyArray) && - !PyArray_IS_C_CONTIGUOUS(pyArray))) || - MatType::IsVectorAtCompileTime || - (PyArray_IS_F_CONTIGUOUS(pyArray) && - PyArray_IS_C_CONTIGUOUS(pyArray))) // no need to allocate - need_to_allocate |= false; + if (is_arr_layout_compatible_with_mat_type<MatType>(pyArray)) + need_to_allocate |= false; // no need to allocate else need_to_allocate |= true; if (Options != diff --git a/unittest/python/test_std_vector.py b/unittest/python/test_std_vector.py index 7f7c99a547b3d6c1079a461f0e7870d790370268..53121ec51c9cad805374f7eb9a377df153261def 100644 --- a/unittest/python/test_std_vector.py +++ b/unittest/python/test_std_vector.py @@ -76,9 +76,10 @@ print("-----------------") print("l3:") vector.setZero(l3) pprint.pp(list(l3)) -# checkZero(l3) +checkZero(l3) print("-----------------") print("l4:") vector.setZero(l4) pprint.pp(list(l4)) +checkZero(l4)