Found by phugoid rung 0 (ledgered as phugoid GAPS.md G1).
Extracting flight modes needs eigenvalues of a 4x4 state matrix (equivalently the complex roots of its characteristic quartic). lib/linalg.eigs stops at eigenvalues_2x2; lib/numerics.eigs has power_iteration (dominant eigenvalue only, real). phugoid hand-rolled both halves in modes.eigs:
- charpoly4: Faddeev-LeVerrier characteristic polynomial from a matrix (~15 lines, generalizes to NxN with lib/linalg mat ops)
- dk_roots: Durand-Kerner complex root finder on [re, im] pairs (~30 lines)
Both are generic and validated in phugoid against published eigenvalues (Caughey 747, eq. 5.54/5.95) plus residual/Vieta identities and a planted-fault matrix — a ready-made test corpus if adopted.
Candidate API: charpoly of A, poly_roots of coeffs (complex roots as [re, im] pairs), or a direct eigenvalues of A. Sits naturally in lib/linalg or lib/numerics.
Related: # (complex arithmetic is a prerequisite shape for the return type).
Found by phugoid rung 0 (ledgered as phugoid GAPS.md G1).
Extracting flight modes needs eigenvalues of a 4x4 state matrix (equivalently the complex roots of its characteristic quartic). lib/linalg.eigs stops at eigenvalues_2x2; lib/numerics.eigs has power_iteration (dominant eigenvalue only, real). phugoid hand-rolled both halves in modes.eigs:
Both are generic and validated in phugoid against published eigenvalues (Caughey 747, eq. 5.54/5.95) plus residual/Vieta identities and a planted-fault matrix — a ready-made test corpus if adopted.
Candidate API: charpoly of A, poly_roots of coeffs (complex roots as [re, im] pairs), or a direct eigenvalues of A. Sits naturally in lib/linalg or lib/numerics.
Related: # (complex arithmetic is a prerequisite shape for the return type).