diff --git a/.github/workflows/check-changelog.yml b/.github/workflows/check-changelog.yml index da9c25bd22696e6296371a35ca6bd19903e752dd..a4f874c0bd52d6e6086473935450759bf2ddc970 100644 --- a/.github/workflows/check-changelog.yml +++ b/.github/workflows/check-changelog.yml @@ -1,7 +1,7 @@ name: Check-changelog on: pull_request: - types: [assigned, opened, synchronize, reopened, labeled, unlabeled] + types: [assigned, opened, synchronize, reopened, labeled, unlabeled, edited] branches: - devel jobs: diff --git a/CHANGELOG.md b/CHANGELOG.md index 8c936ecb648c4db7910c4a98f7fd66fb5b87b59a..8d798ab4bcde00f75151bcd231fa3c66f23cd117 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,6 +16,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). ### Fixed - Fix the issue of missing exposition of Eigen types with __int64 scalar type ([#426](https://github.com/stack-of-tasks/eigenpy/pull/426)) - Fix namespace use in unittest/std_pair.cpp ([#429](https://github.com/stack-of-tasks/eigenpy/pull/429)) +- Fix case of zero-size sparse matrices ([#437](https://github.com/stack-of-tasks/eigenpy/pull/437)) ## [3.3.0] - 2024-01-23 diff --git a/cmake b/cmake index 0fa7e43f52b679c6f728ddaceb8783978d16885b..dd1d28f510754e85bf802189e29d601116df6699 160000 --- a/cmake +++ b/cmake @@ -1 +1 @@ -Subproject commit 0fa7e43f52b679c6f728ddaceb8783978d16885b +Subproject commit dd1d28f510754e85bf802189e29d601116df6699 diff --git a/include/eigenpy/scipy-allocator.hpp b/include/eigenpy/scipy-allocator.hpp index 848fd62f0b60b1fd39a42a46a53bb6f5b2591ca1..0f471b896d11df672552b75dcf96480139989353 100644 --- a/include/eigenpy/scipy-allocator.hpp +++ b/include/eigenpy/scipy-allocator.hpp @@ -85,6 +85,9 @@ struct scipy_allocator_impl_sparse_matrix { // scipy_sparse_matrix_type(*bp::make_tuple(0,0),**args); scipy_sparse_matrix = scipy_sparse_matrix_type( Eigen::Matrix<Scalar, Eigen::Dynamic, Eigen::Dynamic>(0, 0)); + } else if (mat.nonZeros() == 0) { + scipy_sparse_matrix = + scipy_sparse_matrix_type(bp::make_tuple(mat.rows(), mat.cols())); } else { scipy_sparse_matrix = scipy_sparse_matrix_type(bp::make_tuple( DataVector(data), diff --git a/include/eigenpy/sparse/eigen-from-python.hpp b/include/eigenpy/sparse/eigen-from-python.hpp index f5158a53f2e77cf08b6875e8568a9ee1958729ba..13c20f77972f556f18e2579b8ad1345e756d7e60 100644 --- a/include/eigenpy/sparse/eigen-from-python.hpp +++ b/include/eigenpy/sparse/eigen-from-python.hpp @@ -146,8 +146,15 @@ void eigen_sparse_matrix_from_py_construct( const Eigen::Index m = bp::extract<Eigen::Index>(shape[0]), n = bp::extract<Eigen::Index>(shape[1]), nnz = bp::extract<Eigen::Index>(obj.attr("nnz")); - MapMatOrRefType sparse_map(m, n, nnz, indptr.data(), indices.data(), - data.data()); + + // Handle the specific case of the null matrix + Scalar *data_ptr = nullptr; + StorageIndex *indices_ptr = nullptr; + if (nnz > 0) { + data_ptr = data.data(); + indices_ptr = indices.data(); + } + MapMatOrRefType sparse_map(m, n, nnz, indptr.data(), indices_ptr, data_ptr); new (raw_ptr) MatOrRefType(sparse_map); } diff --git a/unittest/python/test_sparse_matrix.py b/unittest/python/test_sparse_matrix.py index 428c3bede04d128226ab42a0677ab0bc21770022..3483dcb0fc2217e08841631860f6312fcf59a9c6 100644 --- a/unittest/python/test_sparse_matrix.py +++ b/unittest/python/test_sparse_matrix.py @@ -16,8 +16,7 @@ assert m.toarray() == np.array([2]) v = sparse_matrix.vector1x1(2) assert v.toarray() == np.array([2]) -size = 100 -diag_values = np.random.rand(100) +diag_values = np.random.rand(10) diag_mat = sparse_matrix.diagonal(diag_values) assert (diag_mat.toarray() == np.diag(diag_values)).all() @@ -26,3 +25,8 @@ assert (diag_mat_copy != diag_mat).nnz == 0 diag_mat_csr = csr_matrix(diag_mat) assert (sparse_matrix.copy(diag_mat_csr) != diag_mat_csr).nnz == 0 + +# test zero matrix +zero_mat = csr_matrix(np.zeros((10, 1))) +zero_mat_copy = sparse_matrix.copy(zero_mat) +assert (zero_mat_copy != zero_mat).nnz == 0 diff --git a/unittest/sparse_matrix.cpp b/unittest/sparse_matrix.cpp index e8e4b2d6048c4462da17a946eb95ab9135dfd8c8..6e9572473961d8dc56471c12b0f06967abeb6e9e 100644 --- a/unittest/sparse_matrix.cpp +++ b/unittest/sparse_matrix.cpp @@ -26,7 +26,8 @@ Eigen::SparseMatrix<Scalar, Options> matrix1x1(const Scalar& value) { template <typename Scalar, int Options> Eigen::SparseMatrix<Scalar, Options> diagonal( - const Eigen::Ref<Eigen::Matrix<Scalar, Eigen::Dynamic, 1> >& diag_values) { + const Eigen::Ref<const Eigen::Matrix<Scalar, Eigen::Dynamic, 1> >& + diag_values) { typedef Eigen::SparseMatrix<Scalar, Options> ReturnType; ReturnType mat(diag_values.size(), diag_values.size()); for (Eigen::Index k = 0; k < diag_values.size(); ++k)