Repository navigation
Preserve NaN sign+payload and tiny-float sign in cbor_encode_half - #412
Merged
Merged
Conversation
cbor_encode_half previously encoded all NaN values as 0x7E00, losing the sign bit and up to 10 payload bits. Negative tiny floats (too small for half precision) were also rounded to +0 instead of -0. - cbor_encode_half: map the top 10 bits of the single-precision mantissa to the half-precision mantissa, preserving both the quiet/signaling bit and the payload. Fall back to a quiet NaN only when the payload fits entirely in the bottom 13 bits (not representable in half precision). Preserve the sign bit in the tiny-float-to-zero rounding path. - _cbor_decode_half: reconstruct the single-precision float bit pattern from the half-precision NaN bits, enabling round-trip fidelity. Fixes #215 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
MIPS legacy uses bit 22 = 0 for quiet NaN (opposite of IEEE 754-2008),
so the C NAN constant has a different bit pattern there. Tests that
asserted cbor_encode_half(NAN) == {0xF9, 0x7E, 0x00} were relying on
the old behavior of normalizing all NaN values to 0x7E00.
Replace specific-byte assertions on NAN, -NAN, and nanf("2") with
structural checks (valid CBOR half marker, exp=0x1F, non-zero mantissa)
plus the existing encode/decode round-trip. Keep a deterministic
specific-byte assertion for an explicit bit pattern (0x7FC02000)
constructed via memcpy, which is independent of the platform's NAN.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## master #412 +/- ##
=======================================
Coverage 99.59% 99.59%
=======================================
Files 20 20
Lines 1737 1744 +7
=======================================
+ Hits 1730 1737 +7
Misses 7 7 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
This was referenced Sep 16, 2026
PJK
added a commit
that referenced
this pull request
Sep 16, 2026
* Preserve NaN sign and payload in single and double encoders cbor_encode_single and cbor_encode_double replaced every NaN with the canonical quiet NaN, discarding the sign and payload, while cbor_encode_half has preserved them since #412. Copy the bit pattern verbatim at all widths so that decode/encode round trips of NaNs are lossless. The comment claiming there is no standard way to extract the bits was contradicted by the union bit-cast on the next line. The canonicalization dated from #329, where exact-byte tests on the C NAN constant failed on MIPS legacy-NaN hosts. Follow #412 instead: test NAN and friends structurally (sign, exponent, non-zero mantissa, round trip) and test exact bytes only with memcpy-built bit patterns. Reconcile the test vector list: the four quiet NaNs with payloads now pass outright; the eight signaling NaNs join the half-float ones as platform-dependent since x87 quiets them. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * Link PR number in changelog Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * Simplify NaN round-trip helpers Take the expected sign bit as a parameter and let the decoder plus isnan establish that the buffer holds a NaN, instead of branching on the sign and checking exponent and mantissa bits by hand. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
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
cbor_encode_half: all NaN values were encoded as0x7E00(positive quiet NaN, zero payload), discarding the sign bit and up to 10 payload bits. Now the top 10 bits of the single-precision mantissa are mapped to the 10-bit half-precision mantissa, preserving both the quiet/signaling distinction and the payload. If the payload fits entirely in the bottom 13 bits (below half-precision resolution), the encoder falls back to a quiet NaN with the sign preserved.cbor_encode_half: very small normal floats withlogical_exp < -24were rounded to+0regardless of sign. Negative values now correctly round to−0._cbor_decode_half: NaN values were decoded using the CNANconstant, losing the sign and payload. Now the half-precision NaN bits are used to reconstruct the single-precision float bit pattern directly, enabling true encode/decode round-trip fidelity.Fixes #215.
Test plan
test_half/test_half_special/test_half_infinitystill passcbor_encode_half(-1e-25f)→{0xF9, 0x80, 0x00}(negative zero)cbor_encode_half(-NAN)→{0xF9, 0xFE, 0x00}(negative quiet NaN)0x7FC02000) →{0xF9, 0x7E, 0x01}, with codec identity verifiedctestsuite: 28/28 pass🤖 Generated with Claude Code