VectorKernels
The vector-vector routines — dot, axpy, scale, nrm2, asum — as a backend half, alongside Blas and Lapack.
Every implementation of these routines is one of these, which was not always true and is the point of the interface. koblas ships a compile-time specialization per target (PlatformVectorKernels: Vector API SIMD on the JVM, scalar loops elsewhere) and may additionally have a host BLAS registered; both are VectorKernels, and RoutedVectorKernels picks between them by run length.
Why these sit below the Blas seam
They do nanoseconds of work, so a virtual call per invocation would cost more than the kernel. That is why the compiled-in kernels exist at all, and why a registered backend is consulted only once a run is long enough for a foreign call to pay for itself — DispatchThresholds.level1. What it is not is a reason for the compiled kernels to have a different shape from a registered one: they used to be loose expect fun platformDot-style functions implementing no interface, so "the kernels" meant two unrelated things depending on where you looked, and the seam needed null to mean "the other kind". One interface removes both problems.
What is not here, and why
iamax is excluded on a contract question rather than a performance one. koblas documents its tie-breaking — first by index for a dense vector, storage order for a sparse one — and its behaviour for an all-unstored vector. idamax implementations do not agree with each other on where a NaN ranks, so routing it would make the answer depend on whether a host library happened to be installed. It could join once that behaviour has been checked against the libraries koblas actually dispatches to.
copy and swap are excluded on the arithmetic: copyInto and an element exchange are already the best available, so a foreign call could only lose.
Implementations must agree with PlatformVectorKernels exactly — same result for the same (offset, length) window, no reads outside it — and must be safe to call from any thread that can already call dot. Kernels that disagree silently change results everywhere in the library, since gemv, the factorizations and the eta updates all bottom out here.
Inheritors
Properties
Relative preference among simultaneously available backends: automatic selection through registerBackend — JVM classpath discovery, native startup registration — picks the highest per half. The portable reference is 0; native-accelerated backends rank above it (koblas-openblas 100, koblas-cblas 90).
Functions
asum
axpy
y[yOff..yOff+len-1] += alpha * x[xOff..xOff+len-1], with len >= 1.
dot
Sum a[aOff..aOff+len-1] * b[bOff..bOff+len-1], with len >= 1.
dot4
Four dots against a shared right operand: out[outOff + r] = Sum a[aOff + r*stride + i] * b[bOff + i] for r in 0..3. Four columns of a column-major matrix against one vector, which is the shape gemv and the Aᵀ·B gemm branch need.
The one routine here with a default, because it is the one with no BLAS counterpart: ddot exists, batched ddot does not. The default is four dot calls, which is exactly what a host backend should do — so a host implements this by inheriting it, rather than by not having it.
An implementation that can do better should: the point of the shape is that each b segment is loaded once for all four columns and the four accumulator chains are independent, which cuts load traffic and breaks the dependency chain a single dot is limited by. PlatformVectorKernels overrides it for that reason.
nrm2
Euclidean norm of v[vOff..vOff+len-1], with len >= 1 (BLAS dnrm2).
Must be accurate for components whose squares overflow or underflow — koblas's built-in kernel rescales to stay in range, and netlib dnrm2 does the same, so a plain sqrt(sum of squares) is not a valid implementation.