sparse/eigen-from-python.hpp
Go to the documentation of this file.
1 //
2 // Copyright (c) 2024 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  new (raw_ptr) MatOrRefType(sparse_map);
160  }
161 
162  memory->convertible = storage->storage.bytes;
163 }
164 
165 template <typename SparseMatrixType>
166 void eigen_from_py_impl<SparseMatrixType,
167  Eigen::SparseMatrixBase<SparseMatrixType> >::
168  construct(PyObject *pyObj,
169  bp::converter::rvalue_from_python_stage1_data *memory) {
170  eigen_sparse_matrix_from_py_construct<SparseMatrixType>(pyObj, memory);
171 }
172 
173 template <typename SparseMatrixType>
174 void eigen_from_py_impl<
175  SparseMatrixType,
176  Eigen::SparseMatrixBase<SparseMatrixType> >::registration() {
177  bp::converter::registry::push_back(
178  reinterpret_cast<void *(*)(_object *)>(&eigen_from_py_impl::convertible),
179  &eigen_from_py_impl::construct, bp::type_id<SparseMatrixType>()
180 #ifndef BOOST_PYTHON_NO_PY_SIGNATURES
181  ,
183 #endif
184  );
185 }
186 
187 template <typename SparseMatrixType>
189  SparseMatrixType, Eigen::SparseMatrixBase<SparseMatrixType> > {
190  static void registration() {
192 
193  // Add conversion to Eigen::SparseMatrixBase<SparseMatrixType>
194  typedef Eigen::SparseMatrixBase<SparseMatrixType> SparseMatrixBase;
196 
197  // // Add conversion to Eigen::Ref<SparseMatrixType>
198  // typedef Eigen::Ref<SparseMatrixType> RefType;
199  // EigenFromPy<SparseMatrixType>::registration();
200  //
201  // // Add conversion to Eigen::Ref<const SparseMatrixType>
202  // typedef const Eigen::Ref<const SparseMatrixType> ConstRefType;
203  // EigenFromPy<ConstRefType>::registration();
204  }
205 };
206 
207 template <typename SparseMatrixType>
208 struct EigenFromPy<Eigen::SparseMatrixBase<SparseMatrixType> >
209  : EigenFromPy<SparseMatrixType> {
211  typedef Eigen::SparseMatrixBase<SparseMatrixType> Base;
212 
213  static void registration() {
214  bp::converter::registry::push_back(
215  reinterpret_cast<void *(*)(_object *)>(&EigenFromPy::convertible),
216  &EigenFromPy::construct, bp::type_id<Base>()
217 #ifndef BOOST_PYTHON_NO_PY_SIGNATURES
218  ,
220 #endif
221  );
222  }
223 };
224 //
225 // template <typename TensorType>
226 // struct EigenFromPy<Eigen::TensorRef<TensorType> > {
227 // typedef Eigen::TensorRef<TensorType> RefType;
228 // typedef typename TensorType::Scalar Scalar;
229 //
230 // /// \brief Determine if pyObj can be converted into a MatType object
231 // static void *convertible(PyObject *pyObj) {
232 // if (!call_PyArray_Check(pyObj)) return 0;
233 // PyArrayObject *pyArray = reinterpret_cast<PyArrayObject *>(pyObj);
234 // if (!PyArray_ISWRITEABLE(pyArray)) return 0;
235 // return EigenFromPy<TensorType>::convertible(pyObj);
236 // }
237 //
238 // static void registration() {
239 // bp::converter::registry::push_back(
240 // reinterpret_cast<void *(*)(_object *)>(&EigenFromPy::convertible),
241 // &eigen_from_py_construct<RefType>, bp::type_id<RefType>()
242 // #ifndef BOOST_PYTHON_NO_PY_SIGNATURES
243 // ,
244 // &eigenpy::expected_pytype_for_arg<TensorType>::get_pytype
245 // #endif
246 // );
247 // }
248 //};
249 
250 // template <typename TensorType>
251 // struct EigenFromPy<const Eigen::TensorRef<const TensorType> > {
252 // typedef const Eigen::TensorRef<const TensorType> ConstRefType;
253 // typedef typename TensorType::Scalar Scalar;
254 //
255 // /// \brief Determine if pyObj can be converted into a MatType object
256 // static void *convertible(PyObject *pyObj) {
257 // return EigenFromPy<TensorType>::convertible(pyObj);
258 // }
259 //
260 // static void registration() {
261 // bp::converter::registry::push_back(
262 // reinterpret_cast<void *(*)(_object *)>(&EigenFromPy::convertible),
263 // &eigen_from_py_construct<ConstRefType>, bp::type_id<ConstRefType>()
264 // #ifndef BOOST_PYTHON_NO_PY_SIGNATURES
265 // ,
266 // &eigenpy::expected_pytype_for_arg<TensorType>::get_pytype
267 // #endif
268 // );
269 // }
270 // };
271 
272 } // namespace eigenpy
273 
274 #endif // __eigenpy_sparse_eigen_from_python_hpp__
eigenpy::EigenFromPy< Eigen::SparseMatrixBase< SparseMatrixType > >::EigenFromPyDerived
EigenFromPy< SparseMatrixType > EigenFromPyDerived
Definition: sparse/eigen-from-python.hpp:210
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:190
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:211
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:213


eigenpy
Author(s): Justin Carpentier, Nicolas Mansard
autogenerated on Fri Apr 26 2024 02:17:35