Use this guidance when changing scalar math, packet math, decompositions, eigensolvers, linear solvers, matrix functions, or numerical tests. The nearby implementation, tests, and public documentation in the checked-out tree are the source of truth; this file defines the review standard rather than an algorithm.
VERIFY_IS_APPROX as the acceptance criterion for a newly designed numerical kernel. Its defaults in test/numerical_test_helpers.h are deliberately loose test-framework tolerances, not machine-epsilon or ULP bounds.Test regular inputs across the full supported domain and concentrate samples near discontinuities, roots, extrema, range-reduction boundaries, overflow and underflow thresholds, and difficult rounding cases. Use an error metric that matches the contract:
ULP accuracy tool supports MPFR and standard-library references. The coefficient-wise math table records existing accuracy expectations.Test special values explicitly: +0, -0, positive and negative infinity, quiet NaN, normal/subnormal boundaries, the smallest subnormal, and values immediately on both sides of each domain boundary. Approximate comparisons can treat two NaNs as matching and cannot distinguish the sign of zero. Therefore use explicit predicates:
(numext::isnan)(value).(numext::isinf)(value) and check its sign separately.(numext::signbit)(value).Prefer backward-error and invariant checks over forward comparison with one reference answer. Depending on the operation, test normalized reconstruction error, solve residual, eigenpair residual, orthogonality/unitarity, rank, symmetry, or structure preservation. Express tolerances as named bounds derived from NumTraits<RealScalar>::epsilon(), dimension, and the expected operation count; avoid unexplained decimal literals.
Forward error is condition-dependent. A well-conditioned problem may support a tight result comparison, while a near-singular problem can have a small residual and a large forward error. Estimate or bound conditioning when a forward comparison is necessary, and do not reject a stable answer merely because a different stable algorithm selects different vectors, signs, phases, pivots, or bases for a clustered invariant subspace.
Exercise structures relevant to the algorithm: well-conditioned, ill-conditioned, near-singular, singular, rank-deficient, clustered/repeated spectra, extreme scaling, and the matrix properties promised by the API. Useful families include Hilbert, Vandermonde, Wilkinson, Toeplitz/KMS, banded, defective or near-defective, and barely positive-definite matrices. Check error/status reporting as well as successful results.
For uniform transformations and built-in operations on small structured submatrices, use fixed-size block expressions, such as T.template block<2, 2>(i, i).determinant(), so the mathematical structure and compile-time dimensions remain explicit. This is especially useful for Schur blocks, pivots, and small panels; use coefficient access instead when the entries require distinct formulas.
Where LAPACK has a counterpart, require comparable backward stability, conditioning behavior, pivoting robustness, and test-category coverage. Do not require identical internal steps, pivot order, eigenvector signs/phases, or roundoff-level output. Higham‘s Accuracy and Stability of Numerical Algorithms and Golub and Van Loan’s Matrix Computations are standard references for choosing error measures and adversarial inputs.
test/packetmath.cpp and, for special functions, unsupported/test/special_packetmath.cpp. Report backends that were not available locally.A scaling threshold or overflow budget stated in a comment is part of the code: when the operation it bounds widens (a multiply path gains a divide, a growth factor becomes a parameter), re-derive the bound rather than carrying the old expression forward. Early exits and length-one shortcuts must satisfy the same invariant as the general path — they are where a guard added later tends not to reach — so give them regression coverage at the boundary they handle.
Require gradual-underflow behavior when the target and active floating-point mode support it. Some targets or build modes have fixed or enabled flush-to-zero (FTZ) behavior, so an impossible subnormal expectation must be detected and conditionalized rather than made flaky. Use the facilities and platform notes in test/fp_control.h and nearby packet tests.
Keep an FTZ exception narrow: document the affected target and operation, preserve and restore controllable FP state, and still verify normal values, NaN, infinity, signed zero, and scalar/packet consistency in that mode. Do not use FTZ as a blanket reason to skip underflow tests or to hide accidental compiler flags that changed semantics.
Learn algorithms from published papers, standards, and textbooks, then write an original Eigen implementation. Cite the specific reference inline by author/year and algorithm, routine, paper, or working-note identifier. If adapting source code rather than an idea, first confirm that its license and provenance are compatible with Eigen. A citation does not make copied expression from an incompatible or unknown source permissible, and attribution must never be invented. Include the numerical rationale for non-obvious scaling, pivoting, stopping, and tolerance choices.