Phase 2 — Math Layer
Status: complete. Epic E2 (#3, sub-issues #24–#32) merged.
Phase 2 delivered the header-only, type-generic math layer
(math/include/branes/math/, namespace branes::math) that every estimator is built
from. See the Math Layer Overview for the full surface; this page
is the phase summary.
What landed
Section titled “What landed”- Lie groups —
SO3,SE3,Sim3with exp/log, composition, adjoints, and left/right Jacobians (with inverses). See Lie Groups. - Fixed-size primitives (
lie/detail.hpp) —Vec<T,N>,Mat<T,R,C>,hat/vee,dot/cross/norm, and per-scalar math shims (sqrt_,sin_,atan2_, …). - Non-linear least squares — Gauss-Newton and Levenberg-Marquardt with analytical, finite-difference-validated Jacobians and golden-value tests. See NLS.
- Camera models — pinhole+radtan, equidistant fisheye, unified omnidirectional, each with project/unproject/distort + analytical Jacobian. See Cameras.
- Linear algebra — tensor views, sparse matrices, Krylov inner solvers (MTL5 ITL), sparse direct solvers, dense Cholesky/SPD solve.
Design rules ratified
Section titled “Design rules ratified”- Scalar-generic, never
double-hardcoded — everything templates overbranes::math::Scalar; the same code runs indouble,float, and Universal posits. - Call the shims, not
std::— algorithms calldetail::sqrt_etc. so they dispatch correctly per scalar type. - Analytical + FD-validated Jacobians — hand-derived Jacobians are checked against finite differences, so higher layers can trust them at runtime.
Gotchas recorded
Section titled “Gotchas recorded”- Universal include order — include
<number>/<type>.hppbefore<number>/mathlib.hpp, guarded with// clang-format offso the include-regroup formatter doesn’t reorder them and break posit compilation. - Braced float-narrowing — write parenthesized
T(1e-12)rather than bracedT{1e-12}for sub-epsilon constants, so they instantiate forfloat/posits.
This layer is the foundation for Phase 3 — VIO.