.. _program_listing_file_include_eigenpy_numpy-map.hpp: Program Listing for File numpy-map.hpp ====================================== |exhale_lsh| :ref:`Return to documentation for file ` (``include/eigenpy/numpy-map.hpp``) .. |exhale_lsh| unicode:: U+021B0 .. UPWARDS ARROW WITH TIP LEFTWARDS .. code-block:: cpp /* * Copyright 2014-2019, CNRS * Copyright 2018-2023, INRIA */ #ifndef __eigenpy_numpy_map_hpp__ #define __eigenpy_numpy_map_hpp__ #include "eigenpy/exception.hpp" #include "eigenpy/fwd.hpp" #include "eigenpy/stride.hpp" namespace eigenpy { template struct numpy_map_impl_matrix; template ::type> struct numpy_map_impl; template struct numpy_map_impl > : numpy_map_impl_matrix {}; template struct numpy_map_impl > : numpy_map_impl_matrix {}; template struct numpy_map_impl_matrix { typedef Eigen::Matrix EquivalentInputMatrixType; typedef Eigen::Map EigenMap; static EigenMap map(PyArrayObject* pyArray, bool swap_dimensions = false) { enum { OuterStrideAtCompileTime = Stride::OuterStrideAtCompileTime, InnerStrideAtCompileTime = Stride::InnerStrideAtCompileTime, }; assert(PyArray_NDIM(pyArray) == 2 || PyArray_NDIM(pyArray) == 1); const long int itemsize = PyArray_ITEMSIZE(pyArray); int inner_stride = -1, outer_stride = -1; int rows = -1, cols = -1; if (PyArray_NDIM(pyArray) == 2) { assert((PyArray_DIMS(pyArray)[0] < INT_MAX) && (PyArray_DIMS(pyArray)[1] < INT_MAX) && (PyArray_STRIDE(pyArray, 0) < INT_MAX) && (PyArray_STRIDE(pyArray, 1) < INT_MAX)); rows = (int)PyArray_DIMS(pyArray)[0]; cols = (int)PyArray_DIMS(pyArray)[1]; if (EquivalentInputMatrixType::IsRowMajor) { inner_stride = (int)PyArray_STRIDE(pyArray, 1) / (int)itemsize; outer_stride = (int)PyArray_STRIDE(pyArray, 0) / (int)itemsize; } else { inner_stride = (int)PyArray_STRIDE(pyArray, 0) / (int)itemsize; outer_stride = (int)PyArray_STRIDE(pyArray, 1) / (int)itemsize; } } else if (PyArray_NDIM(pyArray) == 1) { assert((PyArray_DIMS(pyArray)[0] < INT_MAX) && (PyArray_STRIDE(pyArray, 0) < INT_MAX)); if (!swap_dimensions) { rows = (int)PyArray_DIMS(pyArray)[0]; cols = 1; if (EquivalentInputMatrixType::IsRowMajor) { outer_stride = (int)PyArray_STRIDE(pyArray, 0) / (int)itemsize; inner_stride = 0; } else { inner_stride = (int)PyArray_STRIDE(pyArray, 0) / (int)itemsize; outer_stride = 0; } } else { rows = 1; cols = (int)PyArray_DIMS(pyArray)[0]; if (EquivalentInputMatrixType::IsRowMajor) { inner_stride = (int)PyArray_STRIDE(pyArray, 0) / (int)itemsize; outer_stride = 0; } else { inner_stride = 0; outer_stride = (int)PyArray_STRIDE(pyArray, 0) / (int)itemsize; } } } // Specific care for Eigen::Stride<-1,0> if (InnerStrideAtCompileTime == 0 && OuterStrideAtCompileTime == Eigen::Dynamic) { outer_stride = std::max(inner_stride, outer_stride); inner_stride = 0; } Stride stride( OuterStrideAtCompileTime == Eigen::Dynamic ? outer_stride : OuterStrideAtCompileTime, InnerStrideAtCompileTime == Eigen::Dynamic ? inner_stride : InnerStrideAtCompileTime); if ((MatType::RowsAtCompileTime != rows) && (MatType::RowsAtCompileTime != Eigen::Dynamic)) { throw eigenpy::Exception( "The number of rows does not fit with the matrix type."); } if ((MatType::ColsAtCompileTime != cols) && (MatType::ColsAtCompileTime != Eigen::Dynamic)) { throw eigenpy::Exception( "The number of columns does not fit with the matrix type."); } InputScalar* pyData = reinterpret_cast(PyArray_DATA(pyArray)); return EigenMap(pyData, rows, cols, stride); } }; template struct numpy_map_impl_matrix { typedef Eigen::Matrix EquivalentInputMatrixType; typedef Eigen::Map EigenMap; static EigenMap map(PyArrayObject* pyArray, bool swap_dimensions = false) { EIGENPY_UNUSED_VARIABLE(swap_dimensions); assert(PyArray_NDIM(pyArray) <= 2); int rowMajor; if (PyArray_NDIM(pyArray) == 1) rowMajor = 0; else if (PyArray_DIMS(pyArray)[0] == 0) rowMajor = 0; // handle zero-size vector else if (PyArray_DIMS(pyArray)[1] == 0) rowMajor = 1; // handle zero-size vector else rowMajor = (PyArray_DIMS(pyArray)[0] > PyArray_DIMS(pyArray)[1]) ? 0 : 1; assert(PyArray_DIMS(pyArray)[rowMajor] < INT_MAX); const int R = (int)PyArray_DIMS(pyArray)[rowMajor]; const long int itemsize = PyArray_ITEMSIZE(pyArray); const int stride = (int)PyArray_STRIDE(pyArray, rowMajor) / (int)itemsize; if ((MatType::MaxSizeAtCompileTime != R) && (MatType::MaxSizeAtCompileTime != Eigen::Dynamic)) { throw eigenpy::Exception( "The number of elements does not fit with the vector type."); } InputScalar* pyData = reinterpret_cast(PyArray_DATA(pyArray)); assert(Stride(stride).inner() == stride && "Stride should be a dynamic stride"); return EigenMap(pyData, R, Stride(stride)); } }; #ifdef EIGENPY_WITH_TENSOR_SUPPORT template struct numpy_map_impl_tensor; template struct numpy_map_impl > : numpy_map_impl_tensor {}; template struct numpy_map_impl > : numpy_map_impl_tensor {}; template struct numpy_map_impl_tensor { typedef TensorType Tensor; typedef typename Eigen::internal::traits::Index Index; static const int Options = Eigen::internal::traits::Options; static const int NumIndices = TensorType::NumIndices; typedef Eigen::Tensor EquivalentInputTensorType; typedef typename EquivalentInputTensorType::Dimensions Dimensions; typedef Eigen::TensorMap EigenMap; static EigenMap map(PyArrayObject* pyArray, bool swap_dimensions = false) { EIGENPY_UNUSED_VARIABLE(swap_dimensions); assert(PyArray_NDIM(pyArray) == NumIndices || NumIndices == Eigen::Dynamic); Eigen::DSizes dimensions; for (int k = 0; k < PyArray_NDIM(pyArray); ++k) dimensions[k] = PyArray_DIMS(pyArray)[k]; InputScalar* pyData = reinterpret_cast(PyArray_DATA(pyArray)); return EigenMap(pyData, dimensions); } }; #endif /* Wrap a numpy::array with an Eigen::Map. No memory copy. */ template ::type> struct NumpyMap : numpy_map_impl {}; } // namespace eigenpy #endif // define __eigenpy_numpy_map_hpp__