Skip to content

Add isequal for adjoint/transpose of sparse matrices - #768

Merged
ViralBShah merged 1 commit into
mainfrom
vs/isequal-adjoint-sparse
Sep 8, 2026
Merged

Add isequal for adjoint/transpose of sparse matrices#768
ViralBShah merged 1 commit into
mainfrom
vs/isequal-adjoint-sparse

Conversation

@ViralBShah

Copy link
Copy Markdown
Member

Follow-up to #766, which added stored-entry-only isequal for SparseMatrixCSC and for the Adjoint/Transpose wrappers of sparse vectors, but not for the wrappers of sparse matrices. Those still fell back to the generic elementwise AbstractArray method even though == has dedicated methods for them.

On two 10^5 x 10^5 matrices with one stored entry each:

Call Before After
isequal(A', B') 14.1 s 0.2 ms
isequal(A, B') 14.1 s 0.1 ms

Changes:

  • Parameterize nzeq on the elementwise predicate and route the CSC-vs-wrapper == through the same _iseq(eq, A, B) helper introduced in Make isequal on sparse vectors and matrices walk stored entries only #766.
  • Add isequal methods for Adjoint/Transpose of sparse matrices mirroring the existing == ones.
  • Loosen the indexed argument of nzeq to AbstractMatrix. This also fixes a pre-existing MethodError in A' == transpose(B) for complex A: the adjoint of a transpose does not collapse for complex eltypes, so it yields a nested Adjoint{<:Any,<:Transpose} that the old one-level signature rejected. (Real eltypes were unaffected since adjoint(::Transpose{<:Real}) returns the parent.)
  • Tests cover all wrapper combinations, a timing guard, and cross-check isequal/== against Matrix for NaN, signed zeros, stored zeros, and conjugation.

Test.detect_ambiguities(SparseArrays) remains empty.

🤖 Generated with Claude Code

https://claude.ai/code/session_01LgBHUw9Hp7YW5ub29B4R5y

#766 added stored-entry-only `isequal` for `SparseMatrixCSC` and for the
`Adjoint`/`Transpose` wrappers of sparse vectors, but not for the wrappers of
sparse matrices, which still fell back to the generic elementwise
`AbstractArray` method. On two 10^5 x 10^5 matrices with one stored entry
each, `isequal(A', B')` took ~14s; it now matches `A' == B'` at ~0.2ms.

Parameterize `nzeq` on the elementwise predicate, mirror the `==` methods
for `Adjoint`/`Transpose` matrices with `isequal`, and loosen the indexed
argument of `nzeq` to `AbstractMatrix`. The latter also fixes a pre-existing
`MethodError` in `A' == transpose(B)` for complex `A`, where the adjoint of a
transpose does not collapse and yields a nested `Adjoint{<:Any,<:Transpose}`.

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.19%. Comparing base (2d29948) to head (dc76e14).

Additional details and impacted files
@@           Coverage Diff           @@
##             main     #768   +/-   ##
=======================================
  Coverage   84.19%   84.19%           
=======================================
  Files          13       13           
  Lines        9400     9403    +3     
=======================================
+ Hits         7914     7917    +3     
  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.

@ViralBShah
ViralBShah merged commit 53690b3 into main Sep 8, 2026
11 checks passed
@ViralBShah
ViralBShah deleted the vs/isequal-adjoint-sparse branch September 8, 2026 09:46
ViralBShah added a commit that referenced this pull request Sep 8, 2026
Follow-up to #766 and #768 (and item 6 of the test-time review).

The `@elapsed(...) < 0.1` assertions guarding the stored-entries-only
`isequal`/`==` paths are wall-clock thresholds, which are the main flake
risk on loaded CI runners. The matrix variants also build `10^5 x 10^5`
matrices (an 800 KB column-pointer array each) for seven wrapper
combinations.

They are replaced with a deterministic check. `sparsematrix_ops.jl`
already has a `Counting` eltype whose `==` increments a global counter;
this PR gives it `isequal` too and asserts that comparing two sparse
arrays performs at most `nnz(A) + nnz(B)` element comparisons. The
generic `AbstractArray` fallback would perform `length(A)` of them, so a
regression to it fails the test regardless of machine speed. The check
covers vectors, matrices, and all adjoint/transpose combinations, for
both `==` and `isequal`.

The existing NaN, signed-zero, stored-zero and dimension-mismatch
semantics tests are unchanged apart from running at small sizes.

#769 adds similar timing guards for `findprev` and `hash`; I'll convert
those the same way once it merges.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

https://claude.ai/code/session_01LgBHUw9Hp7YW5ub29B4R5y

Co-authored-by: Viral B. Shah <ViralBShah@users.noreply.github.com>
Co-authored-by: Claude Fable 5.1 <noreply@anthropic.com>
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