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
+25 -1
View File
@@ -5,8 +5,10 @@ package linalg
import (
"math"
"sourcedock.dev/petrbalvin/tensor/internal/core"
"strings"
"testing"
"sourcedock.dev/petrbalvin/tensor/internal/core"
)
// spdSample builds a deterministic symmetric positive definite matrix:
@@ -156,3 +158,25 @@ func TestCholeskyRankOneErrors(t *testing.T) {
t.Fatal("expected an error for a complex vector")
}
}
// TestCholeskyRankOneRefusesNonFinite pins the refusal of a poisoned
// factor or vector: the diagonal test cannot see a NaN, so the sweep
// would answer an all-NaN factor with a nil error, where the sparse
// twin refuses the same modification.
func TestCholeskyRankOneRefusesNonFinite(t *testing.T) {
l, err := Cholesky(mustFromFloats(t, []float64{4, 0, 0, 1}, 2, 2))
if err != nil {
t.Fatalf("Cholesky: %v", err)
}
badVec := floatsToArray([]float64{math.NaN(), 0.1}, []int{2})
if _, err := CholeskyUpdate(l, badVec); err == nil || !strings.Contains(err.Error(), "not finite") {
t.Fatalf("CholeskyUpdate(NaN vector): %v", err)
}
if _, err := CholeskyDowndate(l, badVec); err == nil || !strings.Contains(err.Error(), "not finite") {
t.Fatalf("CholeskyDowndate(NaN vector): %v", err)
}
badFac := mustFromFloats(t, []float64{4, 0, math.Inf(1), 1}, 2, 2)
if _, err := CholeskyUpdate(badFac, floatsToArray([]float64{0.1, 0.1}, []int{2})); err == nil || !strings.Contains(err.Error(), "not finite") {
t.Fatalf("CholeskyUpdate(Inf factor): %v", err)
}
}