You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
NaN inputs whose payload lies below the target precision are rounded to Infinity #13
This is bug 2 of 3 identified by comparing floating point number conversion results across a few open-source implementations. It appears that NAN inputs are converting to INF in some cases. Feel free to cancel if this is expected/intended.
Below is the full AI-generated summary:
A NaN input must give a NaN. CPFloat rounds a NaN's bit pattern as if it were a finite value, so when every set payload bit lies below the target precision, the payload is rounded away and the result is the Infinity pattern:
cc -std=c11 -Icpfloat/src t.c -lm && ./a.out at 3583976 prints inf inf inf nan.
It happens under RND_NE, RND_TN and RND_TZ. RND_TP keeps these NaNs only because its rounding increment happens to carry into the kept bits. The quiet NaN survives because its quiet bit is the top fraction bit, which every format keeps, except at precision 1 (a custom format), where even 0x7FF8000000000000 becomes Infinity. With a custom exponent range, some NaNs come back as ±0 instead.
Cause: the scalar rounding macros (e.g. RN_TIES_TO_EVEN_SCALAR_OTHER_EXP in src/cpfloat_template.h) check underflow and overflow with < / >= comparisons, which are false for a NaN, so the NaN falls through to the bit-masking step (INTOF(y) + ...) & leadmask, which clears its low payload bits. Passing NaNs through before rounding (e.g. if (isnan(*(y))) *(x) = *(y); else ...), or forcing a quiet NaN, fixes it. Even if signalling NaNs are out of scope, quieting one would be fine; turning it into Infinity is not.
Use the following links to see the expected conversion results:
For NaN conversion, your tool always sets the first payload bit of the output to 1. Is there a reason for this choice? When the target format is narrower, this is as good a choice as any other, but when the target format is wider, the payload could be entirely preserved.
For NaN conversion, your tool always sets the first payload bit of the output to 1. Is there a reason for this choice? When the target format is narrower, this is as good a choice as any other, but when the target format is wider, the payload could be entirely preserved.
Agreed, and no, there wasn't a strong reason for the MSB = 1 behavior. It seems like adding an "Advanced" mode NaN behavior option may be helpful in some cases, as there appear to be implementations that support both. I'll make a note to add that. Thanks for the feedback! Open to any other thoughts or suggestions as well.
Activity
mogrob commentedon Oct 13, 2026
Another good catch – thanks!
For NaN conversion, your tool always sets the first payload bit of the output to 1. Is there a reason for this choice? When the target format is narrower, this is as good a choice as any other, but when the target format is wider, the payload could be entirely preserved.
sw23 commentedon Oct 14, 2026
Agreed, and no, there wasn't a strong reason for the MSB = 1 behavior. It seems like adding an "Advanced" mode NaN behavior option may be helpful in some cases, as there appear to be implementations that support both. I'll make a note to add that. Thanks for the feedback! Open to any other thoughts or suggestions as well.