Skip to content

Commit a9f6a4f

Browse files
authored
Merge pull request #437 from jcarpent/devel
Fix bug in Sparse module with zero-size matrices
2 parents 5ea4023 + 9f6fb97 commit a9f6a4f

File tree

7 files changed

+23
-7
lines changed

7 files changed

+23
-7
lines changed

.github/workflows/check-changelog.yml

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
name: Check-changelog
22
on:
33
pull_request:
4-
types: [assigned, opened, synchronize, reopened, labeled, unlabeled]
4+
types: [assigned, opened, synchronize, reopened, labeled, unlabeled, edited]
55
branches:
66
- devel
77
jobs:

CHANGELOG.md

+1
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
1616
### Fixed
1717
- Fix the issue of missing exposition of Eigen types with __int64 scalar type ([#426](https://github.com/stack-of-tasks/eigenpy/pull/426))
1818
- Fix namespace use in unittest/std_pair.cpp ([#429](https://github.com/stack-of-tasks/eigenpy/pull/429))
19+
- Fix case of zero-size sparse matrices ([#437](https://github.com/stack-of-tasks/eigenpy/pull/437))
1920

2021
## [3.3.0] - 2024-01-23
2122

cmake

Submodule cmake updated 1 file

include/eigenpy/scipy-allocator.hpp

+3
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,9 @@ struct scipy_allocator_impl_sparse_matrix {
8585
// scipy_sparse_matrix_type(*bp::make_tuple(0,0),**args);
8686
scipy_sparse_matrix = scipy_sparse_matrix_type(
8787
Eigen::Matrix<Scalar, Eigen::Dynamic, Eigen::Dynamic>(0, 0));
88+
} else if (mat.nonZeros() == 0) {
89+
scipy_sparse_matrix =
90+
scipy_sparse_matrix_type(bp::make_tuple(mat.rows(), mat.cols()));
8891
} else {
8992
scipy_sparse_matrix = scipy_sparse_matrix_type(bp::make_tuple(
9093
DataVector(data),

include/eigenpy/sparse/eigen-from-python.hpp

+9-2
Original file line numberDiff line numberDiff line change
@@ -146,8 +146,15 @@ void eigen_sparse_matrix_from_py_construct(
146146
const Eigen::Index m = bp::extract<Eigen::Index>(shape[0]),
147147
n = bp::extract<Eigen::Index>(shape[1]),
148148
nnz = bp::extract<Eigen::Index>(obj.attr("nnz"));
149-
MapMatOrRefType sparse_map(m, n, nnz, indptr.data(), indices.data(),
150-
data.data());
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);
151158

152159
new (raw_ptr) MatOrRefType(sparse_map);
153160
}

unittest/python/test_sparse_matrix.py

+6-2
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,7 @@
1616
v = sparse_matrix.vector1x1(2)
1717
assert v.toarray() == np.array([2])
1818

19-
size = 100
20-
diag_values = np.random.rand(100)
19+
diag_values = np.random.rand(10)
2120
diag_mat = sparse_matrix.diagonal(diag_values)
2221
assert (diag_mat.toarray() == np.diag(diag_values)).all()
2322

@@ -26,3 +25,8 @@
2625

2726
diag_mat_csr = csr_matrix(diag_mat)
2827
assert (sparse_matrix.copy(diag_mat_csr) != diag_mat_csr).nnz == 0
28+
29+
# test zero matrix
30+
zero_mat = csr_matrix(np.zeros((10, 1)))
31+
zero_mat_copy = sparse_matrix.copy(zero_mat)
32+
assert (zero_mat_copy != zero_mat).nnz == 0

unittest/sparse_matrix.cpp

+2-1
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,8 @@ Eigen::SparseMatrix<Scalar, Options> matrix1x1(const Scalar& value) {
2626

2727
template <typename Scalar, int Options>
2828
Eigen::SparseMatrix<Scalar, Options> diagonal(
29-
const Eigen::Ref<Eigen::Matrix<Scalar, Eigen::Dynamic, 1> >& diag_values) {
29+
const Eigen::Ref<const Eigen::Matrix<Scalar, Eigen::Dynamic, 1> >&
30+
diag_values) {
3031
typedef Eigen::SparseMatrix<Scalar, Options> ReturnType;
3132
ReturnType mat(diag_values.size(), diag_values.size());
3233
for (Eigen::Index k = 0; k < diag_values.size(); ++k)

0 commit comments

Comments
 (0)