fix: Kahan summation for numerical stability, plus formatting pass#57
Merged
Merged
Conversation
Direct response to r/C_Programming feedback (Axman6 on numx_stats_mean, EpochVanquisher on numx_integrate_simpson), both verified true against the actual code before fixing, not just taken at face value. Applies Kahan (compensated) summation to every summation loop where n can reach a size where accumulated float32 rounding error is a real concern: numx_stats_mean, numx_vec_dot, numx_vec_norm (L1/L2), numx_integrate_trap, numx_integrate_simpson, and signal.c's convolve, correlate, and fir. numx_stats_variance already used Welford's algorithm and needed no change. Left numx_integrate_gauss (bounded to <=8 terms) and the matrix functions (bounded to <=32 by NUMX_MAX_MAT_ROWS) alone, naive summation error at those sizes is genuinely negligible and Kahan would be complexity without real benefit. Added regression tests (test_stats_mean_kahan_stress, test_vec_dot_kahan_stress) using a genuinely adversarial input: a leading value of 2^24 followed by 255 values of 1.0f. At that magnitude float32's ULP is already 2.0, so naive summation loses every single trailing increment (255 confirmed lost in an independent Python check before writing the fix), while Kahan summation lands within 1 ULP of the true answer. Both new tests pass; 337/337 total, up from 335. Verified: strict -std=c99 -pedantic-errors -Wall -Wextra -Werror on gcc and clang, float32 and float64, across the whole project, not just the touched files. Full suite clean under AddressSanitizer and UndefinedBehaviorSanitizer. Also includes a project-wide clang-format pass across src/, include/, examples/, and validation/c/ (whitespace and layout only). Verified the NTT twiddle-table reformatting is value-preserving by extracting and diffing the numeric literals directly before and after: identical.
Missed in the previous commit's formatting pass. Verified value-preserving the same way: stripped whitespace and macro line-continuation backslashes from both versions and diffed, identical once normalized. This file can't be compiled locally (ESP-IDF headers), so this token-level check stands in for the strict-compile verification done on the files in src/.
This was referenced Jul 11, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Direct response to r/C_Programming (Axman6 flagged
numx_stats_mean, EpochVanquisher flaggednumx_integrate_simpson), both verified true against the real code before fixing.Applies Kahan (compensated) summation to every summation loop where n can reach a size that matters:
numx_stats_mean,numx_vec_dot,numx_vec_norm(L1/L2),numx_integrate_trap,numx_integrate_simpson, and signal.c'sconvolve/correlate/fir. Leftnumx_integrate_gauss(<=8 terms) and the matrix functions (<=32, bounded byNUMX_MAX_MAT_ROWS) alone, negligible benefit there for the added complexity.numx_stats_variancealready used Welford's algorithm, no change needed.Verification
-std=c99 -pedantic-errors -Wall -Wextra -Werroron gcc and clang, float32 and float64, across the whole projectAlso included
A project-wide clang-format pass (whitespace/layout only) across
src/,include/,examples/, andvalidation/c/. Verified value-preserving two ways: diffed extracted numeric literals for the NTT twiddle tables (identical), and a whitespace/backslash-normalized token diff forexamples/esp32_ntt_test/main/main.c(which can't be compiled locally, no ESP-IDF toolchain here), also identical.