Bug fixes:
1. computeDirect 3x3: eigenvalues from computeRoots() are theoretically
sorted via the trigonometric formula, but floating-point rounding
(especially in float) can break the ordering. Add a 3-element sorting
network after computeRoots() to guarantee sorted output.
2. compute(): Inf input silently returns Success with garbage results,
unlike NaN which correctly returns NoConvergence. Add an isfinite()
check on the scaling factor (which is maxCoeff of the matrix) to
detect Inf/NaN early and return NoConvergence.
3. computeFromTridiagonal(): lacks the equilibration scaling that
compute() applies, causing overflow and NoConvergence for tridiagonal
matrices with large entries. Add the same scale-to-[-1,1] pattern.
New tests:
- Eigenvalue sorting verification (both iterative and direct solvers)
- Repeated/degenerate eigenvalues (all equal, multiplicity n-1, two
clusters, nearly repeated separated by O(epsilon))
- Extreme eigenvalue ranges (high condition number spanning many orders
of magnitude, near-underflow, near-overflow, mixed positive/negative,
rank-deficient with zero eigenvalue)
- computeFromTridiagonal with large and tiny values
- Diagonal matrices (eigenvalues must match sorted diagonal)
- operatorInverseSqrt accuracy (sqrtA*invSqrtA=I, invSqrtA*A*invSqrtA=I,
symmetry)
- RowMajor storage for computeDirect (2x2, 3x3, float, double) and
iterative solver (dynamic RowMajor)
- Inf input detection
- Tridiagonal structure verification (off-tridiagonal entries are zero)
- Direct solver stress tests: 3x3 (near-planar covariance, triple
eigenvalue, double eigenvalue, large off-diagonal, nearly singular)
and 2x2 (equal eigenvalues, tiny off-diagonal, huge diagonal ratio,
anti-diagonal dominant, negative entries)
- Tightened unitary tolerance from fixed 32*test_precision to
4*n*epsilon (scales with matrix size)
- Fixed typo: "expponential" -> "exponential"
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>