Skip to content

Specialize Diagonal products and dot for adjoint/transpose of sparse matrices - #770

Open
ViralBShah wants to merge 1 commit into
mainfrom
vs/adjoint-diagonal-dot
Open

Specialize Diagonal products and dot for adjoint/transpose of sparse matrices#770
ViralBShah wants to merge 1 commit into
mainfrom
vs/adjoint-diagonal-dot

Conversation

@ViralBShah

Copy link
Copy Markdown
Member

Fixes #619 and #627. Both are cases where a lazy Adjoint/Transpose of a SparseMatrixCSC fell through to a generic method that ignores sparsity.

#619: A' * D and D * A' with D::Diagonal

Materialize the adjoint (O(nnz)) and reuse the existing CSC-times-Diagonal kernels, mirroring how A' * B is already handled for sparse B. The result stays a SparseMatrixCSC.

On released Julia 1.11 the generic fallback is ~300x slower than A * D (N=1000, density 0.1):

Call Julia 1.11 stdlib this PR
A * D 112 µs 143 µs
A' * D 34.6 ms 225 µs
D * A' 35.1 ms 264 µs

On current nightly the generic path already materializes the adjoint, so the gain there is only ~10%; the explicit methods make the fast path independent of LinearAlgebra internals and are worth backporting.

#627: dot(A', B) for sparse A, B

The existing wrapper method walks the stored entries of B and does a binary search into A' for each one. Replace it with a merge: walk the columns of B in order and keep one cursor per column of parent(A). Since the row index being sought in each column of the parent is nondecreasing, the cursors only move forward, giving O(nnz(A) + nnz(B) + n) time with O(n) extra memory and no O(nnz) temporary. dot(B, A') reaches the same kernel through the existing conj(dot(A', B)).

Call (N=1000, density 0.1) Julia 1.11 stdlib main (nightly) this PR
dot(copy(A'), A) 550 µs 606 µs 586 µs
dot(A', A) 28.4 ms 2.0 ms 975 µs

Tests cover both wrappers, real and complex eltypes, mixed eltypes, stored zeros, empty columns, non-square shapes, dimension errors, and timing guards. Full test suite passes on nightly and Test.detect_ambiguities(SparseArrays) remains empty.

🤖 Generated with Claude Code

https://claude.ai/code/session_01LgBHUw9Hp7YW5ub29B4R5y

…rse matrices

Fixes #619: `A' * D` and `D * A'` for a sparse `A` and `Diagonal` `D` fell
through to the generic `AbstractMatrix` product, ~300x slower than `A * D`
on Julia 1.11. Materialize the adjoint (O(nnz)) and reuse the existing
CSC-times-Diagonal kernels, mirroring how `A' * B` is handled for sparse `B`.

Fixes #627: `dot(A', B)` for sparse `A`, `B` walked the stored entries of `B`
and did a binary search into `A'` for each, ~50x slower than `dot(copy(A'), B)`
on Julia 1.11. Add a merge that walks the columns of `B` in order while
keeping one cursor per column of `parent(A)`, so it runs in
O(nnz(A) + nnz(B) + n) time with O(n) extra memory and no O(nnz) temporary.
`dot(B, A')` reaches the same kernel through the existing `conj(dot(A', B))`.

Tests cover both wrappers, real and complex eltypes, mixed eltypes, stored
zeros, empty columns, non-square shapes, dimension errors, and timing guards.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LgBHUw9Hp7YW5ub29B4R5y
@codecov

codecov Bot commented Sep 8, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 84.23%. Comparing base (53690b3) to head (e7f7f00).

Additional details and impacted files
@@            Coverage Diff             @@
##             main     #770      +/-   ##
==========================================
+ Coverage   84.19%   84.23%   +0.04%     
==========================================
  Files          13       13              
  Lines        9403     9428      +25     
==========================================
+ Hits         7917     7942      +25     
  Misses       1486     1486              

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Missing specialization of adjoint sparse matrix times Diagonal

1 participant