Skip to content

fix(bigint): correct log2(10) buffer-estimate constant#5

Open
LukaszRozmej wants to merge 2 commits into
feature/perf4from
fix/bigint-buffer-estimate-constant
Open

fix(bigint): correct log2(10) buffer-estimate constant#5
LukaszRozmej wants to merge 2 commits into
feature/perf4from
fix/bigint-buffer-estimate-constant

Conversation

@LukaszRozmej

@LukaszRozmej LukaszRozmej commented Jun 30, 2026

Copy link
Copy Markdown
Member

Summary

Two related commits:

  1. Correctness fix. The integer-math buffer-length estimate added to 17_bigint.patch (BigInteger decimal parsing) used the constant 3321928095 with a binary >> 35 shift. That constant is round(log2(10) × 10⁹) — a decimal scaling of log₂(10) — but it is divided by 2³⁵ (a binary unit). The unit mismatch makes the effective per-digit word multiplier 0.09668083 instead of the intended log2(10)/32 = 0.10381025 — a 6.87% under-estimate (matching the round(log2(10)·2³⁰) = 3566893132 the comment claims). Fixed by using 3566893132.

  2. Helper extraction. The same estimate was duplicated across three sites (NumberToBigInteger, DivideAndConquer, Recursive), each with its own copy of the fixed-point constant. Extracted into a single EstimateWordCount static local function so the constant lives in exactly one place and can never drift between sites again. The overflow-checked additions on the two inner sites are preserved.

Impact of the bug

The buffer carries a +3 slack. The deficit ≈ 0.00713 · digitCount − 3 overtakes that slack once the digit count passes ~424, after which the result buffer is undersized:

digitCount=424:   needed=45    estimate=44    (short by 1)
digitCount=1000:  needed=104   estimate=100   (short by 4)
digitCount=5000:  needed=520   estimate=487   (short by 33)
digitCount=100000:needed=10382 estimate=9672  (short by 710)

All three sites share the defect. An undersized buffer leads to out-of-bounds writes during conversion — reachable by parsing a BigInteger from any numeric string of a few hundred or more digits.

Verification

Confirmed the corrected constant never under-allocates for digit counts from 1 to 2,000,000.

🤖 Generated with Claude Code

@maximmenshikov

Copy link
Copy Markdown
Collaborator

@LukaszRozmej let's make a run in Actions for this particular patch.

@LukaszRozmej
LukaszRozmej changed the base branch from main to feature/perf4 June 30, 2026 16:00
LukaszRozmej and others added 2 commits June 30, 2026 18:02
The integer-math buffer-length estimate in the BigInteger parsing patch
used 3321928095 (= round(log2(10) * 10^9), a decimal scaling) together
with a binary `>> 35` shift. That pairs a base-10 numerator with a base-2
divisor, so the effective multiplier is 0.0966808 instead of the intended
log2(10)/32 = 0.1038103 — a 6.87% under-estimate.

Once the digit count exceeds ~424, the shortfall exceeds the +3 slack and
the result buffer is undersized, causing out-of-bounds writes (e.g. parsing
a BigInteger from a numeric string of a few hundred or more digits).

Replace the constant with round(log2(10) * 2^30) = 3566893132 in all three
sites, matching the comment's stated intent. Verified the corrected value
never under-allocates across digit counts up to 2,000,000.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Collapse the three duplicated word-count estimates into a single static
local function in NumberToBigInteger, used by the method body and the
nested DivideAndConquer/Recursive local functions. The log2(10) fixed-point
constant now appears exactly once, so it can no longer drift between sites,
and each call-site is a single readable line carrying its own slack.

The overflow-checked addition on the two inner sites is preserved.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@LukaszRozmej
LukaszRozmej force-pushed the fix/bigint-buffer-estimate-constant branch from e0d38cc to eb93de3 Compare June 30, 2026 16:02
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