# The tests of lib/hf/eigen that compare it with reference data (lib/hfref) # or run the sweep drivers (lib/hf/sweep). They live here so that a program # that uses lib/hf/eigen does not load the references. from hf.eigen import eig_jacobi, eig_methods, eig_ql, eig_random_sym, eig_residual from hf.sweep import ( sw_check3_arr, SW_REP_INDEX, sw_rep_new, SW_REP_NSTRAT, SW_REP_STRAT, sweep3_arr, ) #| Test member with a planted bug: member 0's result with the third #| eigenvalue raised by `1e-9`. def eig_t_bad(A: Arr, B: Arr, opts: Arr) -> Arr { R = eig_ql(A, B, opts) R[0, 2] = R[0, 2] + 1.0e-9 return R } test "the sweep over the registry agrees on eigenvalues and blames a planted bug" { # a result is [n + 1, n]: the n eigenvalues, then the vectors; the sweep # compares the eigenvalues eig_ns = 9 eig_A = eig_random_sym(eig_ns, 99) eig_rep = sw_rep_new() eig_R = sweep3_arr(eig_methods(), eig_A, eig_A, eig_A, (eig_ns + 1) * eig_ns, eig_ns, 1.0e-12, eig_rep) assert_near(eig_rep[SW_REP_NSTRAT], 3, 0.0) assert_lt(eig_residual(eig_A, eig_R), 1.0e-13) # a bad member listed first: the median still blames it, at eigenvalue 2 eig_out = zeros(eig_ns + 1, eig_ns) eig_ok = sw_check3_arr([eig_t_bad, eig_ql, eig_jacobi], eig_A, eig_A, eig_A, (eig_ns + 1) * eig_ns, eig_ns, 1.0e-12, eig_rep, eig_out) assert_near(eig_ok, 0.0, 0.0) assert_near(eig_rep[SW_REP_STRAT], 0.0, 0.0) assert_near(eig_rep[SW_REP_INDEX], 2.0, 0.0) } # SPDX-License-Identifier: MIT OR Apache-2.0 # SPDX-FileCopyrightText: 2026 The Viv authors