# Preserve sparse structure during in-place operations

**URL:** <https://discourse.julialang.org/t/preserve-sparse-structure-during-in-place-operations/127864>\
**Category:** Performance\
**Created:** [April 8, 2025, 8:17pm UTC](https://discourse.julialang.org/t/preserve-sparse-structure-during-in-place-operations/127864 "2025-04-08T20:17:13Z")\
**Posts on this page:** 2\
**Page:** 1

<div class="post-metadata">

**Author:** ![luke-kiernan](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/luke-kiernan/32/214309_2.png) [@luke-kiernan](https://discourse.julialang.org/u/luke-kiernan)\
**Post date:** [April 8, 2025, 8:17pm UTC](https://discourse.julialang.org/t/preserve-sparse-structure-during-in-place-operations/127864/1 "2025-04-08T20:17:13Z")

</div>

`SparseArrays` automatically runs `dropzeros!` after certain operations: for example,

```julia
using SparseArrays
A = spdiagm(ones(3))
println(nnz(A)) # result: 3
A .+= spdiagm(-1 .* ones(3))
println(nnz(A)) # result: 0

```

How can I prevent this from happening? Basically I want a version of `.+=` that does not change the sparsity structure of the left side.

The matrix `H` that I’m looking at is of the form `J' * J + c * I`, where `J` has fixed sparsity structure. I could work entry-by-entry: iterate through the columns of `J` as sparse vectors, compute pairwise dot products, and set the appropriate entries. But it seems like there should be a better way. (I care about performance: `J' * J` is almost certainly faster than explicitly computing dots products of pairs of columns.)

---

<div class="post-metadata">

**Author:** ![luke-kiernan](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/luke-kiernan/32/214309_2.png) [@luke-kiernan](https://discourse.julialang.org/u/luke-kiernan)\
**Post date:** [April 15, 2025, 2:00am UTC](https://discourse.julialang.org/t/preserve-sparse-structure-during-in-place-operations/127864/2 "2025-04-15T02:00:02Z")

</div>

Iterating thru the columns was too slow. The best workaround I’ve found is the following:

```julia
"""Does `A += B' * B`, in a way that preserves the sparse structure of `A`, if possible.
A workaround for the fact that Julia seems to run `dropzeros!(A)` automatically if I just 
do `A .+= B' * B`."""
function A_plus_eq_BT_B!(A::SparseMatrixCSC, B::SparseMatrixCSC)
    M = B' * B
    @assert M.colptr == A.colptr && M.rowval == A.rowval
    A.nzval .+= M.nzval
    return
end

```

In context, I know that `A`’s sparse structure will be identical to that of `B' * B`, so this does the job.
