Skip to content

perf!: stop setting optimization options per header and per function - #348

Merged
gabrielfrasantos merged 2 commits into
mainfrom
ccr-90fcd432-u9pqe7
Oct 4, 2026
Merged

gabrielfrasantos merged 2 commits into
mainfrom
ccr-90fcd432-u9pqe7

Conversation

@gabrielfrasantos

Copy link
Copy Markdown
Contributor

Summary

Two commits:

  1. fix(test) — numerical.math_test locks up QEMU at TestGradientCheck.expect_gradient_near_reports_wrong_component, on main as well.
  2. perf! — the toolbox stops setting optimization options per header and per function; OPTIMIZE_FOR_SPEED only forces inlining.

QEMU test lockup

The QEMU test executables link newlib-nano, whose printf has no float conversions unless _printf_float is linked. std::ostream << float formats through vsnprintf("%.*g"), which then returned a bogus length — the address of its output buffer, 0x203ffce0. libstdc++'s num_put::_M_insert_float allocas that many bytes, the stack pointer wraps below zero, the next push bus-faults, the fault entry cannot stack, and QEMU stops with Lockup: can't escalate 3 to HardFault.

That test is the first whose failure message prints a float; any failing float expectation on QEMU would have crashed the same way instead of reporting. numerical_link_qemu_runtime now links _printf_float into every QEMU test target.

Optimization options

GCC does not inline a callee whose optimization options differ from its caller's. Every header bracketed its body with #pragma GCC optimize("O3", "fast-math"), and OPTIMIZE_FOR_SPEED added optimize("-O3") and optimize("-ffast-math"), so each toolbox function had options of its own: it could not be inlined into the consumer's code, and it could not inline the consumer's or the standard library's small helpers (element access, accessors, unit wrappers) either.

  • OPTIMIZE_FOR_SPEED expands to __attribute__((always_inline, hot)) inline when NumericalToolbox_ENABLE_OPTIMIZATIONS is defined, for GCC and Clang alike, and to nothing otherwise.
  • The push_options/optimize/pop_options bracket is gone from all 104 headers.
  • AGENTS.md, CLAUDE.md, the Copilot instructions, the agents, the roadmap and doc/performance-optimization/README.md forbid optimize pragmas and attributes, and leave the optimization level and floating-point model to the consumer, for whole translation units — for embedded targets -O2 or -O3 with -ffast-math -fno-finite-math-only. math::IsFinite stays the way to test finiteness, since a consumer may still build with -ffinite-math-only.

Breaking change: toolbox code no longer builds at O3 with fast-math on its own. Consumers that want those optimizations pass them for whole translation units.

Effect in e-foc (embedded-pro/e-foc#333)

20 kHz FOC inner loop measured in SIL: a QEMU plugin counts the instructions between the DWT_CYCCNT reads that bracket the FOC callback and weights them with Cortex-M4 timings; 19 controller-matrix scenarios, ~118k iterations per build. Weighted cycles per iteration:

e-foc build Mean p99 Calls to ≤ 12-byte helpers on the gated paths
per-function pragmas, this repo's main 1282 1665 256
one set of options, this repo's main 1110 1486 233
one set of options, this PR 949 1301 11

Validation (local)

  • host-single-Debug: build clean, ctest 14/14.
  • qemu-cortex-m4 and qemu-cortex-m7: ctest 15/15 each. numerical.math_test runs 552/552 on M4; before the fix it aborted at the gradient-check test, on main too.
  • e-foc built against this branch: host ctest 25/25, EK-TM4C1294XL, EK-TM4C123GXL, STM32F407G-DISC1, NUCLEO-H563ZI and the QEMU firmware build, SIL 128/128, cycle budgets within their limits.

a13f42d stands on its own if you would rather merge the test fix separately.

🤖 Generated with Claude Code

https://claude.ai/code/session_01HKhRVwu8yvxdKJgNo17oNc


Generated by Claude Code

claude added 2 commits October 4, 2026 16:34
The QEMU test executables link newlib-nano, whose printf has no float
conversions unless _printf_float is linked. std::ostream << float formats
through vsnprintf("%.*g"), which then returned a bogus length (the address
of its output buffer); libstdc++'s num_put allocas that many bytes, the
stack pointer wraps below zero, the next push bus-faults, the fault entry
cannot stack, and QEMU stops with "Lockup: can't escalate 3 to HardFault".

TestGradientCheck.expect_gradient_near_reports_wrong_component is the first
test whose failure message prints a float, so numerical.math_test aborted
there; any failing float expectation would have done the same instead of
reporting. numerical_link_qemu_runtime now links _printf_float into every
QEMU test target.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HKhRVwu8yvxdKJgNo17oNc
GCC does not inline a callee whose optimization options differ from its
caller's. Every header bracketed its body with
#pragma GCC optimize("O3", "fast-math"), and OPTIMIZE_FOR_SPEED added
optimize("-O3") and optimize("-ffast-math"), so each toolbox function had
options of its own: it could not be inlined into the consumer's code, and
it could not inline the consumer's or the standard library's small helpers
either. In e-foc's FOC firmware, together with e-foc's own scoped pragmas,
that left 256 out-of-line calls to helpers of 12 bytes or less on the three
cycle-gated paths. With one set of options for the whole build there are
11, and the 20 kHz inner loop costs 26 % fewer cycles.

- OPTIMIZE_FOR_SPEED expands to always_inline, hot and inline when
  NumericalToolbox_ENABLE_OPTIMIZATIONS is defined, for GCC and Clang
  alike, and to nothing otherwise.
- Drop the push_options/optimize/pop_options bracket from all 104 headers.
- AGENTS.md, CLAUDE.md, the Copilot instructions, the agents, the roadmap
  and the performance guide forbid optimize pragmas and attributes, and
  leave the optimization level and floating-point model to the consumer,
  for whole translation units: -O2 or -O3 with
  -ffast-math -fno-finite-math-only for embedded targets.

BREAKING CHANGE: toolbox code no longer builds at O3 with fast-math on its
own. Consumers that want those optimizations pass them for whole
translation units, e.g. -ffast-math -fno-finite-math-only.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HKhRVwu8yvxdKJgNo17oNc
@github-actions

github-actions Bot commented Oct 4, 2026

Copy link
Copy Markdown
Contributor

✅⚠️MegaLinter analysis: Success with warnings

Descriptor Linter Files Fixed Errors Max errors Warnings Elapsed time
✅ ACTION actionlint 7 0 0 0.41s
✅ CPP clang-format 430 11 0 0 2.56s
✅ CPP cppcheck 430 0 0 6.02s
✅ DOCKERFILE hadolint 1 0 0 0.33s
✅ JSON jsonlint 8 0 0 0.07s
✅ JSON prettier 8 8 0 0 0.37s
⚠️ MARKDOWN markdownlint 132 3 178 0 2.1s
✅ MARKDOWN markdown-table-formatter 132 24 0 0 0.24s
⚠️ SPELL lychee 241 26 0 25.94s
✅ YAML prettier 12 3 0 0 0.42s
✅ YAML yamllint 12 0 0 0.44s

Detailed Issues

⚠️ SPELL / lychee - 26 errors
📝 Summary
---------------------
🔍 Total..........567
🔗 Unique.........436
✅ Successful.....529
⏳ Timeouts.........0
🔀 Redirected.....148
👻 Excluded........11
❓ Unknown..........0
🚫 Errors..........26
⛔ Unsupported.....26

Errors in .github/workflows/static-analysis.yml
[403] https://binaries.sonarsource.com/Distribution/sonar-scanner-cli/sonar-scanner-cli-$ (at 37:21) | Rejected status code: 403 Forbidden

Errors in CHANGELOG.md
[404] https://github.com/embedded-pro/embedded-numerical-toolbox/issues/1 (at 206:31) | Rejected status code: 404 Not Found
[404] https://github.com/embedded-pro/embedded-numerical-toolbox/issues/12 (at 221:8) | Rejected status code: 404 Not Found
[404] https://github.com/embedded-pro/embedded-numerical-toolbox/issues/13 (at 220:7) | Rejected status code: 404 Not Found
[404] https://github.com/embedded-pro/embedded-numerical-toolbox/issues/15 (at 215:18) | Rejected status code: 404 Not Found
[404] https://github.com/embedded-pro/embedded-numerical-toolbox/issues/18 (at 205:62) | Rejected status code: 404 Not Found
[404] https://github.com/embedded-pro/embedded-numerical-toolbox/issues/2 (at 213:34) | Rejected status code: 404 Not Found
[404] https://github.com/embedded-pro/embedded-numerical-toolbox/issues/24 (at 210:19) | Rejected status code: 404 Not Found
[404] https://github.com/embedded-pro/embedded-numerical-toolbox/issues/26 (at 211:30) | Rejected status code: 404 Not Found
[404] https://github.com/embedded-pro/embedded-numerical-toolbox/issues/27 (at 208:23) | Rejected status code: 404 Not Found
[404] https://github.com/embedded-pro/embedded-numerical-toolbox/issues/3 (at 204:35) | Rejected status code: 404 Not Found
[404] https://github.com/embedded-pro/embedded-numerical-toolbox/issues/4 (at 214:34) | Rejected status code: 404 Not Found
[404] https://github.com/embedded-pro/embedded-numerical-toolbox/issues/6 (at 212:53) | Rejected status code: 404 Not Found
[404] https://github.com/embedded-pro/embedded-numerical-toolbox/issues/7 (at 209:32) | Rejected status code: 404 Not Found
[404] https://github.com/embedded-pro/embedded-numerical-toolbox/issues/9 (at 207:15) | Rejected status code: 404 Not Found

Errors in doc/filters/active/AhrsMadgwickMahony.md
[ERROR] file://doc/filters/ComplementaryFilter.md (at 131:3) | File not found. Check if file exists and path is correct

Errors in doc/filters/active/ExtendedKalmanFilter.md
[ERROR] file://doc/dynamics/EulerLagrange.md (at 130:3) | File not found. Check if file exists and path is correct

Errors in doc/filters/active/KalmanFilter.md
[ERROR] file://doc/filters/controllers/Lqr.md (at 114:77) | File not found. Check if file exists and path is correct
[ERROR] file://doc/filters/controllers/Lqr.md (at 133:3) | File not found. Check if file exists and path is correct
[ERROR] file://doc/filters/controllers/Pid.md (at 135:3) | File not found. Check if file exists and path is correct
[ERROR] file://doc/filters/solvers/DiscreteAlgebraicRiccatiEquation.md (at 134:3) | File not found. Check if file exists and path is correct

Errors in doc/performance-optimization/README.md
[403] https://developer.arm.com/documentation/100166/latest/ (at 472:3) | Rejected status code: 403 Forbidden
[403] https://developer.arm.com/documentation/dui0473/latest (at 474:3) | Rejected status code: 403 Forbidden

Errors in README.md
[ERROR] file:///releases/latest (at 38:14) | File not found. Check if file exists and path is correct
[404] https://embedded-pro.github.io/embedded-dsp-control/ (at 37:1) | Rejected status code: 404 Not Found

Errors in roadmap/README.md
[ERROR] file://roadmap/filters/passive/ExponentialMovingAverage/implementation.md (at 24:1) | File not found. Check if file exists and path is correct

Hint: Followed 148 redirects. You might want to consider replacing redirecting URLs with the resolved URLs. Use verbose mode (`-v`/`-vv`) to see redirection details.
Hint: You can configure accepted/rejected response codes with `-a` or `--accept`
⚠️ MARKDOWN / markdownlint - 178 errors
rithm.md:5:401 error MD013/line-length Line length [Expected: 400; Actual: 492]
doc/analysis/GoertzelAlgorithm.md:107:401 error MD013/line-length Line length [Expected: 400; Actual: 451]
doc/analysis/HilbertTransform.md:31:34 error MD056/table-column-count Table column count [Expected: 2; Actual: 4; Too many cells, extra data will be missing]
doc/analysis/PowerDensitySpectrum.md:5:401 error MD013/line-length Line length [Expected: 400; Actual: 509]
doc/analysis/PowerDensitySpectrum.md:104:20 error MD056/table-column-count Table column count [Expected: 2; Actual: 6; Too many cells, extra data will be missing]
doc/analysis/PowerDensitySpectrum.md:104:17 error MD060/table-column-style Table column style [Table pipe does not align with header for style "aligned"]
doc/analysis/PowerDensitySpectrum.md:104:20 error MD060/table-column-style Table column style [Table pipe does not align with header for style "aligned"]
doc/analysis/PowerDensitySpectrum.md:104:32 error MD060/table-column-style Table column style [Table pipe does not align with header for style "aligned"]
doc/analysis/PowerDensitySpectrum.md:104:38 error MD060/table-column-style Table column style [Table pipe does not align with header for style "aligned"]
doc/analysis/PowerDensitySpectrum.md:104:45 error MD060/table-column-style Table column style [Table pipe does not align with header for style "aligned"]
doc/analysis/PowerDensitySpectrum.md:104:135 error MD060/table-column-style Table column style [Table pipe does not align with header for style "aligned"]
doc/analysis/SignalDetectors.md:5:401 error MD013/line-length Line length [Expected: 400; Actual: 481]
doc/control_analysis/FrequencyResponse.md:5:401 error MD013/line-length Line length [Expected: 400; Actual: 469]
doc/control_analysis/README.md:11:68 error MD060/table-column-style Table column style [Table pipe does not align with header for style "aligned"]
doc/control_analysis/README.md:11:147 error MD060/table-column-style Table column style [Table pipe does not align with header for style "aligned"]
doc/control_analysis/README.md:12:53 error MD060/table-column-style Table column style [Table pipe does not align with header for style "aligned"]
doc/control_analysis/README.md:12:172 error MD060/table-column-style Table column style [Table pipe does not align with header for style "aligned"]
doc/control_analysis/README.md:13:68 error MD060/table-column-style Table column style [Table pipe does not align with header for style "aligned"]
doc/control_analysis/README.md:13:151 error MD060/table-column-style Table column style [Table pipe does not align with header for style "aligned"]
doc/control_analysis/RootLocus.md:69 error MD040/fenced-code-language Fenced code blocks should have a language specified [Context: "```"]
doc/control_analysis/TransferFunctionStateSpace.md:5:401 error MD013/line-length Line length [Expected: 400; Actual: 589]
doc/controllers/Feedforward2Dof.md:5:401 error MD013/line-length Line length [Expected: 400; Actual: 627]
doc/controllers/GainScheduledController.md:7:401 error MD013/line-length Line length [Expected: 400; Actual: 454]
doc/controllers/LeadLagCompensator.md:5:401 error MD013/line-length Line length [Expected: 400; Actual: 639]
doc/controllers/Lqg.md:7:401 error MD013/line-length Line length [Expected: 400; Actual: 428]
doc/controllers/SaturationRateLimiter.md:5:401 error MD013/line-length Line length [Expected: 400; Actual: 451]
doc/controllers/SaturationRateLimiter.md:7:401 error MD013/line-length Line length [Expected: 400; Actual: 477]
doc/estimators/ExpectationMaximization.md:104:103 error MD060/table-column-style Table column style [Table pipe does not align with header for style "aligned"]
doc/estimators/LmsAdaptiveFilter.md:5:401 error MD013/line-length Line length [Expected: 400; Actual: 547]
doc/estimators/README.md:11:122 error MD056/table-column-count Table column count [Expected: 2; Actual: 3; Too many cells, extra data will be missing]
doc/estimators/README.md:11:122 error MD060/table-column-style Table column style [Table pipe does not align with header for style "aligned"]
doc/filters/active/AhrsMadgwickMahony.md:5:401 error MD013/line-length Line length [Expected: 400; Actual: 538]
doc/filters/active/AhrsMadgwickMahony.md:7:401 error MD013/line-length Line length [Expected: 400; Actual: 554]
doc/filters/active/AlphaBetaFilter.md:5:401 error MD013/line-length Line length [Expected: 400; Actual: 419]
doc/filters/active/AlphaBetaFilter.md:7:401 error MD013/line-length Line length [Expected: 400; Actual: 451]
doc/filters/active/KalmanSmoother.md:5:401 error MD013/line-length Line length [Expected: 400; Actual: 421]
doc/filters/active/KalmanSmoother.md:111:28 error MD060/table-column-style Table column style [Table pipe does not align with header for style "aligned"]
doc/filters/active/KalmanSmoother.md:111:61 error MD060/table-column-style Table column style [Table pipe does not align with header for style "aligned"]
doc/filters/active/KalmanSmoother.md:111:110 error MD060/table-column-style Table column style [Table pipe does not align with header for style "aligned"]
doc/filters/active/KalmanSmoother.md:122:19 error MD060/table-column-style Table column style [Table pipe does not align with header for style "aligned"]
doc/filters/active/KalmanSmoother.md:122:27 error MD060/table-column-style Table column style [Table pipe does not align with header for style "aligned"]
doc/filters/active/KalmanSmoother.md:122:67 error MD060/table-column-style Table column style [Table pipe does not align with header for style "aligned"]
doc/filters/active/KalmanSmoother.md:123:19 error MD060/table-column-style Table column style [Table pipe does not align with header for style "aligned"]
doc/filters/active/KalmanSmoother.md:123:27 error MD060/table-column-style Table column style [Table pipe does not align with header for style "aligned"]
doc/filters/active/KalmanSmoother.md:123:67 error MD060/table-column-style Table column style [Table pipe does not align with header for style "aligned"]
doc/filters/active/KalmanSmoother.md:124:19 error MD060/table-column-style Table column style [Table pipe does not align with header for style "aligned"]
doc/filters/active/KalmanSmoother.md:124:27 error MD060/table-column-style Table column style [Table pipe does not align with header for style "aligned"]
doc/filters/active/KalmanSmoother.md:124:67 error MD060/table-column-style Table column style [Table pipe does not align with header for style "aligned"]
doc/filters/active/KalmanSmoother.md:125:19 error MD060/table-column-style Table column style [Table pipe does not align with header for style "aligned"]
doc/filters/active/KalmanSmoother.md:125:27 error MD060/table-column-style Table column style [Table pipe does not align with header for style "aligned"]
doc/filters/active/KalmanSmoother.md:125:67 error MD060/table-column-style Table column style [Table pipe does not align with header for style "aligned"]
doc/filters/active/UnscentedKalmanFilter.md:11:401 error MD013/line-length Line length [Expected: 400; Actual: 468]
doc/filters/active/UnscentedKalmanFilter.md:149:65 error MD060/table-column-style Table column style [Table pipe does not align with header for style "aligned"]
doc/filters/active/UnscentedKalmanFilter.md:149:153 error MD060/table-column-style Table column style [Table pipe does not align with header for style "aligned"]
doc/filters/passive/MedianFilter.md:69:25 error MD060/table-column-style Table column style [Table pipe does not align with header for style "aligned"]
doc/filters/passive/MedianFilter.md:69:43 error MD060/table-column-style Table column style [Table pipe does not align with header for style "aligned"]
doc/filters/passive/MedianFilter.md:70:51 error MD060/table-column-style Table column style [Table pipe does not align with header for style "aligned"]
doc/filters/passive/MedianFilter.md:70:96 error MD060/table-column-style Table column style [Table pipe does not align with header for style "aligned"]
doc/filters/README.md:13:74 error MD060/table-column-style Table column style [Table pipe does not align with header for style "aligned"]
doc/filters/README.md:13:179 error MD060/table-column-style Table column style [Table pipe does not align with header for style "aligned"]
doc/filters/README.md:14:74 error MD060/table-column-style Table column style [Table pipe does not align with header for style "aligned"]
doc/filters/README.md:14:179 error MD060/table-column-style Table column style [Table pipe does not align with header for style "aligned"]
doc/filters/README.md:15:74 error MD060/table-column-style Table column style [Table pipe does not align with header for style "aligned"]
doc/filters/README.md:15:179 error MD060/table-column-style Table column style [Table pipe does not align with header for style "aligned"]
doc/filters/README.md:16:74 error MD060/table-column-style Table column style [Table pipe does not align with header for style "aligned"]
doc/filters/README.md:16:179 error MD060/table-column-style Table column style [Table pipe does not align with header for style "aligned"]
doc/filters/README.md:17:74 error MD060/table-column-style Table column style [Table pipe does not align with header for style "aligned"]
doc/filters/README.md:17:179 error MD060/table-column-style Table column style [Table pipe does not align with header for style "aligned"]
doc/math/GivensRotation.md:5:401 error MD013/line-length Line length [Expected: 400; Actual: 429]
doc/math/HouseholderTransform.md:5:401 error MD013/line-length Line length [Expected: 400; Actual: 455]
doc/math/MatrixExponential.md:5:401 error MD013/line-length Line length [Expected: 400; Actual: 555]
doc/math/MatrixNorms.md:5:401 error MD013/line-length Line length [Expected: 400; Actual: 452]
doc/math/MatrixNorms.md:42:67 error MD060/table-column-style Table column style [Table pipe does not align with header for style "aligned"]
doc/math/MatrixNorms.md:43:67 error MD060/table-column-style Table column style [Table pipe does not align with header for style "aligned"]
doc/math/MatrixNorms.md:44:67 error MD060/table-column-style Table column style [Table pipe does not align with header for style "aligned"]
doc/math/MatrixNorms.md:45:67 error MD060/table-column-style Table column style [Table pipe does not align with header for style "aligned"]
doc/math/MatrixNorms.md:46:67 error MD060/table-column-style Table column style [Table pipe does not align with header for style "aligned"]
doc/math/README.md:9:55 error MD060/table-column-style Table column style [Table pipe does not align with header for style "aligned"]
doc/math/README.md:9:151 error MD060/table-column-style Table column style [Table pipe does not align with header for style "aligned"]
doc/math/README.md:10:55 error MD060/table-column-style Table column style [Table pipe does not align with header for style "aligned"]
doc/math/README.md:10:151 error MD060/table-column-style Table column style [Table pipe does not align with header for style "aligned"]
doc/math/README.md:11:55 error MD060/table-column-style Table column style [Table pipe does not align with header for style "aligned"]
doc/math/README.md:11:151 error MD060/table-column-style Table column style [Table pipe does not align with header for style "aligned"]
doc/math/README.md:12:55 error MD060/table-column-style Table column style [Table pipe does not align with header for style "aligned"]
doc/math/README.md:12:151 error MD060/table-column-style Table column style [Table pipe does not align with header for style "aligned"]
doc/math/README.md:13:55 error MD060/table-column-style Table column style [Table pipe does not align with header for style "aligned"]
doc/math/README.md:13:151 error MD060/table-column-style Table column style [Table pipe does not align with header for style "aligned"]
doc/math/README.md:14:55 error MD060/table-column-style Table column style [Table pipe does not align with header for style "aligned"]
doc/math/README.md:14:159 error MD060/table-column-style Table column style [Table pipe does not align with header for style "aligned"]
doc/math/README.md:15:55 error MD060/table-column-style Table column style [Table pipe does not align with header for style "aligned"]
doc/math/README.md:15:153 error MD060/table-column-style Table column style [Table pipe does not align with header for style "aligned"]
doc/math/README.md:16:55 error MD060/table-column-style Table column style [Table pipe does not align with header for style "aligned"]
doc/math/README.md:16:152 error MD060/table-column-style Table column style [Table pipe does not align with header for style "aligned"]
doc/math/README.md:17:55 error MD060/table-column-style Table column style [Table pipe does not align with header for style "aligned"]
doc/math/README.md:17:172 error MD060/table-column-style Table column style [Table pipe does not align with header for style "aligned"]
doc/math/README.md:18:55 error MD060/table-column-style Table column style [Table pipe does not align with header for style "aligned"]
doc/math/README.md:18:171 error MD060/table-column-style Table column style [Table pipe does not align with header for style "aligned"]
doc/math/README.md:19:55 error MD060/table-column-style Table column style [Table pipe does not align with header for style "aligned"]
doc/math/README.md:19:174 error MD060/table-column-style Table column style [Table pipe does not align with header for style "aligned"]
doc/math/StepResponseMetrics.md:5:401 error MD013/line-length Line length [Expected: 400; Actual: 514]
doc/math/StepResponseMetrics.md:61 error MD040/fenced-code-language Fenced code blocks should have a language specified [Context: "```"]
doc/nonlinear_control/BacksteppingControl.md:5:401 error MD013/line-length Line length [Expected: 400; Actual: 594]
doc/nonlinear_control/FeedbackLinearization.md:5:401 error MD013/line-length Line length [Expected: 400; Actual: 533]
doc/nonlinear_control/FeedbackLinearization.md:15:401 error MD013/line-length Line length [Expected: 400; Actual: 491]
doc/nonlinear_control/ModelReferenceAdaptiveControl.md:5:401 error MD013/line-length Line length [Expected: 400; Actual: 587]
doc/nonlinear_control/README.md:9:80 error MD060/table-column-style Table column style [Table pipe does not align with header for style "aligned"]
doc/nonlinear_control/README.md:9:258 error MD060/table-column-style Table column style [Table pipe does not align with header for style "aligned"]
doc/nonlinear_control/README.md:10:80 error MD060/table-column-style Table column style [Table pipe does not align with header for style "aligned"]
doc/nonlinear_control/README.md:10:258 error MD060/table-column-style Table column style [Table pipe does not align with header for style "aligned"]
doc/nonlinear_control/README.md:11:80 error MD060/table-column-style Table column style [Table pipe does not align with header for style "aligned"]
doc/nonlinear_control/README.md:11:270 error MD060/table-column-style Table column style [Table pipe does not align with header for style "aligned"]
doc/regularization/Regularization.md:100:32 error MD060/table-column-style Table column style [Table pipe does not align with header for style "aligned"]
doc/regularization/Regularization.md:100:135 error MD060/table-column-style Table column style [Table pipe does not align with header for style "aligned"]
doc/robust_control/ActiveDisturbanceRejection.md:5:401 error MD013/line-length Line length [Expected: 400; Actual: 699]
doc/robust_control/ActiveDisturbanceRejection.md:85:401 error MD013/line-length Line length [Expected: 400; Actual: 575]
doc/robust_control/ActiveDisturbanceRejection.md:93:401 error MD013/line-length Line length [Expected: 400; Actual: 622]
doc/robust_control/DisturbanceObserver.md:7:401 error MD013/line-length Line length [Expected: 400; Actual: 476]
doc/robust_control/README.md:12:259 error MD060/table-column-style Table column style [Table pipe does not align with header for style "aligned"]
doc/robust_control/SlidingModeControl.md:5:401 error MD013/line-length Line length [Expected: 400; Actual: 644]
doc/solvers/ConditionNumber.md:5:401 error MD013/line-length Line length [Expected: 400; Actual: 461]
doc/solvers/ConditionNumber.md:51:401 error MD013/line-length Line length [Expected: 400; Actual: 425]
doc/solvers/JacobiEigenSolver.md:5:401 error MD013/line-length Line length [Expected: 400; Actual: 443]
doc/solvers/JacobiEigenSolver.md:7:401 error MD013/line-length Line length [Expected: 400; Actual: 609]
doc/solvers/JacobiEigenSolver.md:45:401 error MD013/line-length Line length [Expected: 400; Actual: 427]
doc/solvers/README.md:16:163 error MD060/table-column-style Table column style [Table pipe does not align with header for style "aligned"]
doc/solvers/README.md:17:163 error MD060/table-column-style Table column style [Table pipe does not align with header for style "aligned"]
doc/solvers/README.md:18:167 error MD060/table-column-style Table column style [Table pipe does not align with header for style "aligned"]
doc/solvers/README.md:19:184 error MD060/table-column-style Table column style [Table pipe does not align with header for style "aligned"]
doc/solvers/README.md:20:184 error MD060/table-column-style Table column style [Table pipe does not align with header for style "aligned"]
doc/solvers/RungeKuttaIntegrators.md:9:401 error MD013/line-length Line length [Expected: 400; Actual: 509]
doc/solvers/SpectralRadius.md:5:401 error MD013/line-length Line length [Expected: 400; Actual: 665]
doc/windowing/window.md:5:401 error MD013/line-length Line length [Expected: 400; Actual: 415]
README.md:1 error MD041/first-line-heading/first-line-h1 First line in a file should be a top-level heading [Context: "[![Quality Gate Status](https:..."]
README.md:9:401 error MD013/line-length Line length [Expected: 400; Actual: 442]
README.md:19:327 error MD060/table-column-style Table column style [Table pipe does not align with header for style "aligned"]
README.md:20:211 error MD060/table-column-style Table column style [Table pipe does not align with header for style "aligned"]
README.md:21:303 error MD060/table-column-style Table column style [Table pipe does not align with header for style "aligned"]
README.md:22:250 error MD060/table-column-style Table column style [Table pipe does not align with header for style "aligned"]
README.md:23:446 error MD060/table-column-style Table column style [Table pipe does not align with header for style "aligned"]
README.md:25:140 error MD060/table-column-style Table column style [Table pipe does not align with header for style "aligned"]
README.md:26:174 error MD060/table-column-style Table column style [Table pipe does not align with header for style "aligned"]
README.md:27:363 error MD060/table-column-style Table column style [Table pipe does not align with header for style "aligned"]
README.md:28:158 error MD060/table-column-style Table column style [Table pipe does not align with header for style "aligned"]
README.md:29:205 error MD060/table-column-style Table column style [Table pipe does not align with header for style "aligned"]
roadmap/math/SE3Transform/implementation.md:7 error MD040/fenced-code-language Fenced code blocks should have a language specified [Context: "```"]
roadmap/math/SE3Transform/implementation.md:21 error MD040/fenced-code-language Fenced code blocks should have a language specified [Context: "```"]
roadmap/math/SE3Transform/implementation.md:35 error MD040/fenced-code-language Fenced code blocks should have a language specified [Context: "```"]
roadmap/math/SE3Transform/tests.md:7 error MD040/fenced-code-language Fenced code blocks should have a language specified [Context: "```"]
roadmap/math/SE3Transform/tests.md:16 error MD040/fenced-code-language Fenced code blocks should have a language specified [Context: "```"]
roadmap/README.md:11 error MD040/fenced-code-language Fenced code blocks should have a language specified [Context: "```"]

(Truncated to last 20000 characters out of 24106)

Notices

⚠️ Your configuration references items that have been removed from MegaLinter and are ignored: REPOSITORY_GITLEAKS, REPOSITORY_KICS. See Removed linters to find their replacements.

See detailed reports in MegaLinter artifacts

Your project could benefit from a custom flavor, which would allow you to run only the linters you need, and thus improve runtime performances. (Skip this info by defining FLAVOR_SUGGESTIONS: false)

  • Documentation: Custom Flavors
  • Command: npx mega-linter-runner@10.1.0 --custom-flavor-setup --custom-flavor-linters ACTION_ACTIONLINT,CPP_CPPCHECK,CPP_CLANG_FORMAT,DOCKERFILE_HADOLINT,JSON_JSONLINT,JSON_PRETTIER,MARKDOWN_MARKDOWNLINT,MARKDOWN_MARKDOWN_TABLE_FORMATTER,SPELL_LYCHEE,YAML_PRETTIER,YAML_YAMLLINT

MegaLinter is provided by OX Security
Show us your support by starring ⭐ the repository

@sonarqubecloud

sonarqubecloud Bot commented Oct 4, 2026

Copy link
Copy Markdown

@gabrielfrasantos
gabrielfrasantos merged commit 31c7ac9 into main Oct 4, 2026
@gabrielfrasantos
gabrielfrasantos deleted the ccr-90fcd432-u9pqe7 branch October 4, 2026 18:05
gabrielfrasantos pushed a commit that referenced this pull request Oct 5, 2026
Every Matrix operator that returns a new matrix value-initialised its
result (data = {}) and then overwrote every element. Without the O3
pragmas #348 removed, a consumer that builds at -O2 keeps those loops
rolled, so the zeroing survives. For a 3x3 result it is a memset call,
and the Arm GNU toolchain's newlib-nano memset stores one byte at a
time.

e-foc runs an RLS update in the control interrupt during mechanical
identification. Its covariance update, (P - g g^T / d) / lambda,
builds four 3x3 temporaries. In e-foc's SIL scenario that times the
control interrupt through a full calibration, the slowest execution
rose from 237 to 377 cycles of the emulated 25 MHz clock
(arm-none-eabi-gcc 15.2.1). The four memset calls were 596 of its 1892
instructions.

- Matrix gains a private constructor that leaves the elements
  uninitialised. operator+, operator-, the matrix and scalar products,
  Transpose, GetBlock and GetColumn build their results with it, since
  each writes every element.
- The default and initializer-list constructors still zero-fill, so a
  default-constructed or partly listed matrix keeps its zeros.
- A test evaluates those operators in constant expressions, so a
  compiler that checks (Clang does, GCC does not) rejects an operator
  that leaves an element unwritten.

The RLS update keeps its matrix expression and now makes no memset
calls. The same scenario peaks at 250 cycles.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HKhRVwu8yvxdKJgNo17oNc
gabrielfrasantos added a commit that referenced this pull request Oct 5, 2026
* perf(math): build matrix results without zero-filling them first

Every Matrix operator that returns a new matrix value-initialised its
result (data = {}) and then overwrote every element. Without the O3
pragmas #348 removed, a consumer that builds at -O2 keeps those loops
rolled, so the zeroing survives. For a 3x3 result it is a memset call,
and the Arm GNU toolchain's newlib-nano memset stores one byte at a
time.

e-foc runs an RLS update in the control interrupt during mechanical
identification. Its covariance update, (P - g g^T / d) / lambda,
builds four 3x3 temporaries. In e-foc's SIL scenario that times the
control interrupt through a full calibration, the slowest execution
rose from 237 to 377 cycles of the emulated 25 MHz clock
(arm-none-eabi-gcc 15.2.1). The four memset calls were 596 of its 1892
instructions.

- Matrix gains a private constructor that leaves the elements
  uninitialised. operator+, operator-, the matrix and scalar products,
  Transpose, GetBlock and GetColumn build their results with it, since
  each writes every element.
- The default and initializer-list constructors still zero-fill, so a
  default-constructed or partly listed matrix keeps its zeros.
- A test evaluates those operators in constant expressions, so a
  compiler that checks (Clang does, GCC does not) rejects an operator
  that leaves an element unwritten.

The RLS update keeps its matrix expression and now makes no memset
calls. The same scenario peaks at 250 cycles.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HKhRVwu8yvxdKJgNo17oNc

* fix(math): build the matrix product's result in a member function

The matrix product is a friend function of its left operand's Matrix
specialisation. It built its result, a Matrix of another shape, with
that shape's private constructor. GCC and Clang allowed it, but MSVC
rejects it (C2248): friendship goes to the Matrix specialisations, not
to their friend functions.

The operator now calls a private member function, Multiply, which
builds the result in place, as Transpose, GetBlock and GetColumn
already do. Members of every Matrix specialisation are friends of the
others, so every compiler accepts it.

A static helper that returned the uninitialised result was not used:
GCC folds such an argument-less constexpr call into a zero-filled
constant, which brings back the memset calls.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HKhRVwu8yvxdKJgNo17oNc

---------

Co-authored-by: Claude <noreply@anthropic.com>
gabrielfrasantos added a commit to embedded-pro/robotics-toolbox-cpp that referenced this pull request Oct 23, 2026
…pstream (#25)

* perf!: stop setting optimization options per header

Mirrors embedded-pro/numerical-toolbox-cpp#348 and bumps the
numerical-toolbox pin to 9b37e08, which carries it.

Every robotics header applied an unscoped #pragma GCC optimize("O3",
"fast-math"). GCC does not inline across differing optimization
options, so toolbox helpers could not be inlined into consumer code,
and the unscoped pragma leaked fast-math into every translation unit
that included a robotics header.

- Drop the pragma from all robotics headers.
- AGENTS.md, CLAUDE.md, the Copilot instructions, the agents, the
  roadmap recipe and every spec's deployment note forbid optimize
  pragmas/attributes and leave the optimization level and
  floating-point model to the consumer, per translation unit.

BREAKING CHANGE: robotics headers no longer force O3 and fast-math.
Consumers that want them pass them for whole translation units, e.g.
-O2/-O3 -ffast-math -fno-finite-math-only.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Mmp77ieEy16GxJL8KsLsVx

* docs(roadmap): factor wide Jacobians directly in M11 and M14

numerical-toolbox's SingularValueDecomposition now accepts Rows < Cols,
so ManipulabilityIndex (M11) and RedundancyResolution (M14) decompose
the task Jacobian itself instead of its transpose and no longer swap
the singular-vector factors by hand. Both need a numerical-toolbox pin
that includes the wide-matrix change.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Mmp77ieEy16GxJL8KsLsVx

* docs(roadmap): take SE(3) from numerical-toolbox (NT53)

The SE(3) spec existed twice: roadmap/kinematics/SE3Transform here and
roadmap/math/SE3Transform in numerical-toolbox-cpp, with opposite
6-vector orderings and the same id (M6). SE(3) is generic, so the
upstream spec is now the only one; it adopts this repo's linear-first
convention, twists (v; ω) and wrenches (f; n), and its PoseError.

- Delete roadmap/kinematics/SE3Transform and the M6 row.
- Specs use math::SE3Transform / math::Vector6 from
  numerical/math/SE3Transform.hpp and depend on NT53.
- ROADMAP.md gains an "Upstream prerequisites" table: generic items are
  referenced as NT<n>, numerical-toolbox's master-list number.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Mmp77ieEy16GxJL8KsLsVx

* docs(roadmap): move generic algorithms to numerical-toolbox (NT54–NT65)

Generic parts of this roadmap are now specified upstream in
numerical-toolbox-cpp; robotics items keep only the robot-specific
part and depend on NT<n>:

- Moved whole: M2 polynomial, M3 trapezoidal and M9 S-curve profiles
  (NT55, NT56, NT60, new upstream motion_profiles module) and M4
  friction compensation (NT57). Their specs and numbers are retired.
- M33 is a thin joint-space wrapper over math::CubicSpline (NT61, with
  the Thomas solve NT59) and now owns JointTrajectoryState.
- M14 binds the task Jacobian to solvers::DampedPseudoInverse (NT62).
- M22 feeds regressor rows to IncrementalQrLeastSquares (NT63).
- M34 adapts ABA to SemiImplicitEuler (NT58) and RungeKutta4.
- M13 and M23 run their damped Newton iterations on
  LevenbergMarquardt (NT64): pose IK keeps its manipulability damping
  as a damping policy, Stewart FK its SE(3) retraction.
- M21 wraps joint angles with WrapToPi (NT54).
- M25 gains DistributeExact on ActiveSetQp (NT65) for the workspace
  boundary, where the improved closed form fails (spatial 8-cable
  fixture: 90 of 4000 boundary-biased feasible wrenches); M27 keeps its
  two-variable stage LPs, which a strictly convex QP cannot express.

ROADMAP.md lists NT53–NT65 with spec links and consumers; M14, M22 and
M33 drop one tier now that the numerics live upstream.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Mmp77ieEy16GxJL8KsLsVx

---------

Co-authored-by: Claude <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants