Category report

Sparse matrix and sparse linear algebra libraries

Research date: 2026-10-09

This selection covers sparse storage, assembly, arithmetic, direct and iterative solvers, multigrid, sparse eigensolvers, and semiring algebra. It includes single-process libraries, distributed-memory systems, and GPU implementations. The 24 repositories are selected for engineering study, not ranked by speed or popularity. For broad numerical monorepos, the relevant sparse subsystem is identified and the repository is counted once. Array libraries with higher-dimensional capabilities are included where their sparse matrix implementation is substantive.

Criteria legend. C1: difficult correctness involving structural invariants, concurrency, numerical semantics, or failure handling. C2: substantial reusable abstractions serving multiple use cases. C3: concrete performance constraints addressed through understandable architecture. C4: documented evolution across years, including compatibility, testing, or complexity management. The criterion assignments below are engineering judgments grounded in the cited implementation facts; they do not imply that every component is uniformly exemplary.

Factorization suites and sparse eigensolvers

1. DrTimothyAldenDavis/SuiteSparse

Language/role: C and C++; a collection of sparse factorization, ordering, and algebra packages, with MATLAB interfaces. Relevant components include CHOLMOD, UMFPACK, SPQR, KLU, and SuiteSparse:GraphBLAS. These are counted together.

Study how numerical kernels expose failure information while preserving useful partial results, and how a suite coordinates independently useful packages.

  • C1: CHOLMOD's supernodal numeric factorization distinguishes invalid input or allocation failure from a matrix that is not positive definite. The latter can return successfully at the function level while recording a numerical status, the failed column, and a partially zeroed factor. Callers must respect that richer contract. The source also distinguishes supported factorization and numeric types. See the supernodal numeric implementation.
  • C4: The suite changelog records compatibility work across years: MATLAB empty-matrix behavior and shared-library dependencies in 2016, GraphBLAS integration in 2017, and later compiler, BLAS, and index-width changes. It explicitly distinguishes source compatibility from changes requiring recompilation.

2. xiaoyeli/superlu_dist

Language/role: Primarily C, with C++ and accelerator code; distributed sparse LU using MPI, OpenMP, and GPU backends.

This is a useful study of how numerical pivoting choices interact with distributed factorization and triangular solves. It is a substantive distributed implementation, not merely a language wrapper around serial SuperLU.

  • C1: The repository overview describes Gaussian elimination with static pivoting: a deliberate compromise between numerical stability and the synchronization costs of distributed pivoting. That tradeoff is central to understanding the solver's correctness assumptions.
  • C3: The 9.0.0 release description explains the separation of diagonal, panel, and Schur-complement work, expanded GPU offload, and three-dimensional communication-avoiding triangular solves. It also discusses MPI/OpenMP configuration and warns that adding threads can hurt performance. These are concrete architectural constraints, not an unconditional speed claim.

3. pghysels/STRUMPACK

Language/role: C++; sparse multifrontal solvers using rank-structured compression, alongside related dense algorithms. The sparse solver is the relevant subsystem.

Study the boundary between factorization as a direct solver and factorization as an approximate preconditioner.

  • C1: The sparse solver guide distinguishes uncompressed LU from approximate factorizations using HSS, HODLR, or BLR compression. Its automatic solve strategy connects compression choices to iterative refinement or preconditioned GMRES. Accuracy and convergence policy are therefore part of the solver interface.
  • C2: The same guide exposes separate reordering, factorization, and solve stages, together with sequential and distributed input contracts. Distributed CSR input and right-hand sides are supplied in local row portions, allowing applications to integrate the solver without surrendering all data-distribution decisions.
  • C3: Rank compression targets the storage and work associated with multifrontal factorization. The useful study is where approximate representations enter the factorization pipeline and how subsequent iteration compensates; no universal compression benefit is assumed.

4. ralna/spral

Language/role: Fortran, C, and C++; sparse numerical algorithms. The strongest entry point here is SSIDS, its symmetric indefinite direct solver.

SSIDS makes pivoting, resource scheduling, and numerical failure policy unusually visible to callers.

  • C1: The SSIDS C interface separates analysis and factorization state, exposes pivot information including two-by-two blocks, and lets callers choose whether a zero pivot should stop factorization or permit continuation with a warning. Its contracts also describe matrix checking and numerical thresholds.
  • C3: The same documentation explains block a posteriori pivoting and the different recomputation costs of failed pivots. CPU block sizes, subtree thresholds, CPU/GPU scheduling, and NUMA options connect the elimination-tree structure to available hardware. This is a strong codebase for studying how stability safeguards affect parallel execution rather than treating pivoting as an isolated kernel.

5. opencollab/arpack-ng

Language/role: Fortran, with C/C++ interfaces and MPI PARPACK; sparse and matrix-free eigensolvers. This is a substantive community continuation of ARPACK, with its own fixes, interfaces, build work, and tests.

Study reverse communication: the eigensolver controls iteration while the application supplies matrix operations and, for relevant modes, linear solves.

  • C1: The dnaupd implementation and interface contract encode requested operations through IDO and workspace-pointer arrays. Correctness depends on returning the right operation into the right workspace and respecting convergence requirements, especially for spectral transformation modes.
  • C2: That protocol accommodates application-owned sparse formats and matrix-free operators without embedding every storage or solver backend inside ARPACK.
  • C4: The change history spans the 2011 continuation, later bounds checking and tests, ILP64 support, MPI deadlock fixes, compiler compatibility, and parallel binding tests. It provides evidence of sustained compatibility and correctness work, beyond the original algorithm's age.

Distributed sparse solver frameworks

6. petsc/petsc

Language/role: C-centered numerical framework; focus on Mat, KSP, and PC. Repository status: the GitHub repository identifies itself as an official mirror of the GitLab development repository and retains the substantive source tree.

Study how a common matrix abstraction accommodates distributed ownership, assembly, storage formats, and solver composition.

  • C1: The matrix manual specifies an assembly protocol: additive and overwriting insertion modes cannot be arbitrarily mixed without assembly, and off-process entries must be communicated to their owners. These are state and ownership invariants, not merely container operations.
  • C2: Mat supports multiple sequential and distributed implementations behind a common interface, with runtime matrix-type selection. Applications can change storage/backend choices while preserving much of their solver code.
  • C3: Separate assembly begin/end calls permit communication overlap. AIJ preallocation distinguishes locally owned and off-process columns to avoid repeated allocation and copying. The manual ties these choices directly to the distributed representation.

7. trilinos/Trilinos

Language/role: C++; a numerical monorepo. The relevant subsystem here is Tpetra's distributed sparse linear algebra, rather than every Trilinos package.

Study the separation of data distribution, communication plans, local computation, and scalar types.

  • C2: The Tpetra architecture overview explains Maps for distribution and Import/Export for movement between distributions. The DistObject mechanism allows custom distributed objects to supply packing and unpacking behavior, making communication machinery reusable beyond the built-in matrix and vector classes.
  • C3: Tpetra combines MPI distribution with node-level parallelism through Kokkos. This separates inter-process ownership and communication from local execution and memory choices. Templated scalar support, including types beyond ordinary real and complex numbers, makes the abstraction boundaries worth inspecting.

Tpetra and Kokkos Kernels are included separately because they expose distinct implementations and responsibilities: distributed objects versus local computational kernels.

8. hypre-space/hypre

Language/role: Primarily C; parallel sparse solvers and multigrid preconditioners. The IJ-to-ParCSR path is a particularly concrete architectural entry point.

Study how distributed assembly rules coexist with a solver-oriented compressed representation.

  • C1: The IJ interface documentation differentiates setting locally owned entries from adding contributions to remote rows. Assembly is collective. After assembly, values can be changed through the documented lifecycle, but changing the sparsity pattern requires a new matrix. These restrictions make ownership and structural validity explicit.
  • C3: The same chapter describes an assumed-partition approach that avoids storing a full global partition on each process. It also documents diagonal/off-diagonal row-size hints and access to the underlying ParCSR object without copying the matrix. The key study is how scalable neighbor discovery and allocation planning fit behind an assembly API.

9. sfilippone/psblas3

Language/role: Fortran with C interfaces and MPI; distributed sparse BLAS operations and iterative-solver infrastructure.

This is a useful Fortran-centered alternative to the larger C/C++ frameworks, especially for studying descriptors that connect global indices to distributed data.

  • C2: The PDE matrix-generation example demonstrates descriptor construction from a local row count, a global row-to-owner map, or explicit local global-index lists. The same matrix-generation logic can therefore be adapted to different partitions without embedding one ownership scheme everywhere.
  • C1: The example validates partition inputs and uses communicator-aware failure paths before constructing distributed objects. Its two-dimensional decomposition and local/global index handling expose practical correctness obligations that serial sparse matrix APIs do not have.

The example is the entry point into the library's abstraction, not the reason for treating the repository as a tutorial: the repository itself implements reusable distributed sparse operations.

Iterative solvers and multigrid composition

10. ginkgo-project/ginkgo

Language/role: C++; sparse iterative solvers, preconditioners, and matrix formats across CPU and GPU backends.

Study how solver composition can remain independent of memory ownership and execution placement.

  • C2: In the LinOp composition model, matrices, solvers, preconditioners, and compositions share an application interface. Factories separate configured algorithm parameters from binding an algorithm to a particular operator. This lets a solver participate as an operator inside another algorithm.
  • C3: The executor model centralizes allocation, address spaces, transfers, synchronization, and backend dispatch. Reference, OpenMP, CUDA, HIP, and DPC++ executors provide a clear place to study backend specialization without duplicating the public solver model. The reference implementation also supplies an understandable baseline for examining optimized kernels.

11. ddemidov/amgcl

Language/role: C++; header-only algebraic multigrid and iterative solvers with interchangeable computational backends.

Study policy composition and the economics of rebuilding a preconditioner for sequences of related matrices.

  • C2: The preconditioner documentation makes backend, coarsening, and relaxation separate template policies. It also exposes choices for coarse-level solving and cycle configuration. This is a substantial abstraction over AMG variants rather than one fixed algorithm with incidental options.
  • C3: Hierarchy construction and backend execution are separated. The documented rebuild option retains transfer operators and updates coarse operators using the new fine-level matrix, avoiding a complete hierarchy reconstruction when reuse is appropriate. That design makes setup cost, saved structure, and subsequent solves independently inspectable.

12. pyamg/pyamg

Language/role: Python with compiled kernels; native algebraic multigrid implementations integrated with the scientific Python stack.

Study an inspectable hierarchy representation and how numerical stopping rules and cost estimates are presented to users.

  • C2: The multilevel API represents levels through system, interpolation, and restriction operators. Configurable coarse solvers and an adapter to SciPy's LinearOperator allow a hierarchy to act as either a solver or a preconditioner.
  • C1: The solve contract documents residual-based stopping, convergence status, and changes in interpretation when an acceleration method is supplied. These distinctions matter when composing solvers.
  • C3: Operator, grid, and cycle complexity are exposed as inspectable measures. The documentation explicitly limits its cycle-cost estimate for expensive smoothers, including block Gauss–Seidel; it does not pretend that nonzero counts predict every runtime cost.

Portable kernels, GPU systems, and semiring algebra

13. kokkos/kokkos-kernels

Language/role: C++; portable local numerical kernels. KokkosSparse is the relevant subsystem; this repository does not itself replace an MPI distributed matrix framework.

Study the division between discovering sparse output structure and computing numerical values on different execution spaces.

  • C1: The SpGEMM symbolic interface specifies input sorting flags and output structure behavior. It also documents unsupported transpose cases despite accepting transpose-related parameters. The real contract must therefore be understood beyond the function signature.
  • C3: Sparse matrix multiplication separates symbolic work, including determining output nonzero counts and row pointers, from numerical computation. A kernel handle carries configuration and intermediate information across that split, allowing allocation and structural work to be managed explicitly rather than hidden in a single opaque multiplication call.

14. NVIDIA/AMGX

Language/role: C++ and CUDA, with MPI support; GPU-oriented iterative methods and algebraic multigrid.

Study the shared lifecycle underneath a configurable family of GPU solvers.

  • C2: The solver base implementation separates setup, initialization, iteration, and solve behavior behind a templated solver interface. It exposes solver requirements such as coloring, reordering, and diagonal insertion, allowing the setup pipeline to accommodate algorithm-specific needs.
  • C1: The same interface manages residual norms, convergence history, return statuses, and exception-to-error-code boundaries. This makes numerical termination and API failure handling part of the framework rather than responsibilities left to each calling application.
  • C3: Matrix-structure reuse is an explicit setup option. Studying it alongside coloring requirements and GPU timing hooks reveals where preprocessing is amortized across repeated solves.

15. cusplibrary/cusplibrary

Language/role: C++ templates over CUDA/Thrust; sparse containers and algorithms. Treat this as a valuable legacy GPU design reference; the inspected material does not establish compatibility with current CUDA toolchains.

Study a storage format designed around the mismatch between regular GPU access and irregular row lengths.

  • C1: The HYB matrix documentation specifies sorted, left-packed ELL entries, row-sorted COO overflow, and restrictions on duplicate entries. These representation invariants are prerequisites for correct kernels.
  • C3: HYB places a regular portion in ELL and overflow in COO. The documentation explains the tradeoff between ELL padding and COO reduction work, making the format an understandable response to row-length variability rather than a generic claim of GPU acceleration.

For historical context, the changelog records dispatch refactoring, compatibility headers, and sparse-kernel memory fixes; several highlighted releases target older CUDA/Thrust combinations.

16. PASSIONLab/CombBLAS

Language/role: C++ with MPI/OpenMP; distributed sparse linear algebra over user-defined semirings, including graph-algorithm building blocks.

Study a distributed matrix layer that composes local storage, scalar types, algebra, and communication strategy.

  • C2: The repository's architecture description explains how SpParMat is parameterized by index, numeric, and sequential matrix implementation types. Local CSC, doubly compressed storage, and tuple representations can coexist with user-defined semirings rather than hard-coding ordinary floating-point multiplication and addition.
  • C3: Two-dimensional matrix distribution and sparse SUMMA multiplication explicitly address distributed communication. The repository also describes three-dimensional variants and fully distributed vectors. This provides concrete material on scaling beyond a design where every operation funnels through one process or a diagonal process subset.

An additional entry point is the SpParMat API/source reference, which exposes communication-grid and templated multiplication relationships. That generated reference identifies an older 1.6 version, so use the repository for current implementation details.

17. gunrock/graphblast

Language/role: C++ and CUDA; a GPU GraphBLAS research implementation expressing graph operations through sparse algebra.

Study masks, accumulators, and semirings as reusable computational concepts, with a clear boundary between public operations and backend kernels.

  • C2: The repository overview shows how semirings such as Boolean and min-plus express different graph computations using shared matrix/vector operations. The reusable unit is the algebraic operator, not a separate bespoke traversal API for every graph problem.
  • C1: The operations implementation checks dimensions and object validity around masked operations and backend dispatch. It also explicitly returns an unimplemented status for some operations, an important API failure mode to understand.

Limitation: This is not presented as complete GraphBLAS coverage. The inspected source contains unimplemented operations, and the README's tested compiler/CUDA combinations are old. Current toolchain compatibility was not established.

Sparse containers and language-native numerical APIs

18. scipy/scipy

Language/role: Python with C, C++, and Fortran implementations; focus on scipy.sparse, scipy.sparse.linalg, and the associated sparse graph interfaces.

Study the consequences of preserving sparse representation details inside a widely reused array API.

  • C1: The sparse tutorial distinguishes implicit zeros from stored zeros and explains duplicate entries and canonical form. These details affect assembly and graph semantics, including the distinction between a missing edge and an edge with zero weight.
  • C2: Multiple formats serve assembly, row/column access, arithmetic, and block-structured workloads behind a shared ecosystem of operations and solvers. The same tutorial provides a useful route through those representation choices.
  • C4: The 1.8.0 release introduced sparse arrays for early testing; 1.15.0 documented broader support and continued matrix/array interoperability. The migration guide explains operator changes, index dtypes, and compatibility tactics. Together these show a multi-year semantic migration rather than an abrupt class rename.

19. pydata/sparse

Language/role: Python; multidimensional sparse arrays, including sparse matrices, with COO and compressed representations and NumPy-oriented operations.

Study how an implicit background value changes the implementation contract for apparently ordinary array operations.

  • C1: The operations guide describes nonzero fill values: adding a scalar can change the background value without explicitly materializing every formerly absent entry. Operations must also respect fill-value consistency and densification constraints. A sparse container cannot simply apply a function to stored entries and ignore the rest of the logical array.
  • C2: The documented API composes broadcasting, elementwise functions, reductions, dot products, tensor contractions, reshaping, and interoperability across COO/GCXS arrays. The quickstart connects those operations to coordinate storage and NumPy use.

The selection concerns the substantive sparse representations and operation semantics. It does not assume complete NumPy compatibility or that every operation preserves sparsity; the documentation lists limitations.

20. JuliaSparse/SparseArrays.jl

Language/role: Julia; standard-library sparse arrays, storage, assembly, and arithmetic. The relevant implementation is broader than bindings to external factorization packages.

Study how a high-level language exposes both convenient construction and explicit control over sparse assembly workspaces.

  • C1: The SparseArrays manual specifies CSC storage with sorted row indices and distinguishes structural nonzeros from numerical nonzeros. Advanced construction additionally has duplicate-combination and array-aliasing contracts, so input validation and mutability deserve close attention.
  • C3: The expert sparse assembly interface documents a multi-stage algorithm: counting-sort coordinate entries into a row-oriented intermediate, combine duplicates while determining column counts, then produce sorted CSC. Callers can reuse intermediate and output storage. This exposes both the algorithm and allocation costs that a simpler constructor would hide.

21. sparsemat/sprs

Language/role: Rust; native CSR/CSC matrices, triplet assembly, sparse vectors, and numerical operations.

Study how ownership and borrowing express sparse structural invariants without forbidding useful zero-copy views.

  • C1: The CsMatBase API distinguishes value mutation from structural mutation. Mutable access to numerical values does not automatically permit invalidating index arrays; structural modification APIs check coherence, including index ordering and bounds.
  • C2: The same matrix abstraction supports owned storage and borrowed views, with configurable value and index types. The crate overview exposes common traits and operation modules around those representations. This makes the repository useful for studying a reusable sparse API whose safety boundary follows the structure of the data rather than simply wrapping all arrays in one opaque object.

22. sarah-quinones/faer-rs

Language/role: Rust; dense and sparse linear algebra. Focus on the native sparse storage and factorization implementation, counted as one repository.

Study the separation between symbolic structure, numeric values, ownership, and solver strategy.

  • C2: The sparse module documentation separates symbolic and numeric representations and provides owned matrices plus borrowed immutable/mutable views. Compressed and capacity-bearing representations expose distinct storage responsibilities rather than conflating every sparse object with one allocation policy.
  • C1: The sparse solver guide states the different mathematical requirements of Cholesky, LU, and QR, including positive-definiteness, square systems, and least-squares use.
  • C3: The guide describes automatic selection between simplicial and supernodal factorization based on sparsity. This connects local kernel granularity to matrix structure. It also acknowledges that lower-level tuning is not fully documented, which limits how far the high-level guide alone can support detailed tuning decisions.

23. lessthanoptimal/ejml

Language/role: Java; numerical monorepo with native sparse CSC operations and solvers. Focus on the sparse modules rather than the entire dense API.

Study how a managed-language implementation exposes structural reuse and scratch storage without forcing every caller into a low-level interface.

  • C1: The LinearSolverSparse interface documents structure locking: repeated setup can reuse analysis only when the nonzero pattern remains compatible. The shared interface covers sparse solves while making the structural precondition explicit.
  • C3: The sparse matrix example separates triplet construction from CSC computation and reuses integer and floating-point work arrays across arithmetic calls. This exposes allocation control and analysis reuse as ordinary API choices, useful when studying performance in an otherwise garbage-collected environment.

24. james-bowman/sparse

Language/role: Go; native sparse formats and operations compatible with Gonum's matrix interfaces.

This smaller codebase is useful for studying sparse kernel dispatch without first absorbing a distributed runtime or a large solver framework.

  • C2: The repository API overview describes several sparse formats integrated with Gonum's matrix abstractions. The implementation can specialize known sparse operands while retaining interoperability with a general matrix interface.
  • C3: The compressed arithmetic implementation dispatches among operand-specific paths. CSR multiplication uses scatter/accumulate/gather machinery; diagonal and dense operands have specialized cases, with generic fallbacks for other matrix implementations. This makes the tension between abstraction and efficient representation-aware kernels directly readable.

Search coverage, exclusions, and limits

Discovery used more than six meaningfully different live search formulations, spanning: sparse direct and multifrontal solvers; distributed MPI sparse algebra; algebraic multigrid and preconditioner frameworks; CUDA/GPU sparse kernels; GraphBLAS and semiring systems; Python and Julia sparse arrays; Rust storage/ownership APIs; Go, Java, and C# libraries; Fortran sparse BLAS; and less prominent compressed-format or JIT sparse projects. Searches were followed by opening each retained canonical GitHub repository and at least one additional primary implementation, API, design, or release source. Later searches increasingly returned already-covered projects, ports, wrappers, and applications rather than additional distinct library architectures.

The selection balances large suites with narrower implementations such as PSBLAS, AMGCL, sprs, and the Go library. It does not count language bindings as independent implementations merely to expand the list. SuiteSparse components and the sparse subsystems of SciPy, Trilinos, and faer are each counted once. ARPACK-NG is retained because its own continuation history documents substantive implementation and compatibility work.

Important exclusions and qualifications:

  • The eigenteam/eigen-git-mirror repository explicitly identifies its mirror as deprecated and points development to GitLab. It was excluded under the requirement to retain a substantive official GitHub source, rather than substitute an arbitrary fork. PETSc is included with its official mirror status clearly labeled.
  • SparseX was a plausible additional candidate, but repeated attempts to open supporting primary implementation/documentation files failed. It was excluded for insufficient verification in this research pass, not because its design was judged weak.
  • Thin bindings, generated wrappers, sample-only repositories, unrelated machine-learning sparsity utilities, and projects without a verified canonical GitHub repository were not used to fill out the selection. Standalone tensor compiler research was outside the main scope.
  • Some useful references are historical: CUSP's documented toolchains, GraphBLAST's tested environment and incomplete operations, and the older generated CombBLAS reference are identified above. No inference of current maintenance is made from stars, repository creation dates, or a recent push alone.

This is a source-supported selection guide, not a benchmark, exhaustive ecosystem census, or full correctness audit. No candidate code was installed or executed. Performance criteria refer to documented mechanisms and tradeoffs, not verified speedups; C4 is used only where the inspected history supports evolution and compatibility work across years. Branch-based source links and live documentation may change after the research date.

Continue exploringBack to the collection →