Skip to content

Fix #11148: BigInt to float/double conversion at 64-bit word boundaries and near the maximum - #11149

Merged
thewilsonator merged 1 commit into
dlang:masterfrom
G26karthik:fix-bigint-tofloat
Nov 11, 2026
Merged

thewilsonator merged 1 commit into
dlang:masterfrom
G26karthik:fix-bigint-tofloat

Conversation

@G26karthik

Copy link
Copy Markdown
Contributor

Rationale

Two fixes in BigInt.toFloat, which backs cast(float), cast(double) and comparisons with floating-point values:

  • When the top 64-bit word has its high bit set, w2 >>> w1BitCount shifts a ulong by 64. That is undefined, and on x86-64 the count wraps to 0, so the whole next word is ORed into the mantissa. No bits of the next word are needed in that case, so they are now skipped.
  • exponent is the bit length plus one, so the unbiased exponent is exponent - 2, which is what the biased exponent below is built from. Comparing exponent itself with T.max_exp sent the top two binades, including float.max and double.max, to infinity.

The unittest covers both cases, the rounding carry at float.max and double.max, negative values, and the real comparison path. I also compared 20,000 random BigInts against Python's float(int): the only differences left are exact ties, which round away from zero as documented.

Feature request or issue tracking

Closes #11148.

Pre-review checklist

  • I have performed a self-review of my code.
  • If my PR fixes a bug or introduces a new feature, I have added thorough tests.
  • If my changes are non-trivial and do not concern a reported issue, I have added a changelog entry.

No changelog entry, since this fixes a reported issue.

…ndaries and near the maximum

When the top 64-bit word has its high bit set, toFloat shifted the next
word right by 64, which is undefined; on x86-64 the whole word was ORed
into the mantissa. The overflow checks also compared the bit length plus
one with T.max_exp, so the top two binades, including float.max and
double.max, became infinity.
@thewilsonator
thewilsonator merged commit 58db422 into dlang:master Nov 11, 2026
7 of 9 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

BigInt cast to float/double is wrong at 64-bit word boundaries and overflows two binades early

3 participants