Docs / nablatensor-tensor / com.nablatensor.tensor.linalg
final class
DenseLinalg
Reference dense factorizations for row-major float[] matrices: Cholesky, LU with partial pivoting, Householder QR, symmetric eigen (cyclic Jacobi) and thin SVD (one-sided Jacobi), plus the triangular solves built on them.
These are the custom kernels behind Linalg — no BLAS/LAPACK. They are unblocked (O(n³) with poor cache reuse for large n); the point is that nablatensor has factorizations at all, on every backend, via a host round-trip. Every accumulation is done in double and rounded to float only on write, so the F32 results are about as accurate as F32 can represent.
Methods
A (n×n, symmetric positive-definite) → lower-triangular L (n×n) with A = L·Lᵀ. Only the lower triangle of A is read.
LU factorization of A (n×n) with partial pivoting.
Unit-lower L (1s on the diagonal) from a luDecompose packed result.
Upper-triangular U from a luDecompose packed result.
Full Householder QR of A (m×n), m >= n.
Solve A·X = B for X; A (n×n), B (n×p), row-major.
Solve using an existing luDecompose result.
det(A) via LU: product of the U diagonal times the permutation sign.
Eigendecomposition of a symmetric A (n×n): Householder reduction to tridiagonal form followed by the implicit-shift QL iteration (the classic tred2/tql2). O(n³) once for the reduction and the eigenvector accumulation, O(n²) per QL step — the same shape as LAPACK's ssyev, not the O(sweeps·n³) of plain Jacobi.
Thin SVD of A (m×n, m >= n) via the symmetric eigendecomposition of AᵀA = V·Σ²·Vᵀ, then U = A·V·Σ⁻¹.
This reuses the fast eighSymmetric and is far quicker than a one-sided Jacobi SVD, at the cost of squaring the condition number — the smallest singular values of a badly-scaled A lose about half their digits. For a well-conditioned A the reconstruction is accurate to F32.