numpy-map.hpp
Go to the documentation of this file.
1 /*
2  * Copyright 2014-2019, CNRS
3  * Copyright 2018-2023, INRIA
4  */
5 
6 #ifndef __eigenpy_numpy_map_hpp__
7 #define __eigenpy_numpy_map_hpp__
8 
9 #include "eigenpy/exception.hpp"
10 #include "eigenpy/fwd.hpp"
11 #include "eigenpy/stride.hpp"
12 
13 namespace eigenpy {
14 
15 template <typename MatType, typename InputScalar, int AlignmentValue,
16  typename Stride, bool IsVector = MatType::IsVectorAtCompileTime>
18 
19 template <typename EigenType, typename InputScalar, int AlignmentValue,
20  typename Stride,
21  typename BaseType = typename get_eigen_base_type<EigenType>::type>
23 
24 template <typename MatType, typename InputScalar, int AlignmentValue,
25  typename Stride>
26 struct numpy_map_impl<MatType, InputScalar, AlignmentValue, Stride,
27  Eigen::MatrixBase<MatType> >
28  : numpy_map_impl_matrix<MatType, InputScalar, AlignmentValue, Stride> {};
29 
30 template <typename MatType, typename InputScalar, int AlignmentValue,
31  typename Stride>
32 struct numpy_map_impl<const MatType, InputScalar, AlignmentValue, Stride,
33  const Eigen::MatrixBase<MatType> >
34  : numpy_map_impl_matrix<const MatType, InputScalar, AlignmentValue,
35  Stride> {};
36 
37 template <typename MatType, typename InputScalar, int AlignmentValue,
38  typename Stride>
39 struct numpy_map_impl_matrix<MatType, InputScalar, AlignmentValue, Stride,
40  false> {
41  typedef Eigen::Matrix<InputScalar, MatType::RowsAtCompileTime,
42  MatType::ColsAtCompileTime, MatType::Options>
44  typedef Eigen::Map<EquivalentInputMatrixType, AlignmentValue, Stride>
46 
47  static EigenMap map(PyArrayObject* pyArray, bool swap_dimensions = false) {
48  enum {
49  OuterStrideAtCompileTime = Stride::OuterStrideAtCompileTime,
50  InnerStrideAtCompileTime = Stride::InnerStrideAtCompileTime,
51  };
52 
53  assert(PyArray_NDIM(pyArray) == 2 || PyArray_NDIM(pyArray) == 1);
54 
55  const long int itemsize = PyArray_ITEMSIZE(pyArray);
56  int inner_stride = -1, outer_stride = -1;
57  int rows = -1, cols = -1;
58  if (PyArray_NDIM(pyArray) == 2) {
59  assert((PyArray_DIMS(pyArray)[0] < INT_MAX) &&
60  (PyArray_DIMS(pyArray)[1] < INT_MAX) &&
61  (PyArray_STRIDE(pyArray, 0) < INT_MAX) &&
62  (PyArray_STRIDE(pyArray, 1) < INT_MAX));
63 
64  rows = (int)PyArray_DIMS(pyArray)[0];
65  cols = (int)PyArray_DIMS(pyArray)[1];
66 
67  if (EquivalentInputMatrixType::IsRowMajor) {
68  inner_stride = (int)PyArray_STRIDE(pyArray, 1) / (int)itemsize;
69  outer_stride = (int)PyArray_STRIDE(pyArray, 0) / (int)itemsize;
70  } else {
71  inner_stride = (int)PyArray_STRIDE(pyArray, 0) / (int)itemsize;
72  outer_stride = (int)PyArray_STRIDE(pyArray, 1) / (int)itemsize;
73  }
74  } else if (PyArray_NDIM(pyArray) == 1) {
75  assert((PyArray_DIMS(pyArray)[0] < INT_MAX) &&
76  (PyArray_STRIDE(pyArray, 0) < INT_MAX));
77 
78  if (!swap_dimensions) {
79  rows = (int)PyArray_DIMS(pyArray)[0];
80  cols = 1;
81 
82  if (EquivalentInputMatrixType::IsRowMajor) {
83  outer_stride = (int)PyArray_STRIDE(pyArray, 0) / (int)itemsize;
84  inner_stride = 0;
85  } else {
86  inner_stride = (int)PyArray_STRIDE(pyArray, 0) / (int)itemsize;
87  outer_stride = 0;
88  }
89  } else {
90  rows = 1;
91  cols = (int)PyArray_DIMS(pyArray)[0];
92 
93  if (EquivalentInputMatrixType::IsRowMajor) {
94  inner_stride = (int)PyArray_STRIDE(pyArray, 0) / (int)itemsize;
95  outer_stride = 0;
96  } else {
97  inner_stride = 0;
98  outer_stride = (int)PyArray_STRIDE(pyArray, 0) / (int)itemsize;
99  }
100  }
101  }
102 
103  // Specific care for Eigen::Stride<-1,0>
104  if (InnerStrideAtCompileTime == 0 &&
105  OuterStrideAtCompileTime == Eigen::Dynamic) {
106  outer_stride = std::max(inner_stride, outer_stride);
107  inner_stride = 0;
108  }
109 
110  Stride stride(
111  OuterStrideAtCompileTime == Eigen::Dynamic ? outer_stride
112  : OuterStrideAtCompileTime,
113  InnerStrideAtCompileTime == Eigen::Dynamic ? inner_stride
114  : InnerStrideAtCompileTime);
115 
116  if ((MatType::RowsAtCompileTime != rows) &&
117  (MatType::RowsAtCompileTime != Eigen::Dynamic)) {
118  throw eigenpy::Exception(
119  "The number of rows does not fit with the matrix type.");
120  }
121 
122  if ((MatType::ColsAtCompileTime != cols) &&
123  (MatType::ColsAtCompileTime != Eigen::Dynamic)) {
124  throw eigenpy::Exception(
125  "The number of columns does not fit with the matrix type.");
126  }
127 
128  InputScalar* pyData = reinterpret_cast<InputScalar*>(PyArray_DATA(pyArray));
129 
130  return EigenMap(pyData, rows, cols, stride);
131  }
132 };
133 
134 template <typename MatType, typename InputScalar, int AlignmentValue,
135  typename Stride>
136 struct numpy_map_impl_matrix<MatType, InputScalar, AlignmentValue, Stride,
137  true> {
138  typedef Eigen::Matrix<InputScalar, MatType::RowsAtCompileTime,
139  MatType::ColsAtCompileTime, MatType::Options>
141  typedef Eigen::Map<EquivalentInputMatrixType, AlignmentValue, Stride>
143 
144  static EigenMap map(PyArrayObject* pyArray, bool swap_dimensions = false) {
145  EIGENPY_UNUSED_VARIABLE(swap_dimensions);
146  assert(PyArray_NDIM(pyArray) <= 2);
147 
148  int rowMajor;
149  if (PyArray_NDIM(pyArray) == 1)
150  rowMajor = 0;
151  else if (PyArray_DIMS(pyArray)[0] == 0)
152  rowMajor = 0; // handle zero-size vector
153  else if (PyArray_DIMS(pyArray)[1] == 0)
154  rowMajor = 1; // handle zero-size vector
155  else
156  rowMajor = (PyArray_DIMS(pyArray)[0] > PyArray_DIMS(pyArray)[1]) ? 0 : 1;
157 
158  assert(PyArray_DIMS(pyArray)[rowMajor] < INT_MAX);
159  const int R = (int)PyArray_DIMS(pyArray)[rowMajor];
160  const long int itemsize = PyArray_ITEMSIZE(pyArray);
161  const int stride = (int)PyArray_STRIDE(pyArray, rowMajor) / (int)itemsize;
162 
163  if ((MatType::MaxSizeAtCompileTime != R) &&
164  (MatType::MaxSizeAtCompileTime != Eigen::Dynamic)) {
165  throw eigenpy::Exception(
166  "The number of elements does not fit with the vector type.");
167  }
168 
169  InputScalar* pyData = reinterpret_cast<InputScalar*>(PyArray_DATA(pyArray));
170 
171  assert(Stride(stride).inner() == stride &&
172  "Stride should be a dynamic stride");
173  return EigenMap(pyData, R, Stride(stride));
174  }
175 };
176 
177 #ifdef EIGENPY_WITH_TENSOR_SUPPORT
178 
179 template <typename TensorType, typename InputScalar, int AlignmentValue,
180  typename Stride>
181 struct numpy_map_impl_tensor;
182 
183 template <typename TensorType, typename InputScalar, int AlignmentValue,
184  typename Stride>
185 struct numpy_map_impl<TensorType, InputScalar, AlignmentValue, Stride,
186  Eigen::TensorBase<TensorType> >
187  : numpy_map_impl_tensor<TensorType, InputScalar, AlignmentValue, Stride> {};
188 
189 template <typename TensorType, typename InputScalar, int AlignmentValue,
190  typename Stride>
191 struct numpy_map_impl<const TensorType, InputScalar, AlignmentValue, Stride,
192  const Eigen::TensorBase<TensorType> >
193  : numpy_map_impl_tensor<const TensorType, InputScalar, AlignmentValue,
194  Stride> {};
195 
196 template <typename TensorType, typename InputScalar, int AlignmentValue,
197  typename Stride>
198 struct numpy_map_impl_tensor {
199  typedef TensorType Tensor;
200  typedef typename Eigen::internal::traits<TensorType>::Index Index;
201  static const int Options = Eigen::internal::traits<TensorType>::Options;
202  static const int NumIndices = TensorType::NumIndices;
203 
204  typedef Eigen::Tensor<InputScalar, NumIndices, Options, Index>
205  EquivalentInputTensorType;
206  typedef typename EquivalentInputTensorType::Dimensions Dimensions;
207  typedef Eigen::TensorMap<EquivalentInputTensorType, Options> EigenMap;
208 
209  static EigenMap map(PyArrayObject* pyArray, bool swap_dimensions = false) {
210  EIGENPY_UNUSED_VARIABLE(swap_dimensions);
211  assert(PyArray_NDIM(pyArray) == NumIndices || NumIndices == Eigen::Dynamic);
212 
213  Eigen::DSizes<Index, NumIndices> dimensions;
214  for (int k = 0; k < PyArray_NDIM(pyArray); ++k)
215  dimensions[k] = PyArray_DIMS(pyArray)[k];
216 
217  InputScalar* pyData = reinterpret_cast<InputScalar*>(PyArray_DATA(pyArray));
218  return EigenMap(pyData, dimensions);
219  }
220 };
221 #endif
222 
223 /* Wrap a numpy::array with an Eigen::Map. No memory copy. */
224 template <typename EigenType, typename InputScalar,
225  int AlignmentValue = EIGENPY_NO_ALIGNMENT_VALUE,
226  typename Stride = typename StrideType<EigenType>::type>
227 struct NumpyMap
228  : numpy_map_impl<EigenType, InputScalar, AlignmentValue, Stride> {};
229 
230 } // namespace eigenpy
231 
232 #endif // define __eigenpy_numpy_map_hpp__
#define EIGENPY_NO_ALIGNMENT_VALUE
Definition: fwd.hpp:104
Eigen::Matrix< InputScalar, MatType::RowsAtCompileTime, MatType::ColsAtCompileTime, MatType::Options > EquivalentInputMatrixType
Definition: numpy-map.hpp:43
Definition: complex.cpp:7
Eigen::Map< EquivalentInputMatrixType, AlignmentValue, Stride > EigenMap
Definition: numpy-map.hpp:142
static EigenMap map(PyArrayObject *pyArray, bool swap_dimensions=false)
Definition: numpy-map.hpp:47
stride_type< EigenType, InnerStride, OuterStride >::type type
Definition: stride.hpp:60
static EigenMap map(PyArrayObject *pyArray, bool swap_dimensions=false)
Definition: numpy-map.hpp:144
Eigen::Matrix< InputScalar, MatType::RowsAtCompileTime, MatType::ColsAtCompileTime, MatType::Options > EquivalentInputMatrixType
Definition: numpy-map.hpp:140
#define EIGENPY_UNUSED_VARIABLE(var)
Definition: fwd.hpp:106
Eigen::Map< EquivalentInputMatrixType, AlignmentValue, Stride > EigenMap
Definition: numpy-map.hpp:45
boost::mpl::if_< boost::is_const< typename boost::remove_reference< EigenType >::type >, const _type, _type >::type type
Definition: fwd.hpp:152


eigenpy
Author(s): Justin Carpentier, Nicolas Mansard
autogenerated on Fri Jun 2 2023 02:10:26