Skip to content

Fix UInt128 to double conversion for values >= 2^104#122534

Merged
tannergooding merged 5 commits intodotnet:mainfrom
sdcb:fix-uint128-conversion
Dec 21, 2025
Merged

Fix UInt128 to double conversion for values >= 2^104#122534
tannergooding merged 5 commits intodotnet:mainfrom
sdcb:fix-uint128-conversion

Conversation

@sdcb
Copy link
Contributor

@sdcb sdcb commented Dec 14, 2025

Fixes #122203

Copilot AI review requested due to automatic review settings December 14, 2025 09:33
@dotnet-policy-service dotnet-policy-service bot added the community-contribution Indicates that the PR has been added by a community member label Dec 14, 2025
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR fixes a bug in the UInt128 to double conversion for values >= 2^104. The issue was caused by incorrect handling of precision loss during the conversion, which has been corrected by implementing proper sticky bit rounding.

  • Fixed the rounding logic in the UInt128 to double explicit conversion operator
  • Added a regression test to verify the fix

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated no comments.

File Description
src/libraries/System.Private.CoreLib/src/System/UInt128.cs Changed the conversion logic to use a sticky bit (1 if any of the lower 24 bits are set, 0 otherwise) instead of OR-ing the lower 24 bits directly, ensuring proper rounding for large values
src/libraries/System.Runtime/tests/System.Runtime.Tests/System/UInt128Tests.cs Added a regression test that validates the conversion of a large UInt128 value (>= 2^104) to double produces the correct result

Copy link
Member

@huoyaoyuan huoyaoyuan left a comment

Choose a reason for hiding this comment

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

Can you please check if the issue is also present for Int128?

@sdcb
Copy link
Contributor Author

sdcb commented Dec 14, 2025

@dotnet-policy-service agree

@sdcb
Copy link
Contributor Author

sdcb commented Dec 14, 2025

Can you please check if the issue is also present for Int128?

Yes it's also present for Int128, also this fix also applies to Int128

sdcb added 3 commits December 15, 2025 17:18
- Correctly calculate the sticky bit when converting large UInt128 values (>= 2^104) to double to prevent precision loss.
- Optimize the upper bits extraction by accessing _upper directly instead of shifting.
- Add regression tests for Int128 to ensure it is also fixed.
- Update test comments to better explain the test cases.

Fixes dotnet#122203
@sdcb sdcb force-pushed the fix-uint128-conversion branch from c808380 to 5473f4b Compare December 15, 2025 09:18
Copy link
Member

@huoyaoyuan huoyaoyuan left a comment

Choose a reason for hiding this comment

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

The numbers can be constructed more intuitively (also Int128 ones)

sdcb added 2 commits December 16, 2025 18:17
Use decimal literals instead of scientific notation and hex constructors
instead of bit shifts for clearer test value representation.
Change threshold check from (value._upper >> 24) to (value._upper >> 40)
to correctly handle values up to 2^104 in the intermediate precision branch.
@tannergooding tannergooding enabled auto-merge (squash) December 20, 2025 13:02
@tannergooding tannergooding merged commit 671cd12 into dotnet:main Dec 21, 2025
143 checks passed
@sdcb sdcb deleted the fix-uint128-conversion branch December 21, 2025 03:42
@tannergooding
Copy link
Member

/backport to release/10.0

@github-actions
Copy link
Contributor

Started backporting to release/10.0 (link to workflow run)

jeffhandley pushed a commit that referenced this pull request Jan 5, 2026
…122686)

Backport of #122534 to release/10.0

/cc @tannergooding @sdcb

## Customer Impact

- [x] Customer reported
- [ ] Found internally

#122203 - Customers attempting
to convert a `UInt128` to a double may see incorrect results for values
in the range `[2^88, 2^104)`.

## Regression

- [ ] Yes
- [x] No

Not a regression, `UInt128` was checked in with this bug which was a
simple logic error.

## Testing

Explicit tests and validation covering the scenario were added.

## Risk

Low. This is a lesser used type and the bug was a case where a path was
covering a lesser range than intended. This was due to it shifting by
`24` (`64 - 40 == 24`) when it should've been shifting by `40` instead
(`64 - 24 == 40`).

---------

Co-authored-by: sdcb <[email protected]>
@github-actions github-actions bot locked and limited conversation to collaborators Jan 21, 2026
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

area-System.Numerics community-contribution Indicates that the PR has been added by a community member

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Incorrect (U)Int128 to double conversion

5 participants