Skip to content

sparse

Sparse matrices, fill-reducing orderings and iterative solvers, released v0.1.0.

Status: released v0.1.0.

Sparse matrices, fill-reducing orderings and iterative solvers in pure Go (CGO_ENABLED=0), module github.com/go-sparse/sparse, BSD-3-Clause.

go get github.com/go-sparse/sparse@v0.1.0
a := gallery.Laplacian2D(100, 100)           // *sparse.CSR[float64]
b := make([]float64, a.Rows)
ic, _ := iter.NewIC0(a)                      // incomplete Cholesky
res, _ := iter.CG(a, b, &iter.Options{RTol: 1e-8, M: ic})
fmt.Println(res.Info, res.Iterations)        // 0 = converged, as in SciPy

What is provided

packageprovides
sparseCOO, CSR, CSC, DOK over float64 and complex128; conversions; O(1) transpose; SpMV, SpMM, SpGEMM; Add, Sub, Axpby; scaling; Diagonal, Tril, Triu, Permute, Prune, norms; Eye, Diags; LinearOperator
nd*ndarray.Array in and out: vectors, dense matrices, SpMV and SpMM
mtxMatrix Market read and write: coordinate and array, real, integer, pattern and complex, general, symmetric, skew-symmetric and hermitian, gzip input
orderRCM, AMD, COLAMD; Bandwidth, Profile, CholeskyNNZ, QRFillNNZ
iterCG, GMRES(m), BiCGSTAB, MINRES, LSQR, LSMR; preconditioners Jacobi, SSOR, IC0, ILU0, ILUT
galleryLaplacians (1-D, 2-D, 3-D), convection-diffusion, seeded random sparse matrices

Solvers follow scipy.sparse.linalg: the stopping rule is ‖b − A x‖ ≤ max(rtol·‖b‖, atol), rtol defaults to 1e-5, maxiter to 10n (5n for MINRES), and info is 0 on success, the iteration limit when it was reached, and negative on breakdown.

Not provided yet: sparse direct factorisations (LU, Cholesky, QR), nested dissection, eigensolvers, algebraic multigrid, Rutherford-Boeing I/O.

Orderings: provenance

AMD and COLAMD are written from the papers (Amestoy, Davis and Duff, 1996; Davis, Gilbert, Larimore and Ng, 2004). SuiteSparse AMD and COLAMD are the reference algorithms; CHOLMOD, UMFPACK and CSparse (GPL/LGPL) were not consulted. Tie-breaking differs, so permutations differ; quality is compared by fill.

Verification

Every solver, LSQR and LSMR and the orderings are compared with SciPy 1.18.1 and NumPy 2.5.4 (and SuiteSparse AMD through cvxopt as a binary oracle). A Go harness drives SciPy over a pipe and records the answers in a committed fixture; the regression tests replay it, so they need neither Python nor network. The full method is the library’s docs/verification.md.

On the committed suite: CG, GMRES, MINRES, LSQR and LSMR iteration counts equal SciPy’s; BiCGSTAB agrees within a few iterations. AMD Cholesky fill is within 1% of SuiteSparse AMD; COLAMD LU fill is within 4% of SuperLU’s COLAMD; RCM bandwidth equals SciPy’s.

Performance

One core, Go 1.27.2 on darwin/arm64, SciPy 1.18.1, medians of 7 interleaved rounds. Ratio is Go time / SciPy time; below 1 means Go is faster. From the library’s docs/perf.md, measured on 2026-10-20 at load 5.

workSpMVCGGMRES(30)
2-D Laplacian, 1.1e5 nonzeros0.970.700.56
2-D Laplacian, 1.0e6 nonzeros0.980.890.82

Column indices are int32, as in scipy.sparse; dot products and vector updates use the fleet’s SIMD kernels, and the Krylov solvers fuse each vector update with the dot product that follows it.

Untrusted input

mtx.ReadLimited takes limits on dimensions, entries, line length, decompressed size and comment lines; declared sizes are checked before allocation, and a gzip bomb is cut off at the byte limit. mtx.FuzzRead has a committed corpus.

Quality gates

gofmt, go vet, go test -race with 100% statement coverage over all packages, 386 and the other architectures in CI, and govulncheck.

Created on by tannevaled

Modified on by tannevaled