Skip to content

Fix Dragon4 shortest formatting for exact powers of two#131131

Merged
tannergooding merged 2 commits into
dotnet:mainfrom
tannergooding:tannergooding-fix-dragon4-power-of-two-margins
Jul 21, 2026
Merged

Fix Dragon4 shortest formatting for exact powers of two#131131
tannergooding merged 2 commits into
dotnet:mainfrom
tannergooding:tannergooding-fix-dragon4-power-of-two-margins

Conversation

@tannergooding

Copy link
Copy Markdown
Member

Summary

Number.Dragon4 computed hasUnequalMargins by comparing the extracted mantissa against 1U << TNumber.DenormalMantissaBits. 1U is 32-bit, and C# masks the shift count to 5 bits for a 32-bit operand, so for double (DenormalMantissaBits == 52) this evaluates to 1U << (52 & 31) == 1U << 20, not 1UL << 52.

As a result hasUnequalMargins was wrongly false for every exact power of two in double, so Dragon4 used equal rounding margins and produced a non-round-trippable shortest string for cases like 2^-25 and 2^-958:

Value Before After
2^-25 2.980232238769531E-08 2.9802322387695312E-08
2^-958 4.104536801298376E-289 4.1045368012983762E-289

The "before" strings parse back to the adjacent lower-magnitude double.

The fix widens the shift to 1UL, which is correct for all supported types (float 23, double 52, Half 10, BFloat16 7 � all < 64).


This is a regression from #102683, which merged the per-type double/float/Half paths into one generic method. The pre-refactor double path used 1UL << DiyFp.DoubleImplicitBitIndex; the merge kept Half's 1U, which silently truncates for double. ExtractFractionAndBiasedExponent and DiyFp.GetBoundaries were unaffected (both already use 1UL).

Testing

  • Added DoubleTests.ToString_ExactPowerOfTwo_Roundtrips covering �2^-25 and �2^-958. It fails without the fix and passes with it.
  • Existing double/float/Half/BFloat16 ToString tests pass (checked runtime).
  • Exhaustive power-of-two sweep (2098 values) and ~10M randomized float/double round-trips, plus exhaustive Half, all pass.

Note

GitHub Copilot helped create this PR.

hasUnequalMargins compared the mantissa against a 32-bit `1U` shift, which truncated for double (DenormalMantissaBits == 52) and forced equal margins for every exact power of two. This produced non-round-trippable shortest strings such as `2^-25` and `2^-958`. Use a 64-bit shift.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines:
Successfully started running 3 pipeline(s).
13 pipeline(s) were filtered out due to trigger conditions.
There may be pipelines that require an authorized user to comment /azp run to run.

@dotnet-policy-service

Copy link
Copy Markdown
Contributor

Tagging subscribers to this area: @dotnet/area-system-numerics
See info in area-owners.md if you want to be subscribed.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Fixes a correctness issue in the generic Number.Dragon4 floating-point shortest-formatting path where the implicit-bit comparison used a 32-bit shift (1U << ...), producing the wrong result for double and causing non-roundtrippable output for certain exact powers of two.

Changes:

  • Widened the implicit-bit check to use a 64-bit shift (1UL << TNumber.DenormalMantissaBits) when computing hasUnequalMargins.
  • Added a regression test covering positive/negative double exact power-of-two cases that previously formatted to a non-roundtrippable shortest string.
Show a summary per file
File Description
src/libraries/System.Private.CoreLib/src/System/Number.Dragon4.cs Fixes hasUnequalMargins computation by using a 64-bit shift to correctly detect the implicit bit for double.
src/libraries/System.Runtime/tests/System.Runtime.Tests/System/DoubleTests.cs Adds regression coverage ensuring affected exact power-of-two double values format and parse round-trip as expected.

Copilot's findings

  • Files reviewed: 2/2 changed files
  • Comments generated: 1

Comment thread src/libraries/System.Runtime/tests/System.Runtime.Tests/System/DoubleTests.cs Outdated
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot AI review requested due to automatic review settings July 21, 2026 02:41

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Copilot's findings

  • Files reviewed: 2/2 changed files
  • Comments generated: 0 new

@tannergooding
tannergooding enabled auto-merge (squash) July 21, 2026 02:44
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.

3 participants