When assigning to a repeated index, a SparseMatrixCSC instead stores multiple assigned values. The last write should win, but with a sparse matrix the assignment corrupts the matrix:
julia> using SparseArrays
julia> A = spzeros(2, 2);
julia> A[[1, 1], 1] = [5.0, 6.0];
julia> Matrix(A)
2×2 Matrix{Float64}:
6.0 0.0
0.0 0.0
julia> A # incorrect value and number of stored entries
2×2 SparseMatrixCSC{Float64, Int64} with 2 stored entries:
5.0 ⋅
⋅ ⋅
julia> sum(A) # incorrect sum
11.0
julia> sum(Matrix(A))
6.0
julia> B = zeros(2, 2);
julia> B = zeros(2, 2);^C
julia> B[[1, 1], 1] = [5.0, 6.0];
julia> B
2×2 Matrix{Float64}:
6.0 0.0
0.0 0.0
Possible cause (AI-diagnosed)
setindex!(A::AbstractSparseMatrixCSC, V::AbstractVecOrMat, I, J) in sparsematrix.jl sorts I and J but assumes they contain no repeats. In the column merge
rowB = I[rowvalB[ptrB]] # two rows of B map to the same row of A: both are emitted
...
colptrA[col+1] = ptrS
colB += 1 # one column of B per distinct column of A: later duplicates in J are never visited
and the final _checkbuffers(A) only checks buffer lengths. A minimal fix is to fall back to the generic element-wise loop when !allunique(I) || !allunique(J) (which gives the Matrix semantics), or to throw an ArgumentError for repeated indices.
When assigning to a repeated index, a
SparseMatrixCSCinstead stores multiple assigned values. The last write should win, but with a sparse matrix the assignment corrupts the matrix:Possible cause (AI-diagnosed)
setindex!(A::AbstractSparseMatrixCSC, V::AbstractVecOrMat, I, J)insparsematrix.jlsortsIandJbut assumes they contain no repeats. In the column mergeand the final
_checkbuffers(A)only checks buffer lengths. A minimal fix is to fall back to the generic element-wise loop when!allunique(I) || !allunique(J)(which gives theMatrixsemantics), or to throw anArgumentErrorfor repeated indices.