numpy-allocator.hpp
Go to the documentation of this file.
1 /*
2  * Copyright 2020-2023 INRIA
3  */
4 
5 #ifndef __eigenpy_numpy_allocator_hpp__
6 #define __eigenpy_numpy_allocator_hpp__
7 
8 #include "eigenpy/fwd.hpp"
10 #include "eigenpy/numpy-type.hpp"
11 #include "eigenpy/register.hpp"
12 
13 namespace eigenpy {
14 
15 template <typename EigenType, typename BaseType>
17 
18 template <typename EigenType>
20 
21 template <typename MatType>
23  MatType, Eigen::MatrixBase<typename remove_const_reference<MatType>::type> >
24  : numpy_allocator_impl_matrix<MatType> {};
25 
26 template <typename MatType>
28  const MatType,
29  const Eigen::MatrixBase<typename remove_const_reference<MatType>::type> >
30  : numpy_allocator_impl_matrix<const MatType> {};
31 
32 // template <typename MatType>
33 // struct numpy_allocator_impl<MatType &, Eigen::MatrixBase<MatType> > :
34 // numpy_allocator_impl_matrix<MatType &>
35 //{};
36 
37 template <typename MatType>
38 struct numpy_allocator_impl<const MatType &, const Eigen::MatrixBase<MatType> >
40 
41 template <typename EigenType,
42  typename BaseType = typename get_eigen_base_type<EigenType>::type>
43 struct NumpyAllocator : numpy_allocator_impl<EigenType, BaseType> {};
44 
45 template <typename MatType>
47  template <typename SimilarMatrixType>
48  static PyArrayObject *allocate(
49  const Eigen::MatrixBase<SimilarMatrixType> &mat, npy_intp nd,
50  npy_intp *shape) {
51  typedef typename SimilarMatrixType::Scalar Scalar;
52 
53  const int code = Register::getTypeCode<Scalar>();
54  PyArrayObject *pyArray = (PyArrayObject *)call_PyArray_SimpleNew(
55  static_cast<int>(nd), shape, code);
56 
57  // Copy data
59 
60  return pyArray;
61  }
62 };
63 
64 #ifdef EIGENPY_WITH_TENSOR_SUPPORT
65 
66 template <typename TensorType>
67 struct numpy_allocator_impl_tensor;
68 
69 template <typename TensorType>
70 struct numpy_allocator_impl<TensorType, Eigen::TensorBase<TensorType> >
71  : numpy_allocator_impl_tensor<TensorType> {};
72 
73 template <typename TensorType>
74 struct numpy_allocator_impl<const TensorType,
75  const Eigen::TensorBase<TensorType> >
76  : numpy_allocator_impl_tensor<const TensorType> {};
77 
78 template <typename TensorType>
79 struct numpy_allocator_impl_tensor {
80  template <typename TensorDerived>
81  static PyArrayObject *allocate(const TensorDerived &tensor, npy_intp nd,
82  npy_intp *shape) {
83  const int code = Register::getTypeCode<typename TensorDerived::Scalar>();
84  PyArrayObject *pyArray = (PyArrayObject *)call_PyArray_SimpleNew(
85  static_cast<int>(nd), shape, code);
86 
87  // Copy data
89  static_cast<const TensorDerived &>(tensor), pyArray);
90 
91  return pyArray;
92  }
93 };
94 #endif
95 
96 template <typename MatType>
97 struct numpy_allocator_impl_matrix<MatType &> {
98  template <typename SimilarMatrixType>
99  static PyArrayObject *allocate(Eigen::PlainObjectBase<SimilarMatrixType> &mat,
100  npy_intp nd, npy_intp *shape) {
101  typedef typename SimilarMatrixType::Scalar Scalar;
102  enum {
103  NPY_ARRAY_MEMORY_CONTIGUOUS =
104  SimilarMatrixType::IsRowMajor ? NPY_ARRAY_CARRAY : NPY_ARRAY_FARRAY
105  };
106 
107  if (NumpyType::sharedMemory()) {
108  const int Scalar_type_code = Register::getTypeCode<Scalar>();
109  PyArrayObject *pyArray = (PyArrayObject *)call_PyArray_New(
110  getPyArrayType(), static_cast<int>(nd), shape, Scalar_type_code,
111  mat.data(), NPY_ARRAY_MEMORY_CONTIGUOUS | NPY_ARRAY_ALIGNED);
112 
113  return pyArray;
114  } else {
115  return NumpyAllocator<MatType>::allocate(mat, nd, shape);
116  }
117  }
118 };
119 
120 #if EIGEN_VERSION_AT_LEAST(3, 2, 0)
121 
122 template <typename MatType, int Options, typename Stride>
123 struct numpy_allocator_impl_matrix<Eigen::Ref<MatType, Options, Stride> > {
124  typedef Eigen::Ref<MatType, Options, Stride> RefType;
125 
126  static PyArrayObject *allocate(RefType &mat, npy_intp nd, npy_intp *shape) {
127  typedef typename RefType::Scalar Scalar;
128  enum {
129  NPY_ARRAY_MEMORY_CONTIGUOUS =
130  RefType::IsRowMajor ? NPY_ARRAY_CARRAY : NPY_ARRAY_FARRAY
131  };
132 
133  if (NumpyType::sharedMemory()) {
134  const int Scalar_type_code = Register::getTypeCode<Scalar>();
135  const bool reverse_strides = MatType::IsRowMajor || (mat.rows() == 1);
136  Eigen::DenseIndex inner_stride = reverse_strides ? mat.outerStride()
137  : mat.innerStride(),
138  outer_stride = reverse_strides ? mat.innerStride()
139  : mat.outerStride();
140 
141  const int elsize = call_PyArray_DescrFromType(Scalar_type_code)->elsize;
142  npy_intp strides[2] = {elsize * inner_stride, elsize * outer_stride};
143 
144  PyArrayObject *pyArray = (PyArrayObject *)call_PyArray_New(
145  getPyArrayType(), static_cast<int>(nd), shape, Scalar_type_code,
146  strides, mat.data(), NPY_ARRAY_MEMORY_CONTIGUOUS | NPY_ARRAY_ALIGNED);
147 
148  return pyArray;
149  } else {
150  return NumpyAllocator<MatType>::allocate(mat, nd, shape);
151  }
152  }
153 };
154 
155 #endif
156 
157 template <typename MatType>
158 struct numpy_allocator_impl_matrix<const MatType &> {
159  template <typename SimilarMatrixType>
160  static PyArrayObject *allocate(
161  const Eigen::PlainObjectBase<SimilarMatrixType> &mat, npy_intp nd,
162  npy_intp *shape) {
163  typedef typename SimilarMatrixType::Scalar Scalar;
164  enum {
165  NPY_ARRAY_MEMORY_CONTIGUOUS_RO = SimilarMatrixType::IsRowMajor
166  ? NPY_ARRAY_CARRAY_RO
167  : NPY_ARRAY_FARRAY_RO
168  };
169 
170  if (NumpyType::sharedMemory()) {
171  const int Scalar_type_code = Register::getTypeCode<Scalar>();
172  PyArrayObject *pyArray = (PyArrayObject *)call_PyArray_New(
173  getPyArrayType(), static_cast<int>(nd), shape, Scalar_type_code,
174  const_cast<Scalar *>(mat.data()),
175  NPY_ARRAY_MEMORY_CONTIGUOUS_RO | NPY_ARRAY_ALIGNED);
176 
177  return pyArray;
178  } else {
179  return NumpyAllocator<MatType>::allocate(mat, nd, shape);
180  }
181  }
182 };
183 
184 #if EIGEN_VERSION_AT_LEAST(3, 2, 0)
185 
186 template <typename MatType, int Options, typename Stride>
188  const Eigen::Ref<const MatType, Options, Stride> > {
189  typedef const Eigen::Ref<const MatType, Options, Stride> RefType;
190 
191  static PyArrayObject *allocate(RefType &mat, npy_intp nd, npy_intp *shape) {
192  typedef typename RefType::Scalar Scalar;
193  enum {
194  NPY_ARRAY_MEMORY_CONTIGUOUS_RO =
195  RefType::IsRowMajor ? NPY_ARRAY_CARRAY_RO : NPY_ARRAY_FARRAY_RO
196  };
197 
198  if (NumpyType::sharedMemory()) {
199  const int Scalar_type_code = Register::getTypeCode<Scalar>();
200 
201  const bool reverse_strides = MatType::IsRowMajor || (mat.rows() == 1);
202  Eigen::DenseIndex inner_stride = reverse_strides ? mat.outerStride()
203  : mat.innerStride(),
204  outer_stride = reverse_strides ? mat.innerStride()
205  : mat.outerStride();
206 
207  const int elsize = call_PyArray_DescrFromType(Scalar_type_code)->elsize;
208  npy_intp strides[2] = {elsize * inner_stride, elsize * outer_stride};
209 
210  PyArrayObject *pyArray = (PyArrayObject *)call_PyArray_New(
211  getPyArrayType(), static_cast<int>(nd), shape, Scalar_type_code,
212  strides, const_cast<Scalar *>(mat.data()),
213  NPY_ARRAY_MEMORY_CONTIGUOUS_RO | NPY_ARRAY_ALIGNED);
214 
215  return pyArray;
216  } else {
217  return NumpyAllocator<MatType>::allocate(mat, nd, shape);
218  }
219  }
220 };
221 
222 #endif
223 
224 #ifdef EIGENPY_WITH_TENSOR_SUPPORT
225 template <typename TensorType>
226 struct numpy_allocator_impl_tensor<Eigen::TensorRef<TensorType> > {
227  typedef Eigen::TensorRef<TensorType> RefType;
228 
229  static PyArrayObject *allocate(RefType &tensor, npy_intp nd,
230  npy_intp *shape) {
231  typedef typename RefType::Scalar Scalar;
232  static const bool IsRowMajor = TensorType::Options & Eigen::RowMajorBit;
233  enum {
234  NPY_ARRAY_MEMORY_CONTIGUOUS =
235  IsRowMajor ? NPY_ARRAY_CARRAY : NPY_ARRAY_FARRAY
236  };
237 
238  if (NumpyType::sharedMemory()) {
239  const int Scalar_type_code = Register::getTypeCode<Scalar>();
240  // static const Index NumIndices = TensorType::NumIndices;
241 
242  // const int elsize =
243  // call_PyArray_DescrFromType(Scalar_type_code)->elsize; npy_intp
244  // strides[NumIndices];
245 
246  PyArrayObject *pyArray = (PyArrayObject *)call_PyArray_New(
247  getPyArrayType(), static_cast<int>(nd), shape, Scalar_type_code, NULL,
248  const_cast<Scalar *>(tensor.data()),
249  NPY_ARRAY_MEMORY_CONTIGUOUS | NPY_ARRAY_ALIGNED);
250 
251  return pyArray;
252  } else {
253  return NumpyAllocator<TensorType>::allocate(tensor, nd, shape);
254  }
255  }
256 };
257 
258 template <typename TensorType>
259 struct numpy_allocator_impl_tensor<const Eigen::TensorRef<const TensorType> > {
260  typedef const Eigen::TensorRef<const TensorType> RefType;
261 
262  static PyArrayObject *allocate(RefType &tensor, npy_intp nd,
263  npy_intp *shape) {
264  typedef typename RefType::Scalar Scalar;
265  static const bool IsRowMajor = TensorType::Options & Eigen::RowMajorBit;
266  enum {
267  NPY_ARRAY_MEMORY_CONTIGUOUS_RO =
268  IsRowMajor ? NPY_ARRAY_CARRAY_RO : NPY_ARRAY_FARRAY_RO
269  };
270 
271  if (NumpyType::sharedMemory()) {
272  const int Scalar_type_code = Register::getTypeCode<Scalar>();
273 
274  PyArrayObject *pyArray = (PyArrayObject *)call_PyArray_New(
275  getPyArrayType(), static_cast<int>(nd), shape, Scalar_type_code, NULL,
276  const_cast<Scalar *>(tensor.data()),
277  NPY_ARRAY_MEMORY_CONTIGUOUS_RO | NPY_ARRAY_ALIGNED);
278 
279  return pyArray;
280  } else {
281  return NumpyAllocator<TensorType>::allocate(tensor, nd, shape);
282  }
283  }
284 };
285 
286 #endif
287 } // namespace eigenpy
288 
289 #endif // ifndef __eigenpy_numpy_allocator_hpp__
ReturnMatrix copy(const Eigen::MatrixBase< Matrix > &mat)
Definition: matrix.cpp:131
static PyArrayObject * allocate(Eigen::PlainObjectBase< SimilarMatrixType > &mat, npy_intp nd, npy_intp *shape)
static bool sharedMemory()
Definition: numpy-type.cpp:32
static PyArrayObject * allocate(const Eigen::MatrixBase< SimilarMatrixType > &mat, npy_intp nd, npy_intp *shape)
Definition: complex.cpp:7
PyObject * call_PyArray_SimpleNew(int nd, npy_intp *shape, int np_type)
Definition: numpy.hpp:140
static PyArrayObject * allocate(const Eigen::PlainObjectBase< SimilarMatrixType > &mat, npy_intp nd, npy_intp *shape)
PyObject * call_PyArray_New(PyTypeObject *py_type_ptr, int nd, npy_intp *shape, int np_type, void *data_ptr, int options)
Definition: numpy.hpp:144
PyTypeObject * getPyArrayType()
Definition: numpy.hpp:163
boost::mpl::if_< boost::is_const< typename boost::remove_reference< EigenType >::type >, const _type, _type >::type type
Definition: fwd.hpp:152
PyArray_Descr * call_PyArray_DescrFromType(int typenum)
Definition: numpy.hpp:165


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