Skip to content

Commit fbabe8f

Browse files
fix: scope the O3/fast-math pragma to each header instead of leaking it (#347)
Every algorithm header applied `#pragma GCC optimize("O3", "fast-math")` at file scope with no pop, so including any of them switched every function defined later in the translation unit to fast-math (folded NaN checks, reassociation). Bracket each header with push_options/pop_options at the same position the pragma used to be, so the library's own code generation is preserved while consumer code after the include is compiled with the consumer's flags. - 98 headers: push_options + optimize ... pop_options (GCC only; clang never honoured the pragma and warns on it). - ComplexNumber.hpp and TwiddleFactorsTable.hpp: add the scoped pragma; they previously only got fast-math by leaking from earlier headers. - Remove the pragma from four controller test TUs. - Update AGENTS.md, CLAUDE.md, copilot instructions, agent definitions, roadmap recipe and performance doc to the scoped pattern. Closes #334 Claude-Session: https://claude.ai/code/session_01N4pngRiBqeb1xiseKXNLG6 Co-authored-by: Claude <noreply@anthropic.com>
1 parent de14e02 commit fbabe8f

118 files changed

Lines changed: 655 additions & 132 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

‎.claude/agents/algo-implementer.md‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,5 +28,5 @@ from its `roadmap/<domain>/<Name>/` spec into the codebase, following both exact
2828
- **No comments** (except license/`NOLINT`). Allman braces, brace-init.
2929
- **Tests**: `TEST_F` on `float`, `StrictMock` only, anonymous-namespace fixture; implement EXACTLY
3030
the spec's cases — no redundant or extra tests.
31-
- **Embedded**: `#pragma GCC optimize` + `OPTIMIZE_FOR_SPEED` on hot paths.
31+
- **Embedded**: scoped `#pragma GCC push_options`/`optimize`/`pop_options` + `OPTIMIZE_FOR_SPEED` on hot paths.
3232
- **Terse**: no preamble/postamble, no plan restatement, no narration; don't re-read files; batch reads.

‎.claude/agents/planner.md‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ Canonical rules: `AGENTS.md`. Produce plans only — no code edits.
2525
- [ ] No heap; no recursion; tests too
2626
- [ ] `template<typename T>` + `static_assert(std::is_floating_point_v<T>)`; `float` only
2727
- [ ] `TEST_F` on `float` — no `TYPED_TEST`; `StrictMock` only; never plain `TEST()`
28-
- [ ] `#pragma GCC optimize` + `OPTIMIZE_FOR_SPEED` on hot paths
28+
- [ ] scoped `#pragma GCC push_options`/`optimize`/`pop_options` + `OPTIMIZE_FOR_SPEED` on hot paths
2929
- [ ] `doc/` update planned
3030

3131
**Terse**: no preamble/postamble, no plan restatement; don't re-read files; batch reads.

‎.claude/agents/reviewer.md‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ End with totals + verdict: APPROVE / REQUEST CHANGES.
3535
- [ ] `extern template` guarded by `#ifdef NUMERICAL_TOOLBOX_COVERAGE_BUILD`.
3636

3737
**Embedded optimizations (WARNING)**
38-
- [ ] `#pragma GCC optimize("O3","fast-math")` after `#pragma once` in algorithm headers.
38+
- [ ] `#pragma GCC push_options` + `optimize("O3","fast-math")` after `#pragma once`, matching `pop_options` at end of algorithm headers (no TU leak; none in test `.cpp`).
3939
- [ ] `OPTIMIZE_FOR_SPEED` on `Filter/Compute/Update/Solve/Step`.
4040

4141
**Namespaces (WARNING)**

‎.github/agents/algo-implementer.agent.md‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,5 +31,5 @@ Authoritative rules: `AGENTS.md`. Recipe: `roadmap/DEPLOYMENT.md`. Follow both e
3131
- **No comments** (except license/`NOLINT`). Allman braces, brace-init.
3232
- **Tests**: `TEST_F` on `float`, `StrictMock` only, anonymous-namespace fixture; implement EXACTLY
3333
the spec's cases — no redundant or extra tests.
34-
- **Embedded**: `#pragma GCC optimize` + `OPTIMIZE_FOR_SPEED` on hot paths.
34+
- **Embedded**: scoped `#pragma GCC push_options`/`optimize`/`pop_options` + `OPTIMIZE_FOR_SPEED` on hot paths.
3535
- **Terse**: no preamble/postamble, no plan restatement, no narration; don't re-read files; batch reads.

‎.github/agents/planner.agent.md‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ Canonical rules: `AGENTS.md`. Produce plans only — no code edits.
2828
- [ ] No heap; no recursion; tests too
2929
- [ ] `template<typename T>` + `static_assert(std::is_floating_point_v<T>)`; `float` only
3030
- [ ] `TEST_F` on `float` — no `TYPED_TEST`; `StrictMock` only; never plain `TEST()`
31-
- [ ] `#pragma GCC optimize` + `OPTIMIZE_FOR_SPEED` on hot paths
31+
- [ ] scoped `#pragma GCC push_options`/`optimize`/`pop_options` + `OPTIMIZE_FOR_SPEED` on hot paths
3232
- [ ] `doc/` update planned
3333

3434
**Terse**: no preamble/postamble, no plan restatement; don't re-read files; batch reads.

‎.github/agents/reviewer.agent.md‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ End with totals + verdict: APPROVE / REQUEST CHANGES.
4141
- [ ] `extern template` guarded by `#ifdef NUMERICAL_TOOLBOX_COVERAGE_BUILD`.
4242

4343
**Embedded optimizations (WARNING)**
44-
- [ ] `#pragma GCC optimize("O3","fast-math")` after `#pragma once` in algorithm headers.
44+
- [ ] `#pragma GCC push_options` + `optimize("O3","fast-math")` after `#pragma once`, matching `pop_options` at end of algorithm headers (no TU leak; none in test `.cpp`).
4545
- [ ] `OPTIMIZE_FOR_SPEED` on `Filter/Compute/Update/Solve/Step`.
4646

4747
**Namespaces (WARNING)**

‎.github/copilot-instructions.md‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ Code-file specifics: `.github/instructions/` (applyTo-scoped). Deployment recipe
66
Essentials (full detail in AGENTS.md):
77
- **No heap** — bounded containers / `std::array` / `std::optional`; no recursion; tests too.
88
- **Float-only** — generic `template<typename T>` + `static_assert(std::is_floating_point_v<T>)`; instantiate/test `float`; no Q15/Q31.
9-
- **Embedded** — `#pragma GCC optimize("O3","fast-math")` + `OPTIMIZE_FOR_SPEED` on hot paths.
9+
- **Embedded** — scoped `#pragma GCC push_options` / `optimize("O3","fast-math")` … `pop_options` (never leak to the TU) + `OPTIMIZE_FOR_SPEED` on hot paths.
1010
- **No comments** (except license/NOLINT). Allman braces, brace-init, PascalCase/camelCase.
1111
- **Tests** — `TEST_F` on `float`, `StrictMock` only, never plain `TEST()`, no redundant cases.
1212
- **No exceptions** — `std::optional`/status enums; interfaces `virtual ~I() = default`.

‎.github/instructions/numerical-cpp.instructions.md‎

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,16 +41,25 @@ To replace a function with a platform-specific implementation, define the corres
4141

4242
## Embedded Optimizations
4343

44-
Every algorithm header MUST include:
44+
Every algorithm header MUST bracket its body with a scoped pragma, so the options never leak into the including translation unit:
4545

4646
```cpp
4747
#pragma once
4848

49-
#if defined(__GNUC__) || defined(__clang__)
49+
#if defined(__GNUC__) && !defined(__clang__)
50+
#pragma GCC push_options
5051
#pragma GCC optimize("O3", "fast-math")
5152
#endif
53+
54+
// ... includes and header body ...
55+
56+
#if defined(__GNUC__) && !defined(__clang__)
57+
#pragma GCC pop_options
58+
#endif
5259
```
5360

61+
The `pop_options` block is the last thing in the header. Never use the pragma in test `.cpp` files.
62+
5463
Apply `OPTIMIZE_FOR_SPEED` (from `numerical/math/CompilerOptimizations.hpp`) on hot-path methods: `Compute()`, `Filter()`, `Calculate()`, `Solve()`, `Update()`, `Step()`.
5564

5665
## Naming

‎AGENTS.md‎

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,12 +26,24 @@ resource-constrained embedded systems. Real-time, deterministic, no heap.
2626

2727
```cpp
2828
#pragma once
29-
#if defined(__GNUC__) || defined(__clang__)
29+
#if defined(__GNUC__) && !defined(__clang__)
30+
#pragma GCC push_options
3031
#pragma GCC optimize("O3", "fast-math")
3132
#endif
3233
#include "numerical/math/CompilerOptimizations.hpp"
34+
35+
// ... header body ...
36+
37+
#if defined(__GNUC__) && !defined(__clang__)
38+
#pragma GCC pop_options
39+
#endif
3340
```
3441

42+
The `pop_options` block is the **last thing in the header**: the pragma must never leak into the
43+
including translation unit (it would silently apply fast-math, e.g. folded NaN checks and
44+
reassociation, to unrelated code). Use `math::IsFinite` for finiteness checks. Test `.cpp` files
45+
never use the pragma.
46+
3547
`OPTIMIZE_FOR_SPEED` on hot paths (`Filter/Compute/Update/Solve/Step`). Pure interfaces exempt.
3648

3749
## Style

‎CLAUDE.md‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ Code-file specifics: `.github/instructions/`. Deployment recipe: `roadmap/DEPLOY
66
Essentials (full detail in AGENTS.md):
77
- **No heap** — bounded containers / `std::array` / `std::optional`; no recursion; tests too.
88
- **Float-only** — generic `template<typename T>` + `static_assert(std::is_floating_point_v<T>)`; instantiate/test `float`; no Q15/Q31.
9-
- **Embedded** — `#pragma GCC optimize("O3","fast-math")` + `OPTIMIZE_FOR_SPEED` on hot paths.
9+
- **Embedded** — scoped `#pragma GCC push_options` / `optimize("O3","fast-math")` … `pop_options` (never leak to the TU) + `OPTIMIZE_FOR_SPEED` on hot paths.
1010
- **No comments** (except license/NOLINT). Allman braces, brace-init, PascalCase/camelCase.
1111
- **Tests** — `TEST_F` on `float`, `StrictMock` only, never plain `TEST()`, no redundant cases.
1212
- **No exceptions** — `std::optional`/status enums; interfaces `virtual ~I() = default`.

0 commit comments

Comments
 (0)