eigenpy 3.12.0
Bindings between Numpy and Eigen using Boost.Python
Loading...
Searching...
No Matches
eigen-to-python.hpp
1//
2// Copyright (c) 2014-2024 CNRS INRIA
3//
4
5#ifndef __eigenpy_eigen_to_python_hpp__
6#define __eigenpy_eigen_to_python_hpp__
7
8#include <boost/type_traits.hpp>
9
10#include "eigenpy/fwd.hpp"
11
12#include "eigenpy/eigen-allocator.hpp"
13#include "eigenpy/numpy-allocator.hpp"
14#include "eigenpy/scipy-allocator.hpp"
15#include "eigenpy/numpy-type.hpp"
16#include "eigenpy/scipy-type.hpp"
17#include "eigenpy/registration.hpp"
18
19namespace eigenpy {
20
21EIGENPY_DOCUMENTATION_START_IGNORE
22
23template <typename EigenType,
24 typename BaseType = typename get_eigen_base_type<EigenType>::type>
26
27template <typename MatType>
29
30template <typename MatType>
31struct eigen_to_py_impl<MatType, Eigen::MatrixBase<MatType>>
32 : eigen_to_py_impl_matrix<MatType> {};
33
34template <typename MatType>
35struct eigen_to_py_impl<MatType&, Eigen::MatrixBase<MatType>>
37
38template <typename MatType>
39struct eigen_to_py_impl<const MatType, const Eigen::MatrixBase<MatType>>
40 : eigen_to_py_impl_matrix<const MatType> {};
41
42template <typename MatType>
43struct eigen_to_py_impl<const MatType&, const Eigen::MatrixBase<MatType>>
45
46template <typename MatType>
48 static PyObject* convert(
49 typename boost::add_reference<
50 typename boost::add_const<MatType>::type>::type mat) {
51 typedef typename boost::remove_const<
52 typename boost::remove_reference<MatType>::type>::type MatrixDerived;
53
54 assert((mat.rows() < INT_MAX) && (mat.cols() < INT_MAX) &&
55 "Matrix range larger than int ... should never happen.");
56 const npy_intp R = (npy_intp)mat.rows(), C = (npy_intp)mat.cols();
57
58 PyArrayObject* pyArray;
59 // Allocate Python memory
60 if ((((!(C == 1) != !(R == 1)) && !MatrixDerived::IsVectorAtCompileTime) ||
61 MatrixDerived::IsVectorAtCompileTime)) // Handle array with a single
62 // dimension
63 {
64 npy_intp shape[1] = {C == 1 ? R : C};
66 const_cast<MatrixDerived&>(mat.derived()), 1, shape);
67 } else {
68 npy_intp shape[2] = {R, C};
70 const_cast<MatrixDerived&>(mat.derived()), 2, shape);
71 }
72
73 // Create an instance (either np.array or np.matrix)
74 return NumpyType::make(pyArray).ptr();
75 }
76
77 static PyTypeObject const* get_pytype() { return getPyArrayType(); }
78};
79
80template <typename MatType>
82
83template <typename MatType>
84struct eigen_to_py_impl<MatType, Eigen::SparseMatrixBase<MatType>>
86
87template <typename MatType>
88struct eigen_to_py_impl<MatType&, Eigen::SparseMatrixBase<MatType>>
90
91template <typename MatType>
92struct eigen_to_py_impl<const MatType, const Eigen::SparseMatrixBase<MatType>>
93 : eigen_to_py_impl_sparse_matrix<const MatType> {};
94
95template <typename MatType>
96struct eigen_to_py_impl<const MatType&, const Eigen::SparseMatrixBase<MatType>>
98
99template <typename MatType>
101 enum { IsRowMajor = MatType::IsRowMajor };
102
103 static PyObject* convert(
104 typename boost::add_reference<
105 typename boost::add_const<MatType>::type>::type mat) {
106 typedef typename boost::remove_const<
107 typename boost::remove_reference<MatType>::type>::type MatrixDerived;
108
109 // Allocate and perform the copy
110 PyObject* pyArray =
111 ScipyAllocator<MatType>::allocate(const_cast<MatrixDerived&>(mat));
112
113 return pyArray;
114 }
115
116 static PyTypeObject const* get_pytype() {
117 return IsRowMajor ? ScipyType::getScipyCSRMatrixType()
118 : ScipyType::getScipyCSCMatrixType();
119 }
120};
121
122#ifdef EIGENPY_WITH_TENSOR_SUPPORT
123template <typename TensorType>
124struct eigen_to_py_impl_tensor;
125
126template <typename TensorType>
127struct eigen_to_py_impl<TensorType, Eigen::TensorBase<TensorType>>
128 : eigen_to_py_impl_tensor<TensorType> {};
129
130template <typename TensorType>
131struct eigen_to_py_impl<const TensorType, const Eigen::TensorBase<TensorType>>
132 : eigen_to_py_impl_tensor<const TensorType> {};
133
134template <typename TensorType>
135struct eigen_to_py_impl_tensor {
136 static PyObject* convert(
137 typename boost::add_reference<
138 typename boost::add_const<TensorType>::type>::type tensor) {
139 // typedef typename boost::remove_const<
140 // typename boost::remove_reference<Tensor>::type>::type
141 // TensorDerived;
142
143 static const int NumIndices = TensorType::NumIndices;
144 npy_intp shape[NumIndices];
145 for (int k = 0; k < NumIndices; ++k) shape[k] = tensor.dimension(k);
146
147 PyArrayObject* pyArray = NumpyAllocator<TensorType>::allocate(
148 const_cast<TensorType&>(tensor), NumIndices, shape);
149
150 // Create an instance (either np.array or np.matrix)
151 return NumpyType::make(pyArray).ptr();
152 }
153
154 static PyTypeObject const* get_pytype() { return getPyArrayType(); }
155};
156#endif
157
158EIGENPY_DOCUMENTATION_END_IGNORE
159
160template <typename EigenType,
161 typename Scalar =
162 typename boost::remove_reference<EigenType>::type::Scalar>
163struct EigenToPy : eigen_to_py_impl<EigenType> {};
164
165template <typename MatType>
167 static void registration() {
168 bp::to_python_converter<MatType, EigenToPy<MatType>, true>();
169 }
170};
171
172} // namespace eigenpy
173
174namespace boost {
175namespace python {
176
177template <typename MatrixRef, class MakeHolder>
179 template <class U>
180 inline PyObject* operator()(U const& mat) const {
181 return eigenpy::EigenToPy<MatrixRef>::convert(const_cast<U&>(mat));
182 }
183
184#ifndef BOOST_PYTHON_NO_PY_SIGNATURES
185 inline PyTypeObject const* get_pytype() const {
186 return converter::registered_pytype<MatrixRef>::get_pytype();
187 }
188#endif
189};
190
191template <typename Scalar, int RowsAtCompileTime, int ColsAtCompileTime,
192 int Options, int MaxRowsAtCompileTime, int MaxColsAtCompileTime,
193 class MakeHolder>
194struct to_python_indirect<
195 Eigen::Matrix<Scalar, RowsAtCompileTime, ColsAtCompileTime, Options,
196 MaxRowsAtCompileTime, MaxColsAtCompileTime>&,
197 MakeHolder>
199 Eigen::Matrix<Scalar, RowsAtCompileTime, ColsAtCompileTime, Options,
200 MaxRowsAtCompileTime, MaxColsAtCompileTime>&,
201 MakeHolder> {};
202
203template <typename Scalar, int RowsAtCompileTime, int ColsAtCompileTime,
204 int Options, int MaxRowsAtCompileTime, int MaxColsAtCompileTime,
205 class MakeHolder>
206struct to_python_indirect<
207 const Eigen::Matrix<Scalar, RowsAtCompileTime, ColsAtCompileTime, Options,
208 MaxRowsAtCompileTime, MaxColsAtCompileTime>&,
209 MakeHolder>
211 const Eigen::Matrix<Scalar, RowsAtCompileTime, ColsAtCompileTime,
212 Options, MaxRowsAtCompileTime,
213 MaxColsAtCompileTime>&,
214 MakeHolder> {};
215
216} // namespace python
217} // namespace boost
218
219#endif // __eigenpy_eigen_to_python_hpp__