fix(linalg): refuse non-finite input in dense Cholesky, Eigen and rank-one updates

Assisted-by: GLM 5.3 Flash
This commit is contained in:
2026-09-27 11:12:43 +02:00
parent af4ee19703
commit 7bc030c78b
10 changed files with 144 additions and 11 deletions
+14 -3
View File
@@ -71,14 +71,25 @@ func cholRankOne(l, x *core.Array, name string, sign int) (*core.Array, error) {
}
// The rotations below assume a lower triangular factor; a nonzero
// strict upper triangle would silently corrupt the sweep, so it is
// refused up front.
// refused up front, and so is a non-finite entry anywhere: the
// diagonal test cannot see a NaN, and the hyperbolic square of an
// Inf overflows mid-sweep. The sparse twin refuses the same input.
for i := range n {
for j := i + 1; j < n; j++ {
if out.RawFloats()[i*n+j] != 0 {
for j := range n {
w := out.RawFloats()[i*n+j]
if math.IsNaN(w) || math.IsInf(w, 0) {
return nil, base.Errf("%s: factor entry [%d,%d] is not finite", name, i, j)
}
if j > i && w != 0 {
return nil, base.Errf("%s: the factor must be lower triangular (nonzero entry at row %d, column %d)", name, i, j)
}
}
}
for i := range n {
if math.IsNaN(v[i]) || math.IsInf(v[i], 0) {
return nil, base.Errf("%s: entry %d is not finite", name, i)
}
}
// The modified matrix reads [L, x]·J·[L, x]ᵀ with J = diag(I, ±1):
// one sweep of (hyperbolic for −1, orthogonal for +1) rotations
// eliminates the vector column, and the surviving columns are the