Fix UInt128 to double conversion for values >= 2^104#122534
Fix UInt128 to double conversion for values >= 2^104#122534tannergooding merged 5 commits intodotnet:mainfrom
Conversation
There was a problem hiding this comment.
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 |
huoyaoyuan
left a comment
There was a problem hiding this comment.
Can you please check if the issue is also present for Int128?
src/libraries/System.Runtime/tests/System.Runtime.Tests/System/UInt128Tests.cs
Outdated
Show resolved
Hide resolved
|
@dotnet-policy-service agree |
Yes it's also present for Int128, also this fix also applies to Int128 |
- 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
c808380 to
5473f4b
Compare
huoyaoyuan
left a comment
There was a problem hiding this comment.
The numbers can be constructed more intuitively (also Int128 ones)
src/libraries/System.Runtime/tests/System.Runtime.Tests/System/UInt128Tests.cs
Outdated
Show resolved
Hide resolved
src/libraries/System.Runtime/tests/System.Runtime.Tests/System/UInt128Tests.cs
Outdated
Show resolved
Hide resolved
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.
|
/backport to release/10.0 |
|
Started backporting to |
…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]>
Fixes #122203