fix(linalg): converge the Hermitian Jacobi sweep on near-diagonal matrices
Assisted-by: GLM 5.3 Flash
This commit is contained in:
@@ -294,6 +294,39 @@ func subComplex(a, b []complex128) []complex128 {
|
||||
return out
|
||||
}
|
||||
|
||||
// TestEigenComplexNearDiagonalConverges pins the Jacobi sweep against a
|
||||
// matrix whose every off-diagonal entry sits just under the per-entry
|
||||
// skip level while the aggregate off-norm stays above the convergence
|
||||
// threshold: the skip must not freeze the sweep above its own
|
||||
// convergence test, which used to exhaust the passes and report the
|
||||
// nearly diagonal matrix as unconverged.
|
||||
func TestEigenComplexNearDiagonalConverges(t *testing.T) {
|
||||
const n = 30
|
||||
cv := make([]complex128, n*n)
|
||||
for i := range n {
|
||||
cv[i*n+i] = 1
|
||||
}
|
||||
for i := range n {
|
||||
for j := i + 1; j < n; j++ {
|
||||
cv[i*n+j] = complex(0.9e-13, 0)
|
||||
cv[j*n+i] = complex(0.9e-13, 0)
|
||||
}
|
||||
}
|
||||
a, err := core.FromComplexes(cv, n, n)
|
||||
if err != nil {
|
||||
t.Fatalf("FromComplexes: %v", err)
|
||||
}
|
||||
vals, _, err := EigenComplex(a)
|
||||
if err != nil {
|
||||
t.Fatalf("EigenComplex: %v", err)
|
||||
}
|
||||
for i := range n {
|
||||
if math.Abs(vals.FloatAt(i)-1) > 1e-11 {
|
||||
t.Fatalf("eigenvalue %d is %.12g, want 1", i, vals.FloatAt(i))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// TestEigenComplexRefusesNonFinite pins that a poisoned matrix never
|
||||
// reads as Hermitian: the mirror comparison cannot see a NaN
|
||||
// difference, so the entry is refused outright, the way the sparse
|
||||
|
||||
Reference in New Issue
Block a user