Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix BigInteger.Rotate{Left,Right} #112864

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open

Conversation

kzrnm
Copy link
Contributor

@kzrnm kzrnm commented Feb 24, 2025

Fix #112854

  • Fixed the logic of RotateRight.
  • Fixed a bug that caused incorrect two’s complement computation for negative numbers with the most significant bit set in RotateRight and RotateLeft.

I reused the code from #112632.

Benchmark

Code
using BenchmarkDotNet.Attributes;
using BenchmarkDotNet.Configs;
using System.Numerics;

[MemoryDiagnoser(false)]
[HideColumns("Job", "Error", "StdDev", "Median", "RatioSD")]
public class RotateTest
{
    const int shiftSize = (1 << 23) + 13;
    BigInteger positive, negative;

    [GlobalSetup]
    public void Setup()
    {
        var bytes = new byte[1 << 25];
        new Random(227).NextBytes(bytes);
        positive = new BigInteger(bytes, isUnsigned: true);
        negative = -positive;
    }

    [Benchmark] public BigInteger PositiveRotateLeft() => BigInteger.RotateLeft(positive, shiftSize);
    [Benchmark] public BigInteger NegativeRotateLeft() => BigInteger.RotateLeft(negative, shiftSize);

    [Benchmark] public BigInteger PositiveRotateRight() => BigInteger.RotateRight(positive, shiftSize);
    [Benchmark] public BigInteger NegativeRotateRight() => BigInteger.RotateRight(negative, shiftSize);
}

BenchmarkDotNet v0.13.12, Windows 11 (10.0.26100.3194)
13th Gen Intel Core i5-13500, 1 CPU, 20 logical and 14 physical cores
.NET SDK 10.0.100-alpha.1.25077.2
  [Host]     : .NET 10.0.0 (10.0.25.7313), X64 RyuJIT AVX2
  Job-JFZQTT : .NET 10.0.0 (42.42.42.42424), X64 RyuJIT AVX2
  Job-RFISUH : .NET 10.0.0 (42.42.42.42424), X64 RyuJIT AVX2


Method Toolchain Mean Ratio Gen0 Gen1 Gen2 Allocated Alloc Ratio
PositiveRotateLeft \main\corerun.exe 19.15 ms 1.00 156.2500 156.2500 156.2500 33 MB 1.00
PositiveRotateLeft \pr\corerun.exe 14.10 ms 0.61 218.7500 218.7500 218.7500 32.69 MB 0.99
NegativeRotateLeft \main\corerun.exe 19.35 ms 1.00 156.2500 156.2500 156.2500 33 MB 1.00
NegativeRotateLeft \pr\corerun.exe 18.59 ms 0.96 218.7500 218.7500 218.7500 33.25 MB 1.01
PositiveRotateRight \main\corerun.exe 14.93 ms 1.00 156.2500 156.2500 156.2500 32.5 MB 1.00
PositiveRotateRight \pr\corerun.exe 14.07 ms 0.94 234.3750 234.3750 234.3750 32.73 MB 1.01
NegativeRotateRight \main\corerun.exe 16.92 ms 1.00 156.2500 156.2500 156.2500 33 MB 1.00
NegativeRotateRight \pr\corerun.exe 16.43 ms 0.97 218.7500 218.7500 218.7500 33.25 MB 1.01

@dotnet-policy-service dotnet-policy-service bot added the community-contribution Indicates that the PR has been added by a community member label Feb 24, 2025
@kzrnm kzrnm force-pushed the BigIntegerFixRotate branch from 20bca5c to 2ef4970 Compare February 24, 2025 15:59
@@ -3239,267 +3238,89 @@ public static BigInteger PopCount(BigInteger value)
public static BigInteger RotateLeft(BigInteger value, int rotateAmount)
{
value.AssertValid();
int byteCount = (value._bits is null) ? sizeof(int) : (value._bits.Length * 4);
Copy link
Member

Choose a reason for hiding this comment

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

Can this initially be done as a smaller fix that doesn't rewrite the whole algorithm?

We likely need to backport this fix and a less complex change is more desirable for that, as it reduces risk.

A separate PR that also rewrites it for improved performance just for .NET 10 is fine, just ideally separate from the bug fix.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
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.

RotateLeft and RotateRight of BigInteger is buggy.
2 participants