Top-level
The containers every part of koblas speaks, and the free-function arithmetic over them. The routines themselves live one package down, split by storage: com.eignex.koblas.dense and com.eignex.koblas.sparse. See the README's "BLAS coverage" table for the routine-by-routine mapping to BLAS/LAPACK and the deliberate deviations.
Containers: MatrixView / DenseMatrix and VectorView / DenseVector / SparseVector, all
@Serializable, plus the CSC SparseMatrix. The view roots are sealed, which is what gives the concrete storage a closed set and lets a snapshot round-trip with its type preserved — and is why the containers stay in one package rather than splitting with the operations that consume them.Free-function arithmetic over the views, dispatching dense or sparse by operand type: dot, axpy, scale, norm2, asum, iamax, copy, swap, ger, gemv, transpose, forEachStored, and the matrix 1-norm norm1.
Shared machinery: Backend (what every backend of every tier reports about itself), the Workspace buffer pool, DispatchThresholds and the mathBackend identifier.
Types
One replaceable half of a KoblasContext, named so a caller can ask about it.
Dense column-major matrix backed by a single contiguous DoubleArray of length rows * cols. Element (i, j) lives at data[i + j * rows], so each column is a contiguous run of rows doubles.
Dense double-precision vector backed by a flat DoubleArray. The default carrier when the caller already has a dense array or expects most entries to be populated.
Every backend koblas will use for a piece of work, in one object you can hold.
Read-only matrix contract: shape, entry access, materialisation. Anything that only reads a matrix should take this.
The matrix storages koblas itself defines: DenseMatrix and SparseMatrix, and nothing else ever.
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.
Compressed sparse vector: parallel indices/values arrays of equal length, each holding one nonzero entry. Immutable from the caller's perspective; to change the sparsity pattern, rebuild.
Read-only vector contract: length, entry access, materialisation. Anything that only reads a vector should take this.
The vector storages koblas itself defines: DenseVector and SparseVector, and nothing else ever.
Properties
The process-wide default context: an installBackends override when set, else whatever registered itself, else the portable reference implementations.
What this runtime resolved, for startup logging — e.g. "backend=openblas, kernels=simd(8 lanes)".
Short human-readable identifier for the vector kernels the current process resolved: "scalar" on any non-JVM target (or a JVM started without --add-modules=jdk.incubator.vector), "simd(4 lanes)" on a JVM with AVX2, "simd(8 lanes)" with AVX-512, and a "+openblas" suffix when a host backend is registered for long runs. Print at startup to verify your runtime picked up what you expected.
The com.eignex.koblas.dense.LuDecomposition.failedAt / com.eignex.koblas.sparse.SparseFactorization.failedAt value of a factorization that succeeded.
The slots still running koblas's own portable implementation, in declaration order.
A failedAt meaning "singular, but this backend cannot say where".
Functions
Sum of absolute values Sum |v_i| (BLAS dasum). Sparse vectors sum over stored entries only.
y = y + alpha * x. Dense x uses SIMD; sparse x walks stored entries.
The backend currently filling slot.
dst = src (BLAS dcopy). Dense sources bulk-copy; sparse sources zero-fill then scatter.
aT * b. Dense×dense routes through the active com.eignex.koblas.dense.VectorKernels; a mixed pair walks the sparse side and gathers from the dense one; anything else is read entry by entry.
Visit each stored entry of this as (index, value), in ascending index order for any storage. For DenseVector that's every index in 0 until size; for SparseVector that's the entries present in the parallel index/value arrays (which may include numerical zeros); for any other VectorLike it is every index, read through VectorLike.get.
Matrix-vector product A · x into a fresh dense result (BLAS dgemv with alpha = 1, beta = 0).
Rank-one update A = A + alpha · x · yᵀ (BLAS dger). Subtract by passing alpha = -1.0.
Index of the first entry with maximal |v_i| (BLAS idamax), or -1 for a zero-length vector. "First" is by index for either storage: a SparseVector's stored entries are ascending, so its storage order is index order and the two contracts agree. An all-unstored (zero) vector returns index 0, matching the dense zero vector.
Overrides the context koblas returns, taking precedence over every automatic mechanism — registration and platform discovery alike. Passing null restores automatic selection.
Whether slot is filled by something other than koblas's own portable implementation.
Translates a LAPACK info return into a failedAt position.
Matrix 1-norm: the maximum absolute column sum (LAPACK dlange with norm 1). This is the anorm input LinearAlgebra.rcond expects, computed on the matrix before factoring, so a solver that estimates conditioning each refactorization calls both.
Euclidean norm ||v||₂ (BLAS dnrm2). Sparse vectors sum over stored entries only.
Frobenius norm: sqrt(Sum a_ij²) (LAPACK dlange with norm F).
Matrix infinity-norm: the maximum absolute row sum (LAPACK dlange with norm I).
Offers backend for automatic selection as every half it implements.
Throws unless every one of slots is filled by an accelerated backend.
Apply a plane rotation to a pair of vectors in place (BLAS drot): each (x_i, y_i) becomes (c·x_i + s·y_i, c·y_i − s·x_i).
v = alpha * v.
Symmetric rank-1 update A += alpha · x · xᵀ (BLAS dsyr); see Blas.syr.
Symmetric rank-2 update A += alpha · (x · yᵀ + y · xᵀ) (BLAS dsyr2); see Blas.syr2.
Fresh transposed matrix Aᵀ. Always materializes; for products against a transposed operand, prefer the transpose flags on LinearAlgebra.gemv / LinearAlgebra.gemm, which read the original storage without copying.
Fresh transposed matrix Aᵀ, still CSC — which makes this the CSC-to-CSR conversion as well.