Files
tensor/linalg/doc.go
T

85 lines
4.4 KiB
Go
Raw Normal View History

2026-09-03 10:00:00 +02:00
// Copyright (c) 2026 Petr Balvín <opensource@petrbalvin.org> (https://petrbalvin.org)
// SPDX-License-Identifier: MIT
// Package linalg is the dense and sparse linear algebra of the library:
// the factorisations, the solvers, the eigensolvers, the matrix
// functions and the Krylov methods, over the array types the core
// provides. Every symbol here is re-exported by the root package, so
// user code may import that facade alone and write tensor.Solve.
//
// # Dense
//
// The dense surface takes a 2-D array and answers arrays. Solve, Inv
// and Det run one LU decomposition with partial pivoting; Cholesky,
// QR, LeastSquares, RRQR and the tridiagonal pair SolveTridiagonal and
// SolveCyclicTridiagonal are the other factorisations and their solves.
// Eigen, EigenComplex, EigenGeneral, EigenGeneralised, SVD, SVDComplex
// and SchurComplex are the spectral decompositions, and Pinverse,
// MatrixRank and Cond read the singular spectrum that SVD produces.
// SolveTikhonov, SolveTruncated and SolveRRQR answer a system whose
// data does not determine the solution. MatrixExp, MatrixSqrt and
// MatrixLog are the matrix functions; FitPolynomial, PolynomialRoots
// and CubicSpline carry the polynomial work; GMRES solves a system
// presented as an operator rather than as a matrix.
//
// # Sparse
//
// The sparse surface starts from a COO matrix (the root package's
// tensor.SparseCOO) and converts it once into the compressed view the
// algorithm wants: SparseCSR for the iterative solvers, the Lanczos
// eigensolver and the row-wise products, SparseCSC for the direct
// factorisations and the column-wise scatter. The direct route is
// NewSparseCholesky for a symmetric positive definite matrix, under a
// fill-reducing SparseOrdering, and NewSparseLU for a general square
// matrix; NewSparseILU builds the incomplete factorisation the Krylov
// solvers take as a preconditioner. SpSolve and SpSolveBiCGSTAB, with
// their two complex counterparts, are the iterative solves; SpLSQR and
// SpLSMR are the least-squares iterations; SpEigen, SpEigenGeneral and
// the two complex forms are the Krylov eigensolvers; SpExpApply
// applies a matrix exponential to a vector without forming the matrix.
//
// # The pipeline
//
// Pipe and Pipeline read a sequence of array transformations as one
// expression. The evaluation is eager and each step allocates a new
// array. There is no lazy graph, no autograd and no backpropagation
// here: a failed step is recorded, the steps after it become no-ops,
// and Result returns the first error alongside the array.
//
// # Conventions
//
// The dense routines compute in float64 and complex128: int and float32
// inputs promote on the way in, and one complex operand promotes the
// whole call. A sparse routine with no complex form refuses a complex
// input instead of promoting it, and the four complex entry points name
// their element type in the name: SpSolveComplexCG,
// SpSolveComplexBiCGSTAB, SpEigenComplex and SpEigenGeneralComplex.
//
// Symmetry is checked where the algorithm depends on it, within a
// scale-relative 1e-12 tolerance by Eigen, EigenComplex, SpEigen,
// SpEigenComplex, SpSolve, SpSolveComplexCG and SpExpApply. It is not
// checked where the algorithm does not need it: EigenGeneralised
// requires a symmetric a and does not verify it, and the two general
// sparse eigensolvers do not screen for non-finite entries, which come
// back as NaN Ritz pairs.
//
// A shape mismatch, a singular matrix, a rank-deficient system, a
// matrix that leaves the positive definite cone during a rank-one
// update, and a Krylov iteration that exhausts its budget with the
// tolerance unmet are all errors naming themselves. An unconverged
// iterative solve returns no estimate, never a silent approximation.
//
// Results are reproducible: the kernels that dispatch over workers
// split the output space rather than the reduction, so an element is
// computed by the same arithmetic sequence whatever the worker count.
//
// # Constructors
//
// The array type belongs to the core, and its general constructors are
// re-exported by the root package as tensor.FromFloats, tensor.Zeros,
// tensor.Identity and their neighbours. A caller that imports this
// package on its own, without the root facade, has ArrayFromFloatsSafe
// for building the input to a call: it copies the slice it is given,
// so the caller keeps ownership of the values it passed in.
package linalg