koblas

KoblasContext

class KoblasContext(val vectorKernels: VectorKernels, val blas: Blas, val lapack: Lapack, val sparseVectorKernels: SparseVectorKernels, val sparseBlas: SparseBlas, val sparseLapack: SparseLapack) : LinearAlgebra, Blas, Lapack, SparseLinearAlgebra, SparseBlas, SparseLapack(source)

Every backend koblas will use for a piece of work, in one object you can hold.

koblas is the process-wide default, assembled from whatever registered itself, and the free functions use it — so nothing has to know contexts exist. Build your own when you want the choice to be explicit rather than ambient: a test that must not depend on what the platform happened to install, a benchmark comparing two backends in the same process, a solver instance pinned to a configuration, a run someone needs to reproduce.

A LinearAlgebra and a SparseLinearAlgebra at once, by delegation, so a context is a backend and context.gemv(...) works wherever koblas.gemv(...) does. That is also what let the old ComposedBackend and ComposedSparseBackend classes go: pairing two halves into a whole was their entire job, and a context already does it.

Six halves, and the split between them is the one the rest of the library uses: three dense and three sparse, vector kernels below the matrix routines below the factorizations. Construct by name — six positional backends would be unreadable — or, more usually, adjust the default with with:

val portable = koblas.with(blas = ReferenceLinearAlgebra, lapack = ReferenceLinearAlgebra)
val x = portable.solve(portable.factor(a), b)

Immutable, so it is safe to share between threads and cheap to keep: the fields are final, which is strictly better than the global it replaces for the hot path, since a final kernel reference lets a null check hoist out of a loop where a @Volatile one cannot.

Constructors

KoblasContext

constructor(vectorKernels: VectorKernels, blas: Blas, lapack: Lapack, sparseVectorKernels: SparseVectorKernels, sparseBlas: SparseBlas, sparseLapack: SparseLapack)(source)

Properties

blas

lapack

name

open override val name: String(source)

The distinct names of the backends that do the matrix work, joined — e.g. "openblas" when one library won everything, or "openblas+reference" when the sparse halves fell back.

The two vector-kernel halves are deliberately left out. They are reported by mathBackend, and folding them in here made every name carry "simd(4 lanes)+" in front of the answer anyone was actually asking for. koblasInfo prints both parts.

Explicit rather than delegated because every half is a Backend and Kotlin cannot pick one to inherit this from. Deduplicated in encounter order, since the usual case is one or two real answers repeated.

priority

open override val priority: Int(source)

The strongest half's priority: a context is at least as preferred as the best thing in it.

sparseBlas

sparseLapack

sparseVectorKernels

vectorKernels

Link copied to clipboard

The slots still running koblas's own portable implementation, in declaration order.

Functions

toString

open override fun toString(): String(source)

with

fun with(vectorKernels: VectorKernels = this.vectorKernels, blas: Blas = this.blas, lapack: Lapack = this.lapack, sparseVectorKernels: SparseVectorKernels = this.sparseVectorKernels, sparseBlas: SparseBlas = this.sparseBlas, sparseLapack: SparseLapack = this.sparseLapack): KoblasContext(source)

A copy with the named halves replaced and the rest kept.

The ergonomic way to build a context, because it starts from one that already resolved: the six-way constructor makes you name a backend for every half, which is the right default for a type you can install but tedious when you want to change one thing.

Link copied to clipboard
open override fun applyQ(qr: QrDecomposition, y: DoubleArray, transpose: Boolean = false): DoubleArray

Apply Q (or Qᵀ when transpose) from qr to a length-m y, into a fresh result (LAPACK dormqr restricted to a single column). Allocates; applyQInto does not.

Link copied to clipboard
open override fun applyQInto(qr: QrDecomposition, y: DoubleArray, out: DoubleArray, transpose: Boolean = false): DoubleArray

Apply Q (or Qᵀ when transpose) from qr to y into out, which is returned. out may be y.

Link copied to clipboard

The backend currently filling slot.

Link copied to clipboard
open override fun cholesky(a: MatrixLike, policy: CholeskyPolicy = CholeskyPolicy.Strict): DenseMatrix

Lower-triangular Cholesky decomposition A = L * LT, returned as a fresh matrix.

Link copied to clipboard
open override fun factor(a: DenseMatrix): LuDecomposition

LU factorization with partial pivoting of a square a (LAPACK dgetrf); a is not modified. Allocates the factor buffers; factorInto refactorizes into existing ones.

open override fun factor(a: SparseMatrix, equilibrate: Boolean = false, dropTolerance: Double = NO_DROP): SparseFactorization

Factorize the square a into something solvable, never null.

Link copied to clipboard

Refactorize a into out's existing buffers, returning out. A periodic refactorization — the simplex rebuilding its basis, a filter re-decomposing a covariance — otherwise allocates an copy and a pivot array each time; this reuses both. out must have the same dimension as a, and its previous contents are discarded.

Link copied to clipboard
open override fun gemm(a: DenseMatrix, b: DenseMatrix): DenseMatrix

Matrix-matrix product A · B into a fresh matrix (restricted gemm with alpha = 1, beta = 0); A.cols must equal B.rows.

open override fun gemm(alpha: Double, a: DenseMatrix, transposeA: Boolean, b: DenseMatrix, transposeB: Boolean, beta: Double, c: DenseMatrix)

In-place matrix-matrix accumulate C = alpha · op(A) · op(B) + beta · C (full BLAS dgemm), where op transposes its operand when transposeA / transposeB is set. Shapes must satisfy op(A): m×k, op(B): k×n, C: m×n. Per BLAS convention, beta == 0.0 overwrites c without reading it, and alpha == 0.0 reduces to the beta scale.

Link copied to clipboard
open override fun gemv(a: DenseMatrix, x: DoubleArray, transpose: Boolean = false): DoubleArray

Matrix-vector product A · x, or Aᵀ · x when transpose, into a fresh result (restricted gemv with alpha = 1, beta = 0).

open override fun gemv(alpha: Double, a: DenseMatrix, x: DoubleArray, beta: Double, y: DoubleArray, transpose: Boolean = false)

In-place matrix-vector accumulate y = alpha · op(A) · x + beta · y (full BLAS dgemv), where op(A) is Aᵀ when transpose. Per BLAS convention, beta == 0.0 overwrites y without reading it (it may be uninitialized), and alpha == 0.0 reduces to the beta scale.

open override fun gemv(a: SparseMatrix, x: DoubleArray, transpose: Boolean = false): DoubleArray

A · x, or Aᵀ · x when transpose, into a fresh result — the restricted gemv with alpha = 1, beta = 0.

open override fun gemv(alpha: Double, a: SparseMatrix, x: DoubleArray, beta: Double, y: DoubleArray, transpose: Boolean = false)

In-place y = alpha · op(A) · x + beta · y, where op(A) is Aᵀ when transpose — the sparse dgemv. Per BLAS convention beta == 0.0 overwrites y without reading it, so it may arrive uninitialized, and alpha == 0.0 reduces to the beta scale.

Link copied to clipboard
open override fun ger(alpha: Double, x: DoubleArray, y: DoubleArray, a: DenseMatrix)

Rank-one update A = A + alpha · x · yᵀ (BLAS dger).

Link copied to clipboard
open override fun invert(lu: LuDecomposition, workspace: Workspace? = null): DenseMatrix

Invert a general matrix from its LU factorization: returns A⁻¹ given P·A = L·U (LAPACK dgetri).

Link copied to clipboard
open override fun invertSpd(L: DenseMatrix, workspace: Workspace? = null): DenseMatrix

Invert an SPD matrix from its Cholesky factor: returns A^-1 given L = chol(A).

Link copied to clipboard

Whether slot is filled by something other than koblas's own portable implementation.

Link copied to clipboard
open override fun ldl(a: DenseMatrix, workspace: Workspace? = null): LdlDecomposition

Symmetric indefinite factorization A = L·D·Lᵀ with Bunch–Kaufman partial pivoting (LAPACK dsytrf, lower). As with Blas.symv, only the lower triangle of a is read — the strictly upper triangle may hold anything — and a is not modified. Use this where the matrix is symmetric but not positive definite (KKT systems); for SPD matrices cholesky is cheaper.

Link copied to clipboard
open override fun qr(a: DenseMatrix, workspace: Workspace? = null): QrDecomposition

QR factorization A = Q·R of an m×n a via Householder reflections (LAPACK dgeqrf); a is not modified and any shape is accepted. Rank deficiency is not detected — zero diagonal entries of R surface in solveLeastSquares as infinities/NaNs, following the triangular-solve convention.

Link copied to clipboard
open override fun rcond(lu: LuDecomposition, anorm: Double, workspace: Workspace? = null): Double

Reciprocal condition number estimate 1 / (anorm · est(‖A⁻¹‖₁)) from a factorization (LAPACK dgecon). anorm is the 1-norm of the original, unfactored matrix (see norm1), which the caller computes before factoring. Returns 1.0 for the empty factorization and exactly 0.0 when lu is singular or anorm is zero.

Link copied to clipboard

Throws unless every one of slots is filled by an accelerated backend.

Link copied to clipboard
open override fun solve(ldl: LdlDecomposition, b: DenseMatrix): DenseMatrix

Solve A · X = B for the b.cols right-hand-side columns of b at once against a symmetric indefinite factorization (LAPACK dsytrs with nrhs); returns a fresh X. Backends may substitute a native block solve.

open override fun solve(ldl: LdlDecomposition, b: DoubleArray): DoubleArray

Solve A · x = b for a symmetric indefinite factorization ldl (LAPACK dsytrs); returns a fresh x. Symmetry makes the transposed solve identical, so there is no transpose flag. Allocates the result; solveInto writes into a caller-owned destination instead.

open override fun solve(lu: LuDecomposition, b: DenseMatrix, transpose: Boolean = false): DenseMatrix

Solve A · X = B (or Aᵀ · X = B when transpose) for the b.cols right-hand-side columns of b at once (LAPACK dgetrs with nrhs); returns a fresh X. The default runs the permutation and the two triangular block solves directly on the shared packed format; backends may substitute a native block solve.

open override fun solve(lu: LuDecomposition, b: DoubleArray, transpose: Boolean = false): DoubleArray

Solve A · x = b (or Aᵀ · x = b when transpose) for the factorization lu (LAPACK dgetrs); returns a fresh x. transpose serves the simplex's BTRAN (Bᵀ y = c) against a factored basis. Allocates the result; solveInto writes into a caller-owned destination instead.

Link copied to clipboard
open override fun solveInto(ldl: LdlDecomposition, b: DoubleArray, out: DoubleArray): DoubleArray

Solve A · x = b into out, which is returned; allocates nothing. out may be b.

open override fun solveInto(ldl: LdlDecomposition, b: DenseMatrix, out: DenseMatrix, workspace: Workspace? = null): DenseMatrix

Solve A · X = B into out, which is returned. out may be b.

open override fun solveInto(lu: LuDecomposition, b: DenseMatrix, out: DenseMatrix, transpose: Boolean = false, workspace: Workspace? = null): DenseMatrix

Solve A · X = B (or Aᵀ · X = B when transpose) into out, which is returned. out may be b. The transposed direction stages a block before scattering its rows through the permutation, so pass a workspace to lend that n·nrhs buffer.

open override fun solveInto(lu: LuDecomposition, b: DoubleArray, out: DoubleArray, transpose: Boolean = false, workspace: Workspace? = null): DoubleArray

Solve A · x = b (or Aᵀ · x = b when transpose) into out, which is returned. Nothing is allocated, so a loop that owns its destination — a simplex FTRAN/BTRAN against a factored basis, a filter update — runs without touching the collector. out may be the same array as b.

Link copied to clipboard
open override fun solveLeastSquares(qr: QrDecomposition, b: DoubleArray, workspace: Workspace? = null): DoubleArray

Least-squares solve min ‖A·x − b‖₂ from the factorization (the dgels shape): requires m ≥ n and full column rank, returns the length-n solution x = R⁻¹·(Qᵀb)[0..n). This is the kernel square-root/array filters build on; it composes with cholesky rank-one updates for sliding-window problems.

Link copied to clipboard
open override fun solveLeastSquaresInto(qr: QrDecomposition, b: DoubleArray, out: DoubleArray, workspace: Workspace? = null): DoubleArray

Least-squares solve into out, which has length n and is returned. The Qᵀb product needs a length-m intermediate, so pass a workspace to make the call allocation-free.

Link copied to clipboard
open override fun solveMinimumNorm(qr: QrDecomposition, b: DoubleArray, workspace: Workspace? = null): DoubleArray

Minimum-norm solution of the underdetermined consistent system A · x = b for a wide m×n A with m <= n and full row rank (LAPACK dgels's underdetermined shape, via QR of the transpose instead of LQ): pass the factorization qr(Aᵀ). With Aᵀ = Q·R we have A = Rᵀ·Qᵀ, so a forward solve Rᵀ·w = b followed by x = Q·(w padded with zeros) gives the solution of smallest 2-norm. b has length m; the result has length n. Rank deficiency is not detected and surfaces as infinities/NaNs, following the triangular-solve convention.

Link copied to clipboard
open override fun solveMinimumNormInto(qr: QrDecomposition, b: DoubleArray, out: DoubleArray, workspace: Workspace? = null): DoubleArray

Minimum-norm solve into out, which has length m (the wide system's column count) and is returned. A length-n intermediate holds the forward solve, so pass a workspace to make the call allocation-free.

Link copied to clipboard
open override fun solveSpd(L: DenseMatrix, b: DoubleArray): DoubleArray

Solve A * x = b for x, given L = chol(A) (lower-triangular, A = L * LT). Allocates a fresh result vector; b is not modified.

Link copied to clipboard
open override fun symm(alpha: Double, a: DenseMatrix, b: DenseMatrix, beta: Double, c: DenseMatrix, lower: Boolean = true, right: Boolean = false)

In-place symmetric matrix-matrix accumulate C = alpha · A · B + beta · C, or C = alpha · B · A + beta · C when right (BLAS dsymm). As with symv, only the triangle of the symmetric a selected by lower is read. Shapes: b and c agree, and a is square with dimension B.rows (left) or B.cols (right). Per BLAS convention, beta == 0.0 overwrites c without reading it, and alpha == 0.0 reduces to the beta scale.

Link copied to clipboard
open override fun symv(alpha: Double, a: DenseMatrix, x: DoubleArray, beta: Double, y: DoubleArray, lower: Boolean = true)

In-place symmetric matrix-vector accumulate y = alpha · A · x + beta · y for a symmetric a (BLAS dsymv). Only the triangle selected by lower (diagonal included) is read; the opposite strict triangle may hold anything. Exploits symmetry for roughly half the memory traffic of gemv. Per BLAS convention, beta == 0.0 overwrites y without reading it, and alpha == 0.0 reduces to the beta scale.

Link copied to clipboard
open override fun syr(alpha: Double, x: VectorLike, a: DenseMatrix, uplo: Uplo = Uplo.FULL)

Symmetric rank-1 update A += alpha · x · xᵀ (BLAS dsyr), writing the triangle(s) uplo selects.

Link copied to clipboard
open override fun syr2(alpha: Double, x: VectorLike, y: VectorLike, a: DenseMatrix, uplo: Uplo = Uplo.FULL)

Symmetric rank-2 update A += alpha · (x · yᵀ + y · xᵀ) (BLAS dsyr2), writing the triangle(s) uplo selects.

Link copied to clipboard
open override fun syr2k(alpha: Double, a: DenseMatrix, b: DenseMatrix, transpose: Boolean, beta: Double, c: DenseMatrix, uplo: Uplo = Uplo.FULL)

Symmetric rank-2k update C = alpha · (op(A) · op(B)ᵀ + op(B) · op(A)ᵀ) + beta · C (BLAS dsyr2k), where op transposes when transpose.

Link copied to clipboard
open override fun syrk(alpha: Double, a: DenseMatrix, transpose: Boolean, beta: Double, c: DenseMatrix, uplo: Uplo = Uplo.FULL, workspace: Workspace? = null)

In-place symmetric rank-k accumulate C = alpha · A·Aᵀ + beta · C, or alpha · Aᵀ·A + beta · C when transpose (BLAS dsyrk). With the default Uplo.FULL the full symmetric result is produced (the alpha term is applied to both triangles, and beta scales all of c); with Uplo.LOWER / Uplo.UPPER the standard dsyrk semantics apply — only the selected triangle is written and beta-scaled, the opposite strict triangle untouched. c must be square with dimension op(A).rows. Per BLAS convention, beta == 0.0 overwrites without reading (within the written region), and alpha == 0.0 reduces to the beta scale.

Link copied to clipboard
open override fun trmm(a: DenseMatrix, b: DenseMatrix, lower: Boolean, transpose: Boolean = false, unitDiag: Boolean = false, right: Boolean = false)

Multiply B = op(T) · B, or B = B · op(T) when right (BLAS dtrmm), the counterpart of trsm.

Link copied to clipboard
open override fun trmv(a: DenseMatrix, x: DoubleArray, lower: Boolean, transpose: Boolean = false, unitDiag: Boolean = false)

Multiply x = op(T) · x in place (BLAS dtrmv), the product counterpart of trsv.

Link copied to clipboard
open override fun trsm(a: DenseMatrix, b: DenseMatrix, lower: Boolean, transpose: Boolean = false, unitDiag: Boolean = false, right: Boolean = false)

Solve op(T) · X = B in place, or X · op(T) = B when right (BLAS dtrsm): b holds the right-hand sides on entry and the solutions on return. Flags follow trsv. From the left the right-hand sides are the columns of b; from the right, its rows.

Link copied to clipboard
open override fun trsv(a: DenseMatrix, x: DoubleArray, lower: Boolean, transpose: Boolean = false, unitDiag: Boolean = false)

Solve op(T) · x = b in place (BLAS dtrsv), where T is the lower or upper triangle of the square a, op transposes when transpose, and unitDiag takes the diagonal as 1 without reading it. x holds the right-hand side on entry and the solution on return. Only the selected triangle is read, so the rest of a may hold anything.

open override fun trsv(a: SparseMatrix, x: DoubleArray, lower: Boolean, transpose: Boolean = false)

Solve op(T) · x = b in place, where T is the lower or upper triangle of the square a and op transposes when transpose — the sparse dtrsv. x holds the right-hand side on entry and the solution on return.

Link copied to clipboard
open override fun trtri(a: DenseMatrix, lower: Boolean, unitDiag: Boolean = false): DenseMatrix

Invert a triangular matrix in place of a fresh result (LAPACK dtrtri): returns T⁻¹ for the lower or upper triangle of the square a, taking the diagonal as 1 when unitDiag.