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
Should lossy packing round to the closest Float instead of truncating? #349
Lossy packing truncates: when a value needs more digits than an int224 coefficient holds, it keeps the representable Float toward zero. #333 sharpens this into "the closest representable Float without exceeding the true magnitude".
The #340 discussion raised the question of whether truncation is the right default at all. The absolute error can be up to one unit in the last place, where rounding to the closest Float would be at most half a unit. Example from #340: for 1e100 − 1, truncation gives (10^67 − 1)e33 (off by about 1e33), and the closest Float is 1e100 (off by 1).
The library can't know the caller's safe direction. DeFi rounds in the protocol's favour, which is down for some call sites and up for others. So "always toward zero" isn't a safety property on its own, and closest-value rounding may be the better default.
Decide:
Default rounding for lossy packing and for every operation built on it (mul, div, inv, add/sub, conversions): toward zero, or closest Float (and which tie-break).
Whether callers need explicit directional variants (down/up) for the cases where direction matters.
Consequences to weigh:
gas on the packed and shed paths;
consistency with the transcendentals (which already round to nearest at 41 digits);
Related finding from #386 / PR #411: log10, pow10 and pow are not correctly rounded. They round an internal approximation, within the proven bound, to nearest at 41 digits. A true value that lies within that bound of a rounding tie can therefore land on either neighbour.
Example: x = 62876337819492131669053461917963730523385842721800e-50. The true 10^x (bc) is just above a tie (…3215|500000001784…), but pow10 rounds down. That is within the documented bound.
#411 rewords the NatSpec and README to say this, instead of the literal "rounded to nearest, half up". The tie-rounding test stays as a white-box check of the internal rounding step; the public contract is the bound.
For this issue: whatever default rounding direction is chosen, it can only be exact for operations that are exact before packing (add, sub, mul, div, inv, sqrt, the conversions). For the transcendentals the contract is a bound around the true value, so "round once in direction X" can only be guaranteed up to that bound, unless they get the precision to decide ties (the table-maker's dilemma; see #350).
Closing per the ruling on #350: toward zero stays the default for lossy packing and every operation built on it. add/sub move to round once toward zero (#350), so mul, div, inv, add, sub and the lossy conversions all truncate the exact result once. Closest-value rounding is not adopted as the default; sqrt, pow, pow10 and log10 stay documented as rounded approximations within their proven bounds.
Activity
thedavidmeister commentedon Oct 9, 2026
Related finding from #386 / PR #411:
log10,pow10andpoware not correctly rounded. They round an internal approximation, within the proven bound, to nearest at 41 digits. A true value that lies within that bound of a rounding tie can therefore land on either neighbour.Example: x = 62876337819492131669053461917963730523385842721800e-50. The true 10^x (bc) is just above a tie (…3215|500000001784…), but
pow10rounds down. That is within the documented bound.#411 rewords the NatSpec and README to say this, instead of the literal "rounded to nearest, half up". The tie-rounding test stays as a white-box check of the internal rounding step; the public contract is the bound.
For this issue: whatever default rounding direction is chosen, it can only be exact for operations that are exact before packing (
add,sub,mul,div,inv,sqrt, the conversions). For the transcendentals the contract is a bound around the true value, so "round once in direction X" can only be guaranteed up to that bound, unless they get the precision to decide ties (the table-maker's dilemma; see #350).thedavidmeister commentedon Oct 11, 2026
Closing per the ruling on #350: toward zero stays the default for lossy packing and every operation built on it.
add/submove to round once toward zero (#350), so mul, div, inv, add, sub and the lossy conversions all truncate the exact result once. Closest-value rounding is not adopted as the default;sqrt,pow,pow10andlog10stay documented as rounded approximations within their proven bounds.