Skip to content

Optional SparseMatrixCSR support via SparseMatricesCSR extension#36

Draft
ChrisRackauckas-Claude wants to merge 3 commits into
SciML:mainfrom
ChrisRackauckas-Claude:csr-extension
Draft

Optional SparseMatrixCSR support via SparseMatricesCSR extension#36
ChrisRackauckas-Claude wants to merge 3 commits into
SciML:mainfrom
ChrisRackauckas-Claude:csr-extension

Conversation

@ChrisRackauckas-Claude

@ChrisRackauckas-Claude ChrisRackauckas-Claude commented Jun 5, 2026

Copy link
Copy Markdown
Collaborator

Stacked on #35; optional — please ignore until reviewed by @ChrisRackauckas. This may not be merged.

Re-adds optional SparseMatrixCSR input support on top of the CSC-native core (#35), behind the SparseMatricesCSR weak-dep extension. The package core stays pure SparseMatrixCSC + SparseArrays; SparseMatricesCSR is only loaded when the user does using SparseMatricesCSR. The extension converts CSR → CSC and dispatches into the unchanged CSC kernel.

Review surface: GitHub can't base a cross-fork PR on a fork branch, so this PR targets main and therefore also shows #35's two commits. The only incremental change to review here is the top commit, "Re-add optional SparseMatrixCSR support via SparseMatricesCSR extension." It should land only after #35 is merged. The incremental diff (csc-native..csr-extension) is exactly the inverse of the CSR removal in #35.

Status / caveats (not addressed here — captured as TODO)

  1. Per-call reallocation. The current CSR path reconverts CSR → SparseMatrixCSC on every csr_refactor! call (~17 KB/call, ~1.8× slower than the native CSC path — see the benchmark comment on Make SparseMatrixCSC the native API #35). If this PR is pursued, csr_refactor! on a SparseMatrixCSR should reuse a cached CSC buffer instead of reconverting each call, so the refactor stays allocation-light like the native CSC path.

  2. Zero-copy CSR / transpose fast-path (the principled motivation). CSR is the natural representation for transpose/adjoint factorization: SparseMatrixCSR(A) is structurally identical to SparseMatrixCSC(Aᵀ) (same rowptr/colval/nzvalcolptr/rowval/nzval arrays). So a future zero-copy fast path could reinterpret the CSR arrays as the transpose's CSC with no copy, giving a genuine transpose-QR entry point rather than a convert-and-forward shim. That is the real reason to keep CSR around.

Neither optimization is implemented here — this PR just carries the extension as-is so the option is preserved.

Tests

  • Full suite passes locally on Julia 1.10 (Pkg.test()): 730 + 24 + 1 = 755 passing, including the subprocess check that the CSC core still works with the CSR extension absent.
  • Runic-formatted.

🤖 Generated with Claude Code

The entire kernel is already CSC: csr_analyze/csr_factor/csr_refactor!/csr_qr
now accept a SparseMatrixCSC directly, reading its colptr/rowval/nzval into
the pooled workspace with no transpose or intermediate allocation (column
norms are computed straight off nzval). The csr_* names are kept for
back-compatibility.

SparseMatricesCSR is moved from [deps] to [weakdeps]; the SparseMatrixCSR
method overloads now live in SparseColumnPivotedQRSparseMatricesCSRExt, which
delegates to the CSC core via SparseMatrixCSC(A). The precompile workload
exercises the CSC path natively; the CSR extension carries its own workload.

Tests: CSC core covers square/over-/under-determined/rank-deficient, Float64
and ComplexF64, and the refactor reuse + zero-alloc steady state, run in a
SparseMatricesCSR-free subprocess. The existing CSR suite still exercises the
extension path. Refactor steady state on the CSC path is 0 bytes (sparse and
adaptive_dense), as is ldiv!.

Refs SciML#33

Co-Authored-By: Chris Rackauckas <accounts@chrisrackauckas.com>
Remove the optional SparseMatricesCSR extension and all SparseMatricesCSR
references so the package has no dependency on it. The csr_* public names are
kept (they accept SparseMatrixCSC). CSR (SparseMatrixCSR) input support is
carved into a separate, optional PR stacked on this one.

- Delete ext/SparseColumnPivotedQRSparseMatricesCSRExt.jl.
- Remove SparseMatricesCSR from [weakdeps]/[extensions]/[compat]/[extras]/[targets].
- Make the tests CSC-only (helpers now return SparseMatrixCSC); fold the
  CSC-core checks into a plain include (no subprocess isolation needed once
  CSR can never be loaded).
- Scrub CSR mentions from src docstrings, the precompile comment, README, and docs.

Co-Authored-By: Chris Rackauckas <accounts@chrisrackauckas.com>
Stacked on the CSC-native core (SciML#35). Re-adds SparseMatrixCSR input support
behind the optional SparseMatricesCSR weak-dep extension, which converts CSR
to CSC and dispatches into the unchanged CSC kernel. The package's core stays
pure CSC + SparseArrays; CSR is only pulled in when `using SparseMatricesCSR`.

- Restore ext/SparseColumnPivotedQRSparseMatricesCSRExt.jl (csr_qr/csr_analyze/
  csr_factor/csr_refactor! on SparseMatrixCSR, plus its own precompile workload).
- Restore SparseMatricesCSR in [weakdeps]/[extensions]/[compat]/[extras]/[targets].
- Restore the CSR tests (including the subprocess check that the CSC core works
  with the CSR extension absent) and the CSR docstring/precompile notes, README,
  and docs.

Note: the current CSR path reconverts CSR -> CSC on every csr_refactor! call
(~17 KB/call, ~1.8x slower; see the SciML#35 benchmark comment). A future revision
should cache a CSC buffer and reuse it, and ideally add a zero-copy CSR fast
path (SparseMatrixCSR(A) == SparseMatrixCSC(Aᵀ), so the CSR arrays can be
reinterpreted as the transpose's CSC with no copy). Not implemented here.

Co-Authored-By: Chris Rackauckas <accounts@chrisrackauckas.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.

2 participants