sparse/eigen-from-python.hpp
Go to the documentation of this file.
1 //
2 // Copyright (c) 2024-2025 INRIA
3 //
4 
5 #ifndef __eigenpy_sparse_eigen_from_python_hpp__
6 #define __eigenpy_sparse_eigen_from_python_hpp__
7 
8 #include "eigenpy/fwd.hpp"
10 #include "eigenpy/scipy-type.hpp"
12 
13 namespace eigenpy {
14 
15 template <typename SparseMatrixType>
16 struct expected_pytype_for_arg<SparseMatrixType,
17  Eigen::SparseMatrixBase<SparseMatrixType>> {
18  static PyTypeObject const *get_pytype() {
19  PyTypeObject const *py_type = ScipyType::get_pytype<SparseMatrixType>();
20  return py_type;
21  }
22 };
23 
24 } // namespace eigenpy
25 
26 namespace boost {
27 namespace python {
28 namespace converter {
29 
30 template <typename Scalar, int Options, typename StorageIndex>
31 struct expected_pytype_for_arg<
32  Eigen::SparseMatrix<Scalar, Options, StorageIndex>>
34  Eigen::SparseMatrix<Scalar, Options, StorageIndex>> {};
35 
36 template <typename Scalar, int Options, typename StorageIndex>
37 struct rvalue_from_python_data<
38  Eigen::SparseMatrix<Scalar, Options, StorageIndex> const &>
40  Eigen::SparseMatrix<Scalar, Options, StorageIndex> const &> {
41  typedef Eigen::SparseMatrix<Scalar, Options, StorageIndex> T;
43 };
44 
45 template <typename Derived>
46 struct rvalue_from_python_data<Eigen::SparseMatrixBase<Derived> const &>
47  : ::eigenpy::rvalue_from_python_data<Derived const &> {
49 };
50 
51 } // namespace converter
52 } // namespace python
53 } // namespace boost
54 
55 namespace boost {
56 namespace python {
57 namespace detail {
58 // template <typename TensorType>
59 // struct referent_storage<Eigen::TensorRef<TensorType> &> {
60 // typedef Eigen::TensorRef<TensorType> RefType;
61 // typedef ::eigenpy::details::referent_storage_eigen_ref<RefType>
62 // StorageType; typedef typename ::eigenpy::aligned_storage<
63 // referent_size<StorageType &>::value>::type type;
64 // };
65 
66 // template <typename TensorType>
67 // struct referent_storage<const Eigen::TensorRef<const TensorType> &> {
68 // typedef Eigen::TensorRef<const TensorType> RefType;
69 // typedef ::eigenpy::details::referent_storage_eigen_ref<RefType>
70 // StorageType; typedef typename ::eigenpy::aligned_storage<
71 // referent_size<StorageType &>::value>::type type;
72 // };
73 } // namespace detail
74 } // namespace python
75 } // namespace boost
76 
77 namespace eigenpy {
78 
79 template <typename SparseMatrixType>
80 struct eigen_from_py_impl<SparseMatrixType,
81  Eigen::SparseMatrixBase<SparseMatrixType>> {
82  typedef typename SparseMatrixType::Scalar Scalar;
83 
85  static void *convertible(PyObject *pyObj);
86 
88  static void construct(PyObject *pyObj,
89  bp::converter::rvalue_from_python_stage1_data *memory);
90 
91  static void registration();
92 };
93 
94 template <typename SparseMatrixType>
95 void *eigen_from_py_impl<
96  SparseMatrixType,
97  Eigen::SparseMatrixBase<SparseMatrixType>>::convertible(PyObject *pyObj) {
98  const PyTypeObject *type = Py_TYPE(pyObj);
99  const PyTypeObject *sparse_matrix_py_type =
100  ScipyType::get_pytype<SparseMatrixType>();
101  typedef typename SparseMatrixType::Scalar Scalar;
102 
103  if (type != sparse_matrix_py_type) return 0;
104 
105  bp::object obj(bp::handle<>(bp::borrowed(pyObj)));
106 
107  const int type_num = ScipyType::get_numpy_type_num(obj);
108 
109  if (!np_type_is_convertible_into_scalar<Scalar>(type_num)) return 0;
110 
111  return pyObj;
112 }
113 
114 template <typename MatOrRefType>
116  PyObject *pyObj, bp::converter::rvalue_from_python_stage1_data *memory) {
117  typedef typename MatOrRefType::Scalar Scalar;
118  typedef typename MatOrRefType::StorageIndex StorageIndex;
119 
120  typedef Eigen::Map<MatOrRefType> MapMatOrRefType;
121 
122  bp::converter::rvalue_from_python_storage<MatOrRefType> *storage =
123  reinterpret_cast<
124  bp::converter::rvalue_from_python_storage<MatOrRefType> *>(
125  reinterpret_cast<void *>(memory));
126  void *raw_ptr = storage->storage.bytes;
127 
128  bp::object obj(bp::handle<>(bp::borrowed(pyObj)));
129 
130  const int type_num_python_sparse_matrix = ScipyType::get_numpy_type_num(obj);
131  const int type_num_eigen_sparse_matrix = Register::getTypeCode<Scalar>();
132 
133  if (type_num_eigen_sparse_matrix == type_num_python_sparse_matrix) {
134  typedef Eigen::Matrix<Scalar, Eigen::Dynamic, 1> DataVector;
135  // typedef const Eigen::Ref<const DataVector> RefDataVector;
136  DataVector data = bp::extract<DataVector>(obj.attr("data"));
137  bp::tuple shape = bp::extract<bp::tuple>(obj.attr("shape"));
138  typedef Eigen::Matrix<StorageIndex, Eigen::Dynamic, 1> StorageIndexVector;
139  // typedef const Eigen::Ref<const StorageIndexVector>
140  // RefStorageIndexVector;
141  StorageIndexVector indices =
142  bp::extract<StorageIndexVector>(obj.attr("indices"));
143  StorageIndexVector indptr =
144  bp::extract<StorageIndexVector>(obj.attr("indptr"));
145 
146  const Eigen::Index m = bp::extract<Eigen::Index>(shape[0]),
147  n = bp::extract<Eigen::Index>(shape[1]),
148  nnz = bp::extract<Eigen::Index>(obj.attr("nnz"));
149 
150  // Handle the specific case of the null matrix
151  Scalar *data_ptr = nullptr;
152  StorageIndex *indices_ptr = nullptr;
153  if (nnz > 0) {
154  data_ptr = data.data();
155  indices_ptr = indices.data();
156  }
157  MapMatOrRefType sparse_map(m, n, nnz, indptr.data(), indices_ptr, data_ptr);
158 
159 #if EIGEN_VERSION_AT_LEAST(3, 4, 90)
160  sparse_map.sortInnerIndices();
161 #endif
162 
163  new (raw_ptr) MatOrRefType(sparse_map);
164  }
165 
166  memory->convertible = storage->storage.bytes;
167 }
168 
169 template <typename SparseMatrixType>
170 void eigen_from_py_impl<SparseMatrixType,
171  Eigen::SparseMatrixBase<SparseMatrixType>>::
172  construct(PyObject *pyObj,
173  bp::converter::rvalue_from_python_stage1_data *memory) {
174  eigen_sparse_matrix_from_py_construct<SparseMatrixType>(pyObj, memory);
175 }
176 
177 template <typename SparseMatrixType>
178 void eigen_from_py_impl<
179  SparseMatrixType,
180  Eigen::SparseMatrixBase<SparseMatrixType>>::registration() {
181  bp::converter::registry::push_back(
182  reinterpret_cast<void *(*)(_object *)>(&eigen_from_py_impl::convertible),
183  &eigen_from_py_impl::construct, bp::type_id<SparseMatrixType>()
184 #ifndef BOOST_PYTHON_NO_PY_SIGNATURES
185  ,
187 #endif
188  );
189 }
190 
191 template <typename SparseMatrixType>
192 struct eigen_from_py_converter_impl<SparseMatrixType,
193  Eigen::SparseMatrixBase<SparseMatrixType>> {
194  static void registration() {
196 
197  // Add conversion to Eigen::SparseMatrixBase<SparseMatrixType>
198  typedef Eigen::SparseMatrixBase<SparseMatrixType> SparseMatrixBase;
200 
201  // // Add conversion to Eigen::Ref<SparseMatrixType>
202  // typedef Eigen::Ref<SparseMatrixType> RefType;
203  // EigenFromPy<SparseMatrixType>::registration();
204  //
205  // // Add conversion to Eigen::Ref<const SparseMatrixType>
206  // typedef const Eigen::Ref<const SparseMatrixType> ConstRefType;
207  // EigenFromPy<ConstRefType>::registration();
208  }
209 };
210 
211 template <typename SparseMatrixType>
212 struct EigenFromPy<Eigen::SparseMatrixBase<SparseMatrixType>>
213  : EigenFromPy<SparseMatrixType> {
215  typedef Eigen::SparseMatrixBase<SparseMatrixType> Base;
216 
217  static void registration() {
218  bp::converter::registry::push_back(
219  reinterpret_cast<void *(*)(_object *)>(&EigenFromPy::convertible),
220  &EigenFromPy::construct, bp::type_id<Base>()
221 #ifndef BOOST_PYTHON_NO_PY_SIGNATURES
222  ,
224 #endif
225  );
226  }
227 };
228 //
229 // template <typename TensorType>
230 // struct EigenFromPy<Eigen::TensorRef<TensorType> > {
231 // typedef Eigen::TensorRef<TensorType> RefType;
232 // typedef typename TensorType::Scalar Scalar;
233 //
234 // /// \brief Determine if pyObj can be converted into a MatType object
235 // static void *convertible(PyObject *pyObj) {
236 // if (!call_PyArray_Check(pyObj)) return 0;
237 // PyArrayObject *pyArray = reinterpret_cast<PyArrayObject *>(pyObj);
238 // if (!PyArray_ISWRITEABLE(pyArray)) return 0;
239 // return EigenFromPy<TensorType>::convertible(pyObj);
240 // }
241 //
242 // static void registration() {
243 // bp::converter::registry::push_back(
244 // reinterpret_cast<void *(*)(_object *)>(&EigenFromPy::convertible),
245 // &eigen_from_py_construct<RefType>, bp::type_id<RefType>()
246 // #ifndef BOOST_PYTHON_NO_PY_SIGNATURES
247 // ,
248 // &eigenpy::expected_pytype_for_arg<TensorType>::get_pytype
249 // #endif
250 // );
251 // }
252 //};
253 
254 // template <typename TensorType>
255 // struct EigenFromPy<const Eigen::TensorRef<const TensorType> > {
256 // typedef const Eigen::TensorRef<const TensorType> ConstRefType;
257 // typedef typename TensorType::Scalar Scalar;
258 //
259 // /// \brief Determine if pyObj can be converted into a MatType object
260 // static void *convertible(PyObject *pyObj) {
261 // return EigenFromPy<TensorType>::convertible(pyObj);
262 // }
263 //
264 // static void registration() {
265 // bp::converter::registry::push_back(
266 // reinterpret_cast<void *(*)(_object *)>(&EigenFromPy::convertible),
267 // &eigen_from_py_construct<ConstRefType>, bp::type_id<ConstRefType>()
268 // #ifndef BOOST_PYTHON_NO_PY_SIGNATURES
269 // ,
270 // &eigenpy::expected_pytype_for_arg<TensorType>::get_pytype
271 // #endif
272 // );
273 // }
274 // };
275 
276 } // namespace eigenpy
277 
278 #endif // __eigenpy_sparse_eigen_from_python_hpp__
eigenpy::EigenFromPy< Eigen::SparseMatrixBase< SparseMatrixType > >::EigenFromPyDerived
EigenFromPy< SparseMatrixType > EigenFromPyDerived
Definition: sparse/eigen-from-python.hpp:214
Eigen
Definition: complex.cpp:7
eigenpy::eigen_from_py_impl< SparseMatrixType, Eigen::SparseMatrixBase< SparseMatrixType > >::Scalar
SparseMatrixType::Scalar Scalar
Definition: sparse/eigen-from-python.hpp:82
eigenpy::eigen_from_py_impl
Definition: eigen-from-python.hpp:266
eigenpy::eigen_from_py_impl::registration
static void registration()
EIGENPY_RVALUE_FROM_PYTHON_DATA_INIT
#define EIGENPY_RVALUE_FROM_PYTHON_DATA_INIT(type)
Definition: eigen-from-python.hpp:133
eigenpy::EigenFromPy
Definition: eigen-from-python.hpp:296
fwd.hpp
scalar-conversion.hpp
eigenpy::eigen_from_py_impl::convertible
static void * convertible(PyObject *pyObj)
Determine if pyObj can be converted into a MatType object.
setup.data
data
Definition: setup.in.py:48
eigenpy::expected_pytype_for_arg< SparseMatrixType, Eigen::SparseMatrixBase< SparseMatrixType > >::get_pytype
static const PyTypeObject * get_pytype()
Definition: sparse/eigen-from-python.hpp:18
boost
Definition: alignment.hpp:48
eigenpy::eigen_sparse_matrix_from_py_construct
void eigen_sparse_matrix_from_py_construct(PyObject *pyObj, bp::converter::rvalue_from_python_stage1_data *memory)
Definition: sparse/eigen-from-python.hpp:115
eigenpy::eigen_from_py_converter_impl< SparseMatrixType, Eigen::SparseMatrixBase< SparseMatrixType > >::registration
static void registration()
Definition: sparse/eigen-from-python.hpp:194
eigenpy
Definition: alignment.hpp:14
eigenpy::expected_pytype_for_arg
Definition: eigen-from-python.hpp:17
eigen-allocator.hpp
eigenpy::eigen_from_py_converter_impl
Definition: eigen-from-python.hpp:420
python
Definition: python.py:1
eigenpy::ScipyType::get_numpy_type_num
static int get_numpy_type_num(const bp::object &obj)
Definition: scipy-type.hpp:43
eigenpy::eigen_from_py_impl::construct
static void construct(PyObject *pyObj, bp::converter::rvalue_from_python_stage1_data *memory)
Allocate memory and copy pyObj in the new storage.
boost::python::converter::rvalue_from_python_data< Eigen::SparseMatrix< Scalar, Options, StorageIndex > const & >::T
Eigen::SparseMatrix< Scalar, Options, StorageIndex > T
Definition: sparse/eigen-from-python.hpp:41
eigenpy::EigenFromPy< Eigen::SparseMatrixBase< SparseMatrixType > >::Base
Eigen::SparseMatrixBase< SparseMatrixType > Base
Definition: sparse/eigen-from-python.hpp:215
eigenpy::rvalue_from_python_data
Definition: alignment.hpp:130
test_sparse_matrix.m
m
Definition: test_sparse_matrix.py:5
scipy-type.hpp
eigenpy::EigenFromPy< Eigen::SparseMatrixBase< SparseMatrixType > >::registration
static void registration()
Definition: sparse/eigen-from-python.hpp:217


eigenpy
Author(s): Justin Carpentier, Nicolas Mansard
autogenerated on Sat Apr 26 2025 02:17:29