Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions include/nanobind/eigen/sparse.h
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,10 @@ template <typename T> struct type_caster<T, enable_if_t<is_eigen_sparse_matrix_v
return false;
}

bool indices_sorted = cast<bool>(obj.attr("has_sorted_indices"));
if (!indices_sorted)
obj.attr("sort_indices")();

if (object data_o = obj.attr("data"); !data_caster.from_python(data_o, flags, cleanup))
return false;
ScalarNDArray& values = data_caster.value;
Expand Down
26 changes: 26 additions & 0 deletions tests/test_eigen.py
Original file line number Diff line number Diff line change
Expand Up @@ -231,6 +231,26 @@ def test07_mutate_arg():
assert_array_equal(A, 2*A2)


def create_spmat_unsorted():
import scipy.sparse as sparse
# Create a small matrix with explicit indices and indptr
data = np.array([1.0, 2.0, 3.0, 4.0, 5.0])

# Deliberately unsorted indices within columns
# For a properly sorted CSC matrix, indices should be sorted within each column
indices = np.array([0, 2, 1, 4, 3]) # Unsorted (should be [0, 1, 2, 3, 4])

# indptr points to where each column starts in the indices/data arrays
indptr = np.array([0, 2, 3, 5])

# Create a 5x3 matrix with unsorted indices
unsorted_csc = sparse.csc_matrix((data, indices, indptr), shape=(5, 3))

# Verify that indices are unsorted
assert not unsorted_csc.has_sorted_indices
return unsorted_csc


@needs_numpy_and_eigen
def test08_sparse():
pytest.importorskip("scipy")
Expand All @@ -244,6 +264,7 @@ def test08_sparse():
assert type(t.sparse_copy_r(t.sparse_c())) is scipy.sparse.csr_matrix
assert type(t.sparse_copy_c(t.sparse_r())) is scipy.sparse.csc_matrix


def assert_sparse_equal_ref(sparse_mat):
ref = np.array(
[
Expand All @@ -263,6 +284,11 @@ def assert_sparse_equal_ref(sparse_mat):
assert_sparse_equal_ref(t.sparse_copy_r(t.sparse_c()))
assert_sparse_equal_ref(t.sparse_copy_c(t.sparse_r()))

# construct scipy matrix with unsorted indices
assert type(t.sparse_copy_c(create_spmat_unsorted())) is scipy.sparse.csc_matrix
mat_unsort = create_spmat_unsorted()
assert_array_equal(t.sparse_copy_c(mat_unsort).toarray(), create_spmat_unsorted().toarray())


@needs_numpy_and_eigen
def test09_sparse_failures():
Expand Down
Loading