rivrs-sparse
Sparse linear algebra functionality for Rust.
This library builds on faer for foundational data types, dense solvers, and some sparse linear algebra routines.
Algorithms are implemented from academic literature and permissively-licensed reference code.
This library is written as numerical implementations for the rivrs symbolic-numeric framework but functions as a standalone crate for scientific computing applications.
It is also re-exported by the rivrs-linalg crate, containing more general numerical linear algebra functionality.
AI Disclaimer: Large amounts of the codebase were written using Claude Code. Every effort was made to adhere to reference literature and codebases, to use structured development processes to maintain quality, and to extensively test the generated code using comparable test suites and ground truth data (e.g. SuiteSparse matrices). However, as with any numerical code that hasn't existed for very long, it is recommended that you add your own correctness checks (e.g. backwards residual calculations) when using these solvers. Please report any issues
Features
Sparse Symmetric Indefinite Direct Solver
Based on SPRAL. Implemented using faer for dense linear algebra.
Use this for KKT matrices, saddle-point problems, and optimization formulations where the diagonal has negative or zero entries. Compared to faer's built-in sparse LDL^T, it handles difficult indefinite matrices via APTP pivoting, MC64 matching/scaling, and METIS ordering. Compared to SPRAL and MUMPS, it is native Rust, 100% safe code (except for calls to METIS), and competitive on sequential and parallel performance.
- Multifrontal LDL^T factorization with A Posteriori Threshold Pivoting (APTP)
- Two-level pivoting: TPP for small fronts, complete pivoting with BLAS-3 blocking for large fronts
- MC64 weighted bipartite matching & scaling + METIS nested dissection ordering
- Parallel factorization & solve via rayon (tree-level) and faer
Par(intra-node BLAS) - Three-stage API: analyze → factor → solve (symbolic reuse across re-factorizations)
Performance
Benchmarked on 65 SuiteSparse matrices (factorization time, backward error < 1e-12 on all, typically ~1e-16):
| Configuration | vs SPRAL | vs MUMPS |
|---|---|---|
| Sequential (1 thread) | median 5% speedup (36% faster, 38% comparable, 24% slower) | median 0.46x (~2x faster) |
| Parallel (8 threads) | median 10% speedup (53% faster, 23% comparable, 23% slower) | — |
See comparisons/README.md for full results per matrix.
API
use ;
use Col;
use ;
// Build a symmetric matrix (full storage, both triangles)
let triplets = vec!;
let a = try_new_from_triplets.unwrap;
let b = from_fn;
// One-shot solve
let x = solve_full.unwrap;
For the three-stage API with parallel factorization:
use ;
use ;
let mut solver = analyze_with_matrix.unwrap;
solver.factor.unwrap;
let mut mem = new;
let x = solver.solve.unwrap;
Building & Testing
# Unit tests (~360 tests) + CI subset (10 SuiteSparse matrices)
# Full SuiteSparse collection (65 matrices, requires test-data/suitesparse/)
# Lint
Test Data
| Tier | Path | Size | Git status |
|---|---|---|---|
| Hand-constructed | test-data/hand-constructed/ |
~144KB | Tracked |
| CI subset | test-data/suitesparse-ci/ |
~19MB | Tracked |
| Full suite | test-data/suitesparse/ |
~500MB | Gitignored |
The full test suite is enumerated in test-data/metadata.json and can be downloaded from SuiteSparse (recommended) or using the download script (throttled downloads - very slow).
Examples
See examples/README.md for full documentation.
# Self-contained hello world (no external data needed)
# Multiple right-hand sides with workspace reuse
# Refactorization: same sparsity, different values
# End-to-end solve timing on CI SuiteSparse matrices
# Single-matrix profiling with Chrome Trace export
# Parallel scaling across thread counts
# Performance baseline collection for regression tracking
External Solver Comparisons
The comparisons/ directory contains tools for benchmarking against reference
solvers (SPRAL and MUMPS). See
comparisons/README.md for build instructions.
# Build SPRAL driver (prerequisite)
# Side-by-side rivrs vs SPRAL on CI subset
# Control SPRAL thread count