Skip to content

Add O(nnz) issymmetric, count, ==, reverse, circshift, permutedims and sort for views and lazy adjoints of sparse matrices - #1024

Merged
ViralBShah merged 2 commits into
mainfrom
vs/wrapper-view-fallbacks
Oct 12, 2026
Merged

ViralBShah merged 2 commits into
mainfrom
vs/wrapper-view-fallbacks

Conversation

@ViralBShah

Copy link
Copy Markdown
Member

A view or a lazy adjoint/transpose of a sparse matrix falls to the generic elementwise method for a number of functions that the matrix itself handles in O(nnz). Found in a soundness review of the whole package; this is the follow-up batch for elementwise fallbacks. These are new methods, not bug fixes.

n = 3000, about 15,000 stored entries, one timed call after warm-up, ms / bytes. The last column is the branch at n = 200,000 with about 10⁶ stored entries, which main cannot run in reasonable time.

Call main branch branch, 10⁶ entries
issymmetric(A') 41.3 / 0 0.03 / 24640 3.3 ms
issymmetric(view(A, :, vec)) 46.2 / 0 0.06 / 311552 13.4 ms
count(iszero, A') 44.9 / 0 0.00 / 0 0.14 ms
V == V', V = view(A, :, 1:n) 105.0 / 0 0.36 / 573824 51.5 ms
view(A, :, 1:n) + I 42.3 / 778496 0.10 / 659008 8.9 ms
reverse(A') 45.2 / 778496 0.05 / 286912 7.7 ms
reverse(view(A, :, vec); dims=1) 64.8 / 778496 0.08 / 286912 5.3 ms
rot180(A') 126.7 / 712960 0.06 / 286912 13.1 ms
rotl90(view(A, :, 1:n)) 123.2 / 778496 0.12 / 573824 12.9 ms
circshift(A', (1, 1)) 124.4 / 778496 0.11 / 573824 11.9 ms
permutedims(view(A, :, vec)) 112.9 / 778736 0.08 / 573824 6.5 ms
copy(reshape(A', n, n)) 136.1 / 778688 0.08 / 574016 6.5 ms
sort(A'; dims=1) about 19 s at n = 6000 0.24 / 286944 17.0 ms

count on an adjoint or transpose forwards to the parent with the wrapper composed into the predicate, and allocates nothing. issymmetric/ishermitian on an adjoint or transpose ask the parent; on a view they use the view where getcolptr works on it and its sparse copy otherwise. Everything else (==, isequal, reverse, rot180, rotl90, rotr90, circshift, permutedims, sort, copy of a 2-d reshape, and ± I on a view) takes the O(nnz) sparse copy of the argument and hands it to the existing SparseMatrixCSC kernel; the new allocations in the table are that copy. No dispatch alias is added: the methods are on SparseMatrixCSCSubArray and AdjOrTrans{<:Any,<:AbstractSparseMatrixCSC}, so they cover any 2-d view, row subsets included.

Touches dispatch throughout; each new method has a test that it is the one dispatched to. Not for backport.

Behaviour to know:

  • sort(X; dims) on a view or adjoint returns a SparseMatrixCSC, as sort(A) does; the generic method returned a ReshapedArray.
  • Results keep stored zeros, as the SparseMatrixCSC kernels do; the generic path dropped them. Values are equal.
  • isequal(V, V') for a complex view now agrees with isequal(A, A') on a plain sparse matrix, which treats the conjugate of an unstored zero as zero; dense gives false there because of -0.0im. == is unaffected.

Left out: an adjoint against an adjoint when one parent is a view (V' == A'), copy(V') for a view V, and copy(reshape(x, len)) to one dimension are still elementwise. issymmetric on view(A, :, 1:n), count on views, A' + I and A == A' were already O(nnz).

A ± I on a view checks squareness first, as on main; #1019 makes the plain-matrix method do the same.

Written by Claude Code.

🤖 Generated with Claude Code

…s`, `sort`, `issymmetric` and `count` on views and lazy adjoints of sparse matrices

The generic methods visit every entry. A 2-d view, or a lazy adjoint or transpose, of a
sparse matrix now goes through its O(nnz) sparse copy and the existing kernels, and
`issymmetric`, `ishermitian` and `count` on an adjoint or transpose use the parent in place.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@codecov

codecov Bot commented Oct 9, 2026 •

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 95.83333% with 2 lines in your changes missing coverage. Please review.
✅ Project coverage is 94.83%. Comparing base (5f40621) to head (f553257).
⚠️ Report is 8 commits behind head on main.

Files with missing lines Patch % Lines
src/sparsematrix.jl 95.83% 2 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main    #1024      +/-   ##
==========================================
- Coverage   95.63%   94.83%   -0.80%     
==========================================
  Files          16       16              
  Lines        9407     9790     +383     
==========================================
+ Hits         8996     9284     +288     
- Misses        411      506      +95     

☔ 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.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@ViralBShah
ViralBShah enabled auto-merge (squash) October 12, 2026 05:06
@ViralBShah
ViralBShah merged commit 37c1951 into main Oct 12, 2026
9 of 10 checks passed
@ViralBShah
ViralBShah deleted the vs/wrapper-view-fallbacks branch October 12, 2026 05:19
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.

1 participant