Repository navigation
Fix fma for a tie with a far addend and for an infinite addend - #1523
Merged
Merged
Conversation
ibmibmibm
force-pushed
the
fma-inf-addend
branch
from
October 17, 2026 07:37
278a1aa to
e55f42c
Compare
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## develop #1523 +/- ##
=========================================
- Coverage 98.6% 98.4% -0.2%
=========================================
Files 321 323 +2
Lines 27261 27444 +183
Branches 2285 2288 +3
=========================================
+ Hits 26858 26981 +123
- Misses 403 463 +60
... and 7 files with indirect coverage changes Continue to review full report in Codecov by Harness.
🚀 New features to boost your workflow:
|
ibmibmibm
marked this pull request as ready for review
October 17, 2026 12:15
mborland
approved these changes
Oct 20, 2026
If x * y is a tie at the precision of the result, and z is far below it, the sign of z decides the tie in the nearest modes. fma for decimal32_t and decimal64_t added the operands with add_impl, which dropped z when the operands have more digits than the result. fma now keeps the exact product of the significands in 64, 128 or 256 bits, and it does not move the product up. z moves to the product, but a far z moves up p digits and the product moves down to it. The operand that moves down records a dropped digit that is not zero. After the sum, that record goes into the last digit, thus a carry or a borrow does not remove it. A sum of 2p - 1 or 2p digits rounds in one step with the finalizers of multiplication, and other sums round in the constructor. A zero operand leaves one operation, which rounds one time. Fixes boostorg#1522
When an operand of fma was not finite, fma returned x * y + z. If x and y are finite but their product is above the largest value, x * y rounds to an infinity, and with z an infinity of the other sign the sum is NaN. The exact product is finite, so the correct result is z: fma(max, 10, -inf) must be -inf. fma now returns z in this case for all six types, and keeps x * y + z for the other cases. Fixes boostorg#1522
mborland
force-pushed
the
fma-inf-addend
branch
from
October 20, 2026 14:39
e55f42c to
62ce88f
Compare
Member
|
There was a merge conflict from your other PRs so the only change I made was to rebase this PR on develop |
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.
fmafordecimal32_t,decimal64_tand the fast types added the exact product andzwithadd_impl. Ifzwas far below the product, the nearest modes droppedz, and a tie in the product went to the even neighbor.fmanow keeps the exact product of the significands in 64, 128 or 256 bits, and it does not move the product up.zmoves to the product. A farzmoves up p digits, and the product moves down to it.xandyand an infinitez,fmareturnedx * y + z. A large product rounded to an infinity, and withzof the other sign the sum was NaN.fmanow returnszin this case, for all six types.test_fma_tietests ties with a farz, a dropped digit with a carry or a borrow, the bounds of the finalizers, and the five rounding modes.github_issue_1522tests the infinitez.Fixes #1522
Correctness
decimal32_t,decimal64_tanddecimal128_t, in the five rounding modes, against Intel libbid 2.0 Update 4. Each value that is not the same is an underflow error of libbid. Pythondecimalgives our value in each of these cases.z, for all six types and the five modes, against Pythondecimal. All results are correct.tie_farset of the benchmark,developgives a different value from libbid for 6720 of 16384decimal32_ttriples and 6193 of 16384decimal64_ttriples. The fix gives 0.test_fma,test_fma_tie,github_issue_1522andtest_cmathpass with GCC 16.2 and Clang 23.1 in C++14 and C++20 with-Wall -Wextra -Werror. They also pass without the builtin 128-bit integer, withBOOST_DECIMAL_FAST_MATH, and withBOOST_DECIMAL_NO_CONSTEVAL_DETECTION.Speed
The table gives ns for each call, the best of 3 runs. Each set has 16384 triples: random significands and exponents (random), a tie with a far
z(tie_far), aznear the product (near), aznear-(x * y)(cancel) and a zeroz(zero_z). I used-O3 -march=nativeon an AMD Ryzen 9 3900X, on one core. libbid is built with GCC at-O2.decimal32_tdecimal32_tdecimal32_tdecimal32_tdecimal32_tdecimal64_tdecimal64_tdecimal64_tdecimal64_tdecimal64_tdecimal128_tdecimal128_tdecimal128_tdecimal128_tdecimal128_tdecimal_fast32_tdecimal_fast32_tdecimal_fast32_tdecimal_fast32_tdecimal_fast32_tdecimal_fast64_tdecimal_fast64_tdecimal_fast64_tdecimal_fast64_tdecimal_fast64_tdecimal_fast128_tdecimal_fast128_tdecimal_fast128_tdecimal_fast128_tdecimal_fast128_tWith Clang, the 128-bit types are 3 to 5 ns slower in the cancel set.
Size
One function calls
fmafor each of the six types. The table gives the size of all.textsections of its object file, in bytes.-O2-Os-O2-Os