@@ -232,6 +232,22 @@ struct EigenAllocator {
232232};
233233
234234#if EIGEN_VERSION_AT_LEAST(3, 2, 0)
235+ // / @brief Check if we need to allocate @tparam MatType to convert @param
236+ // / pyArray.
237+ // / @details do not allocate if:
238+ // / want row-major & data C-contiguous OR
239+ // / want col-major & data F-contiguous OR
240+ // / you want a compile-time vector
241+ // / in these cases, data layout fits desired view layout
242+ template <typename MatType>
243+ inline bool is_arr_layout_compatible_with_mat_type (PyArrayObject *pyArray) {
244+ bool is_array_C_cont = PyArray_IS_C_CONTIGUOUS (pyArray);
245+ bool is_array_F_cont = PyArray_IS_F_CONTIGUOUS (pyArray);
246+ return (MatType::IsRowMajor && is_array_C_cont) ||
247+ (!MatType::IsRowMajor && is_array_F_cont) ||
248+ MatType::IsVectorAtCompileTime;
249+ }
250+
235251template <typename MatType, int Options, typename Stride>
236252struct EigenAllocator <Eigen::Ref<MatType, Options, Stride> > {
237253 typedef Eigen::Ref<MatType, Options, Stride> RefType;
@@ -255,16 +271,9 @@ struct EigenAllocator<Eigen::Ref<MatType, Options, Stride> > {
255271 const int pyArray_type_code = EIGENPY_GET_PY_ARRAY_TYPE (pyArray);
256272 const int Scalar_type_code = Register::getTypeCode<Scalar>();
257273 if (pyArray_type_code != Scalar_type_code) need_to_allocate |= true ;
258- if ((MatType::IsRowMajor && (PyArray_IS_C_CONTIGUOUS (pyArray) &&
259- !PyArray_IS_F_CONTIGUOUS (pyArray))) ||
260- (!MatType::IsRowMajor && (PyArray_IS_F_CONTIGUOUS (pyArray) &&
261- !PyArray_IS_C_CONTIGUOUS (pyArray))) ||
262- MatType::IsVectorAtCompileTime ||
263- (PyArray_IS_F_CONTIGUOUS (pyArray) &&
264- PyArray_IS_C_CONTIGUOUS (pyArray))) // no need to allocate
265- need_to_allocate |= false ;
266- else
267- need_to_allocate |= true ;
274+ bool incompatible_layout =
275+ !is_arr_layout_compatible_with_mat_type<MatType>(pyArray);
276+ need_to_allocate |= incompatible_layout;
268277 if (Options !=
269278 Eigen::Unaligned) // we need to check whether the memory is correctly
270279 // aligned and composed of a continuous segment
@@ -365,16 +374,9 @@ struct EigenAllocator<const Eigen::Ref<const MatType, Options, Stride> > {
365374 const int Scalar_type_code = Register::getTypeCode<Scalar>();
366375
367376 if (pyArray_type_code != Scalar_type_code) need_to_allocate |= true ;
368- if ((MatType::IsRowMajor && (PyArray_IS_C_CONTIGUOUS (pyArray) &&
369- !PyArray_IS_F_CONTIGUOUS (pyArray))) ||
370- (!MatType::IsRowMajor && (PyArray_IS_F_CONTIGUOUS (pyArray) &&
371- !PyArray_IS_C_CONTIGUOUS (pyArray))) ||
372- MatType::IsVectorAtCompileTime ||
373- (PyArray_IS_F_CONTIGUOUS (pyArray) &&
374- PyArray_IS_C_CONTIGUOUS (pyArray))) // no need to allocate
375- need_to_allocate |= false ;
376- else
377- need_to_allocate |= true ;
377+ bool incompatible_layout =
378+ !is_arr_layout_compatible_with_mat_type<MatType>(pyArray);
379+ need_to_allocate |= incompatible_layout;
378380 if (Options !=
379381 Eigen::Unaligned) // we need to check whether the memory is correctly
380382 // aligned and composed of a continuous segment
0 commit comments