Single source of truth for Claude and Copilot. CLAUDE.md and
.github/copilot-instructions.md point here. Code-file specifics load on demand from
.github/instructions/. Deployment recipe: roadmap/DEPLOYMENT.md.
Numerical algorithms library (DSP, control, filters, estimators, solvers) for resource-constrained embedded systems. Real-time, deterministic, no heap.
- New algorithms are float-only. Write generic
template<typename T>, addstatic_assert(std::is_floating_point_v<T>, "..."), and instantiate/testfloatonly. - Do NOT implement
Q15/Q31now. The genericTkeeps a fixed-point specialisation cheap later. std::numbers::pi_v<float>— never hardcode constants.
- Forbidden:
new/delete/malloc/free,make_unique/make_shared,std::vector/string/deque/list/map/set. - Use:
infra::BoundedVector<T>::WithMaxSize<N>,infra::BoundedString::WithStorage<N>,infra::BoundedDeque<T>::WithMaxSize<N>,infra::BoundedList<T>::WithMaxSize<N>,std::array<T,N>,std::optional<T>. Stack/static only. No recursion. Tests too.
- No
#pragma GCC optimizeand nooptimizeattribute, in headers or sources. GCC does not inline a callee whose optimization options differ from its caller's, so options set per header or per function turn every small helper on a hot path (element access, accessors,math::wrappers) into an out-of-line call. - The optimization level and floating-point model belong to the consumer and apply to whole
translation units. For embedded targets:
-O2or-O3with-ffast-math -fno-finite-math-only. OPTIMIZE_FOR_SPEEDon hot paths (Filter/Compute/Update/Solve/Step). Pure interfaces exempt. WithNumericalToolbox_ENABLE_OPTIMIZATIONSit forces inlining (always_inline,hot,inline); without it, it expands to nothing.- Use
math::IsFinitefor finiteness checks: a consumer may still build with-ffinite-math-only.
- Allman braces, 4-space indent,
.clang-formatauthoritative. - Brace-init
{}everywhere. PascalCase types/methods, camelCase members, lowercase namespaces. - Functions ≤ ~30 lines.
const/constexpr-correct. Fixed-width ints. Full descriptive names. - No comments except license headers,
NOLINT, and a brief note on genuinely non-obvious math.
- Interfaces = pure virtual classes with a
protected:, non-virtual~I() = default— never avirtualor= 0destructor. A virtual one puts a deleting destructor in every vtable, which linksoperator delete/freeinto heap-free firmware. - Concrete classes declare no destructor unless they need one. Never own or delete through an interface pointer (no
std::unique_ptr<I>): hold the concrete type, passI&. - No exceptions. Use
std::optional<T>or status enums.assert/really_assertfor preconditions. - SOLID + DIP: constructor injection; depend on abstractions. RAII. No virtual calls in real-time paths.
analysis, windowing, control_analysis, controllers, estimators,
filters (active Kalman family — not filters::active), filters::passive, math,
optimization, regularization, solvers, and new:
robust_control, nonlinear_control, motion_profiles.
- Production code calls
math::Sin,math::Cos,math::Abs, etc. fromnumerical/math/Math.hpp. Never callstd::cmath functions directly in production. - If a needed
<cmath>function is missing fromMath.hpp, add aconstexprwrapper there first, then usemath::FunctionNameat the call site. - Each function is individually overridable at compile time via
#ifndef MATH_<NAME>_OVERRIDE(e.g.MATH_SIN_OVERRIDE). Define the macro in CMake and supply your own template definition. - Unit tests call
std::sin,std::cos,std::abs, etc. directly. Never usemath::in tests.
- GoogleTest.
TEST_Fonfloat— noTYPED_TEST, no multi-type. Never plainTEST(). StrictMockonly (noNiceMock/bare). Fixture + aliases in an anonymous namespace; macros outside it.- No redundant tests — implement exactly the spec's enumerated cases, one behavior per test,
Arrange/Act/Assert,
EXPECT_NEAR+math::Tolerance<float>(). No heap. - Coverage ≥ 90 % — measured by SonarQube. Every new algorithm must reach this threshold before merge; CI fails below it.
numerical_add_header_library(<target>),numerical_add_coverage_sources(<target> <Name>.cpp),${NUMERICAL_VISIBILITY}.- Coverage
.cpp:template class <Name><float, ...>;.extern templateguarded by#ifdef NUMERICAL_TOOLBOX_COVERAGE_BUILD. NumericalToolbox_ENABLE_OPTIMIZATIONS(enablesOPTIMIZE_FOR_SPEED) is a usage requirement ofnumerical.math, gated byNUMERICAL_TOOLBOX_ENABLE_OPTIMIZATIONS. Never move it toadd_definitions, and downstream repos must not rename it: linknumerical.*to inherit it.
Design-first doc/<domain>/<Name>.md per doc/TEMPLATE.md. Math/theory/complexity/pitfalls —
no code, no class names, no usage examples. Update doc/<domain>/README.md when adding a new algorithm.
- Minimal prose. No preamble/postamble, no restating the plan, no summaries unless asked.
- Report results as file paths + pass/fail. Don't narrate routine tool calls.
- Don't re-read files already read; batch reads; prefer targeted edits.
- Build:
cmake --preset host && cmake --build --preset host· Test:ctest --preset host.