Skip to content

Divide the decimal128 product by 10^33 or 10^34 with a 128-bit reciprocal - #1466

Merged
mborland merged 1 commit into
boostorg:developfrom
ibmibmibm:worktree-d128-mul-div
Sep 25, 2026
Merged

mborland merged 1 commit into
boostorg:developfrom
ibmibmibm:worktree-d128-mul-div

Conversation

@ibmibmibm

Copy link
Copy Markdown
Contributor
  • mul_finalize_u256 gave the 67 or 68 digit product to
    divmod_pow10_u256. That function does a 512-bit multiply-high, a
    256-bit multiply and a shift loop. A profile showed about 64% of a
    decimal128_t multiply in it.
  • 10^k is 5^k * 2^k, with k = 33 or 34. The product shifted right by k bits
    is less than 2^192. A 128-bit reciprocal of 5^k gives the quotient of
    this value or one less, and one compare corrects it.
  • The remainder is less than 2 * 5^k, which is less than 2^80, so its low
    128 bits are enough. The low k bits of the product give the rest of the
    remainder.
  • Only mul_finalize_u256 changes. divmod_pow10_u256 stays as it is,
    because the constructor and the division also use it.

The results are bit-identical to develop:

  • 4 million products for each rounding mode, for decimal128_t and
    decimal_fast128_t. 800,000 of them are exact ties.
  • mul_finalize_u256 against the old division on 22 million products,
    with the edges of its input range and the values next to each rounding
    point.
  • The same checksums in a -m32 build.

test/benchmarks.cpp, multiplication, median of 6 runs (Ryzen 9 3900X,
GCC 16, -O3):

Type develop this PR
decimal128_t 12578813 us 7623474 us
decimal_fast128_t 11266956 us 5837127 us

The checksum s of the benchmark is the same before and after.

…ocal

- mul_finalize_u256 gave the 67 or 68 digit product to divmod_pow10_u256, which does a
  512-bit multiply-high, a 256-bit multiply and a shift loop.
- 10^k is 5^k * 2^k. The product shifted right by k bits is less than 2^192, and a
  128-bit reciprocal of 5^k gives its quotient or one less. One compare corrects it, and
  the low k bits of the product give the rest of the remainder.
- The results are bit-identical to the old division in all five rounding modes.
@codecov

codecov Bot commented Sep 25, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 96.29630% with 1 line in your changes missing coverage. Please review.
✅ Project coverage is 98.6%. Comparing base (a7f0eeb) to head (f3bcc02).

Files with missing lines Patch % Lines
include/boost/decimal/detail/mul_impl.hpp 96.3% 1 Missing ⚠️
Additional details and impacted files

Impacted file tree graph

@@            Coverage Diff            @@
##           develop   #1466     +/-   ##
=========================================
+ Coverage     98.6%   98.6%   +0.1%     
=========================================
  Files          306     306             
  Lines        25607   25619     +12     
  Branches      2202    2202             
=========================================
+ Hits         25242   25256     +14     
+ Misses         365     363      -2     
Files with missing lines Coverage Δ
include/boost/decimal/detail/mul_impl.hpp 95.1% <96.3%> (+0.6%) ⬆️

... and 2 files with indirect coverage changes


Continue to review full report in Codecov by Harness.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update a7f0eeb...f3bcc02. Read the comment docs.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@mborland mborland left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good performance bump. Thanks

@mborland
mborland merged commit 271a8bb into boostorg:develop Sep 25, 2026
74 of 75 checks passed
@ibmibmibm
ibmibmibm deleted the worktree-d128-mul-div branch September 25, 2026 15:15
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants