Skip to content

Parse the decimal128 max significand at compile time - #1480

Merged
mborland merged 1 commit into
boostorg:developfrom
ibmibmibm:max-sig-literal
Sep 30, 2026
Merged

mborland merged 1 commit into
boostorg:developfrom
ibmibmibm:max-sig-literal

Conversation

@ibmibmibm

Copy link
Copy Markdown
Contributor

Summary

For decimal128, max_significand_v() returns the _u128 literal of 34 nines. When it rounds up, fenv_round_impl calls this function at run time, thus each call parses 34 digits. This PR keeps the literal in a local constexpr variable, thus the compiler parses it. Decimal128 addition is 1.36 times faster and tan is 1.29 times faster.

Cause
  • fenv_rounding.hpp lines 602 and 606 call max_significand_v<TargetType>() in a normal expression, not in a constant expression. Thus the compiler can evaluate operator""_u128 at run time.
  • With GCC 16.2.1 at -O2, from_chars_integer_impl takes 7% of the time of a loop of decimal128 tan. Half of it comes from tan, and half from the += in the loop.
  • The other _u128 literals are in constexpr tables, thus the compiler parses them.
Speed

Google Benchmark, median of 9 runs, 1024 random operands with 34 or 16 digits, GCC 16.2.1 at -O3:

Operation develop this PR Speed-up
decimal128_t + 46.4 ns 34.2 ns 1.36x
decimal128_t * 29.2 ns 30.4 ns 0.96x
decimal128_t / 50.2 ns 49.8 ns 1.01x
decimal128_t sin 249.8 ns 214.2 ns 1.17x
decimal128_t tan 565.8 ns 437.7 ns 1.29x
decimal64_t + 13.3 ns 13.5 ns 0.99x
decimal64_t * 14.8 ns 14.8 ns 1.00x

Multiplication, division and decimal64 do not change, as expected.

Tests
  • GCC 16.2.1, C++17, the warning flags of the Jamfile: 162 of the 163 run tests pass. test_format_fmtlib does not build on develop either (the char32_t sign conversion in fmt_format.hpp).
  • Clang 22.1.8, C++14 and C++20: test_fenv, test_cmath, test_trig_rounding, test_sqrt_rounding, test_decimal_quantum and test_big_uints pass.

- max_significand_v() for decimal128 returned the _u128 literal.
  fenv_round_impl calls it at run time, thus each rounding up parsed
  34 digits.
- The function now keeps the literal in a constexpr variable, thus the
  compiler parses it.
- decimal128 addition is 1.36x faster and tan is 1.29x faster.
  Multiplication, division and decimal64 do not change.
@codecov

codecov Bot commented Sep 30, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 98.6%. Comparing base (5b03306) to head (bcd3a62).

Additional details and impacted files

Impacted file tree graph

@@            Coverage Diff            @@
##           develop   #1480     +/-   ##
=========================================
+ Coverage     98.6%   98.6%   +0.1%     
=========================================
  Files          312     312             
  Lines        26265   26266      +1     
  Branches      2264    2264             
=========================================
+ Hits         25892   25893      +1     
  Misses         373     373             
Files with missing lines Coverage Δ
include/boost/decimal/detail/attributes.hpp 100.0% <100.0%> (ø)

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 5b03306...bcd3a62. 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 catch. Thanks!

@mborland
mborland merged commit 7c79789 into boostorg:develop Sep 30, 2026
75 checks passed
@ibmibmibm
ibmibmibm deleted the max-sig-literal branch September 30, 2026 23:48
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