libc: carry the rounding out of the leading digit in %f - #65
Merged
Merged
Conversation
float_to_str() rounds by adding half a unit of the last printed digit to the normalised mantissa, but only after the layout (decimal exponent, "0." prefix, digit count) is fixed. When that addition carries out of the leading digit the first digit comes out as 10, which the emit loop clamps to 9, so the carry is lost: with %.2f, 9.9976 prints as "9.00", 99.9976 as "90.00", 0.996 as "0.90" and 0.006 as "0.00". Seen on a PMD board as a phantom 1 degree encoder disagreement: the absolute encoder at 455 counts (9.9976 deg) printed "9.00 deg" next to a servo position of 10.00, and the position seed log printed "90.00 deg (4551 counts)" for 99.998 deg. Round before the layout, and when the mantissa reaches 1.0 divide it by 10 and bump the exponent so the extra leading digit is printed. The clamp stays as a safety net; it no longer triggers. A host model of the algorithm checked against a decimal half-up reference over 200 000 random values at 2, 3 and 6 decimals: 388 mismatches before, none after. On the PMD mock (STM32H725) the same board prints "455 counts 10.00 deg" where it printed "9.00 deg", and the seed at 4552 counts prints "100.02 deg". Co-Authored-By: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01ExwkpjVKyyM5HBhzois9fr
4dc901e made crashlog_stream.buf a runtime value that the platform sets with crashlog_init(), and updated stm32g4 and stm32h7 but not stm32f4_ccm.c, which includes the same source. The F4 boards therefore fail to build (crashlog_init defined but not used, -Werror), and had it built the crash log would have been silently disabled there because the buffer stays NULL. Call crashlog_init() with the CCM address before crashlog_recover(), exactly as stm32h7.c does. Builds stm32f407g-disc1, stm32f405-feather and stm32h7-nucleo144 again. Co-Authored-By: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01ExwkpjVKyyM5HBhzois9fr
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.
float_to_str()rounds by adding half a unit of the last printed digit to thenormalised mantissa, but only after the layout (exponent, "0." prefix, digit
count) is fixed. When that addition carries out of the leading digit the first
digit comes out as 10 and is clamped to 9, so the carry is lost:
%.2f)9.0010.00%.2f)90.00100.00%.2f)0.901.00%.2f)0.000.01Found on a PMD board: the absolute encoder at 455 counts (9.9976 deg) printed
9.00 degnext to a servo position of10.00, which looked like a 1 degreeencoder disagreement, and the position seed log printed
90.00 deg (4551 counts)for 99.998 deg.Fix: do the rounding before the layout, and when the mantissa reaches 1.0
divide it by 10 and bump the decimal exponent so the extra leading digit is
printed. The digit clamp stays as a safety net; it no longer triggers.
Checked against a decimal half-up reference with a host model of the
algorithm over 200 000 random values at 2, 3 and 6 decimals: 388 mismatches
before, none after. Verified on the PMD mock (STM32H725): the same board that printed
455 counts 9.00 degbefore the flash prints455 counts 10.00 degafter it,and the seed log at 4552 counts prints
100.02 deg.Second commit, unrelated but needed for CI to pass: 4dc901e made the
crash-log buffer a runtime value set by
crashlog_init()and updated stm32g4and stm32h7 but not
stm32f4_ccm.c, so the F4 boards failed to build (unusedstatic function under -Werror) and master has been red since. One line calls
crashlog_init((void *)CRASHLOG_ADDR)beforecrashlog_recover(), as h7 does;stm32f407g-disc1, stm32f405-feather and stm32h7-nucleo144 build again.
Co-Authored-By: Claude noreply@anthropic.com
https://claude.ai/code/session_01ExwkpjVKyyM5HBhzois9fr