SparseMatrix
A sparse matrix in compressed-sparse-column (CSC) form: column j occupies rowIdx[colPtr[j] until colPtr[j + 1]] with the parallel nonzero values in values, row indices strictly ascending within a column — validated by the constructor, since get relies on the ordering. colPtr has length cols + 1 with colPtr[0] == 0 and colPtr[cols] == values.size. CSC is the layout sparse solvers and column-oriented sweeps (matrix–vector products, LU factorization) consume directly — and, since DenseMatrix became column-major, the axis both storages agree is contiguous.
The invariants are not arbitrary: they are what a host sparse solver requires. UMFPACK states them verbatim — Ap[0] zero, Ap[j] <= Ap[j+1], row indices ascending within a column with no duplicates, 0-based and in range — so this backing passes to umfpack_di_* with no repacking. KLU takes the same (n, Ap, Ai) with int32_t arrays. CHOLMOD wraps it as a cholmod_sparse with packed = 1, sorted = 1, stype = 0 (both triangles stored, which is what koblas does) and itype = CHOLMOD_INT. Checked against the 7.x headers rather than remembered.
Two mismatches remain for a future binding, neither structural. A library built for 64-bit indices wants the umfpack_dl_* family and a widening copy, the sparse counterpart of the LP64/ILP64 split the dense backend already documents. And an explicitly stored zero is part of the value here — equality distinguishes it — where a host library may drop it, so a round-trip through one can lose pattern.
Arithmetic lives on the sparse seam rather than here, as it does for DenseMatrix: the products are com.eignex.koblas.sparse.SparseBlas methods, reachable as gemv/lu extensions, so a container stays storage and does not depend on which backend is installed.
A MatrixView like the dense one, so anything written against the view contract accepts either. The two access costs differ though, and the difference is not small: get searches a column rather than indexing, and toArray densifies. Code that wants the sparsity should reach for forEachInColumn.
Serializes through its CSC arrays rather than a readable 2D form, unlike DenseMatrix. The flat dense backing is an implementation detail worth hiding behind a nicer wire shape; CSC is the format, and writing a sparse matrix out densely would cost the rows × cols the representation exists to avoid.
Constructors
SparseMatrix
Functions
equals
Structural equality over the shape and the stored entries.
Compares the CSC arrays, which means two matrices that agree everywhere but store a different set of explicit zeros are not equal. That mirrors SparseVector, where a stored zero is also part of the value: the pattern is information, and a factorization that reserved a slot for fill differs from one that never had it.
forEachInColumn
get
Read entry (i, j), or 0.0 where nothing is stored.
A binary search over column j's row indices, which are ascending — so this is O(log nnzⱼ), not the O(1) the dense storage gives. Fine for a probe; wrong for a sweep, where forEachInColumn visits the same information in O(nnzⱼ) total.
hashCode
toArray
Materialise into a fresh rows × cols array of rows. Densifies, so the result is as large as the representation was avoiding; only the stored entries are written, the rest stay zero.
toString
Lower-triangular Cholesky decomposition A = L * LT, returned as a fresh matrix, from the installed backend; see Lapack.cholesky.
Factorize this sparse matrix with the active backend (koblas) — the sparse counterpart of DenseMatrix.lu(), carrying the same name for the same operation on the other storage.
Fresh transposed matrix Aᵀ, still CSC — which makes this the CSC-to-CSR conversion as well.
Solve op(T) · x = b in place against this matrix's lower or upper triangle, with the active backend (koblas) — the sparse counterpart of the dense trsv free function. See SparseBlas.trsv.