7 #ifndef MDS_UTILS_PYTHON_UBLAS_MATRIX_SPARSE_HPP_INCLUDED 8 #define MDS_UTILS_PYTHON_UBLAS_MATRIX_SPARSE_HPP_INCLUDED 27 #include <mds_utils/python/ublas/detail/common.hpp> 31 #include <boost/numeric/ublas/matrix_sparse.hpp> 32 #include <boost/fusion/container/vector.hpp> 33 #include <boost/numeric/conversion/cast.hpp> 37 namespace mds_utils {
namespace python {
namespace ublas {
42 template<
class orientation_category>
43 struct scipy_sparse_mtx;
46 struct scipy_sparse_mtx<
boost::numeric::ublas::row_major_tag> {
48 static const std::string name;
51 const std::string scipy_sparse_mtx<boost::numeric::ublas::row_major_tag>::name(
"csr_matrix");
54 struct scipy_sparse_mtx<
boost::numeric::ublas::column_major_tag> {
56 static const std::string name;
59 const std::string scipy_sparse_mtx<boost::numeric::ublas::column_major_tag>::name(
"csc_matrix");
85 inline typename std::enable_if<
86 mds_utils::ublas::is_compressed_matrix<M>::value,M>::type
91 Obj module(PyImport_ImportModule(
"scipy.sparse"));
95 Obj type_obj(module.
attr(detail::scipy_sparse_mtx<
96 typename M::orientation_category>::name));
99 if (!PyType_Check(type_obj) ||
100 !PyObject_TypeCheck(po,
101 reinterpret_cast<PyTypeObject*>(static_cast<PyObject*>(type_obj)))) {
103 throw std::invalid_argument(
104 "Cannot get a uBLAS compressed matrix from the given parameter.\n" 105 "Check the data type and the storage layout (i.e. csr or csc).");
113 indices(o.
attr(
"indices")),
114 indptr(o.
attr(
"indptr"));
117 Nr(get<size_t>(shape[0])),
118 Nc(get<size_t>(shape[1])),
119 nnz(get<size_t>(o.
attr(
"nnz")));
121 if (Nr == 0 || Nc == 0)
return M();
126 it_data(reinterpret_cast<PyArrayObject*>(static_cast<PyObject*>(data))),
127 it_data_end(it_data,
true);
129 it_inds(reinterpret_cast<PyArrayObject*>(static_cast<PyObject*>(indices))),
130 it_inds_end(it_inds,
true),
131 it_indptr(reinterpret_cast<PyArrayObject*>(static_cast<PyObject*>(indptr))),
132 it_indptr_end(it_indptr,
true);
134 std::copy(it_data,it_data_end,mout.value_data().begin());
135 std::copy(it_inds,it_inds_end,mout.index2_data().begin());
136 std::copy(it_indptr,it_indptr_end,mout.index1_data().begin());
138 mout.set_filled(
len(indptr),
len(data));
158 template<
class ublas_mat_T>
159 inline typename std::enable_if<
160 mds_utils::ublas::is_compressed_matrix<ublas_mat_T>::value,
165 namespace fus = boost::fusion;
167 Obj module(PyImport_ImportModule(
"scipy.sparse"));
171 Obj type_obj(module.
attr(detail::scipy_sparse_mtx<
172 typename ublas_mat_T::orientation_category>::name));
174 if (!PyType_Check(type_obj)) {
176 throw std::runtime_error(
177 "Cannot create a " + detail::scipy_sparse_mtx<
178 typename ublas_mat_T::orientation_category>::name +
" object.");
182 flags(detail::numpy_flags<
183 typename ublas_mat_T::orientation_category>());
186 data_dims[] = {boost::numeric_cast<npy_intp>(mat.filled2())},
187 indptr_dims[] = {boost::numeric_cast<npy_intp>(mat.filled1())},
189 boost::numeric_cast<npy_intp>(mat.size1()),
190 boost::numeric_cast<npy_intp>(mat.size2())
194 *pdata(PyArray_New(&PyArray_Type,1,data_dims,
196 typename ublas_mat_T::value_type>::typenum,
197 NULL,NULL,0,flags,NULL)),
198 *pindices(PyArray_New(&PyArray_Type,1,data_dims,
200 NULL,NULL,0,flags,NULL)),
201 *pindptr(PyArray_New(&PyArray_Type,1,indptr_dims,
203 NULL,NULL,0,flags,NULL));
206 throw std::runtime_error(
"Could not create the data array.");
208 if (pindices == NULL) {
209 throw std::runtime_error(
"Could not create the indices array.");
211 if (pindptr == NULL) {
212 throw std::runtime_error(
"Could not create the indptr array.");
216 it_data(reinterpret_cast<PyArrayObject*>(pdata));
219 it_indices(reinterpret_cast<PyArrayObject*>(pindices)),
220 it_indptr(reinterpret_cast<PyArrayObject*>(pindptr));
223 typename ublas_mat_T::index_array_type::const_iterator
224 mat_it_indices(mat.index2_data().begin()),
225 mat_it_indptr(mat.index1_data().begin());
226 typename ublas_mat_T::value_array_type::const_iterator
227 mat_it_data(mat.value_data().begin());
229 for (k=0;k < *indptr_dims;++k,++mat_it_indptr,++it_indptr) {
230 *it_indptr = *mat_it_indptr;
232 for (k=0;k < *data_dims;++k,++mat_it_indices,++mat_it_data,++it_indices,++it_data) {
233 *it_indices = *mat_it_indices;
234 *it_data = *mat_it_data;
238 fus::vector<PyObject*,PyObject*,PyObject*>
239 mstruct(pdata,pindices,pindptr);
242 tup_mstruct,tup_sizes,tup_args;
244 tup_mstruct.
set(mstruct);
245 tup_sizes.
set(mat_shape,mat_shape+2);
248 args(tup_mstruct,tup_sizes);
252 Obj out_mtx(type_obj(tup_args));
Contains the wrapper for the NumPy iterator for ndarray objects.
Iterator on a NumPy ndarray.
Main namespace of all Michele De Stefano's C++ utilities.
Contains utilities for the Boost uBLAS library.
Contains a wrapper class for the Python tuple datatype.
void get_ownership()
Used in place of incref, when the wrapped PyObject* was increfed already.
size_t len(PyObject *o)
Retrieves the length of a sequence object.
Contains utilities for the creation of NumPy extensions.
virtual PyObject * transfer()
Returns the Python object with transferred ownership.
void set(const seq_T &seq)
Sets a Python sequence from a Boost Fusion sequence.
ProxyAttr attr(const std::string &name)
Retrieves an attribute.
std::enable_if< mds_utils::ublas::is_matrix< ublas_mat_T >::value, PyObject * >::type to_python(const ublas_mat_T &mat)
"To python" converter for Boost uBLAS matrices.
Provides traits for a specific C/C++ datatype.
This is a simple wrapper around the PyObject* datatype.