diff --git a/src/libraries/System.Runtime.Numerics/src/System/Numerics/BigInteger.cs b/src/libraries/System.Runtime.Numerics/src/System/Numerics/BigInteger.cs index ad88153227d40b..62fc443b8d4bc6 100644 --- a/src/libraries/System.Runtime.Numerics/src/System/Numerics/BigInteger.cs +++ b/src/libraries/System.Runtime.Numerics/src/System/Numerics/BigInteger.cs @@ -1183,16 +1183,12 @@ public int CompareTo(BigInteger other) return _sign < other._sign ? -1 : _sign > other._sign ? +1 : 0; return -other._sign; } - int cuThis, cuOther; - if (other._bits == null || (cuThis = _bits.Length) > (cuOther = other._bits.Length)) + + if (other._bits == null) return _sign; - if (cuThis < cuOther) - return -_sign; - int cuDiff = GetDiffLength(_bits, other._bits, cuThis); - if (cuDiff == 0) - return 0; - return _bits[cuDiff - 1] < other._bits[cuDiff - 1] ? -_sign : _sign; + int bitsResult = BigIntegerCalculator.Compare(_bits, other._bits); + return _sign < 0 ? -bitsResult : bitsResult; } public int CompareTo(object? obj) @@ -3117,16 +3113,6 @@ private bool GetPartsForBitManipulation(Span xd) return _sign < 0; } - internal static int GetDiffLength(uint[] rgu1, uint[] rgu2, int cu) - { - for (int iv = cu; --iv >= 0;) - { - if (rgu1[iv] != rgu2[iv]) - return iv + 1; - } - return 0; - } - [Conditional("DEBUG")] private void AssertValid() { diff --git a/src/libraries/System.Runtime.Numerics/src/System/Numerics/BigIntegerCalculator.Utils.cs b/src/libraries/System.Runtime.Numerics/src/System/Numerics/BigIntegerCalculator.Utils.cs index 30433dabf80494..47c0738ed1299b 100644 --- a/src/libraries/System.Runtime.Numerics/src/System/Numerics/BigIntegerCalculator.Utils.cs +++ b/src/libraries/System.Runtime.Numerics/src/System/Numerics/BigIntegerCalculator.Utils.cs @@ -1,6 +1,8 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using System.Diagnostics; + namespace System.Numerics { internal static partial class BigIntegerCalculator @@ -15,22 +17,18 @@ internal const public static int Compare(ReadOnlySpan left, ReadOnlySpan right) { - if (left.Length < right.Length) - return -1; - if (left.Length > right.Length) - return 1; + Debug.Assert(left.Length <= right.Length || left.Slice(right.Length).ContainsAnyExcept(0u)); + Debug.Assert(left.Length >= right.Length || right.Slice(left.Length).ContainsAnyExcept(0u)); - for (int i = left.Length - 1; i >= 0; i--) - { - uint leftElement = left[i]; - uint rightElement = right[i]; - if (leftElement < rightElement) - return -1; - if (leftElement > rightElement) - return 1; - } + if (left.Length != right.Length) + return left.Length < right.Length ? -1 : 1; + + int iv = left.Length; + while (--iv >= 0 && left[iv] == right[iv]) ; - return 0; + if (iv < 0) + return 0; + return left[iv] < right[iv] ? -1 : 1; } private static int ActualLength(ReadOnlySpan value) diff --git a/src/libraries/System.Runtime.Numerics/tests/BigInteger/Comparison.cs b/src/libraries/System.Runtime.Numerics/tests/BigInteger/Comparison.cs index b6ce8a2e96cde3..d7bd371b3cf271 100644 --- a/src/libraries/System.Runtime.Numerics/tests/BigInteger/Comparison.cs +++ b/src/libraries/System.Runtime.Numerics/tests/BigInteger/Comparison.cs @@ -344,6 +344,40 @@ private static void RunPositiveTests(Random random) BigInteger b1 = new BigInteger(byteArray); VerifyComparison(BigInteger.One, false, b1 / b1, false, 0); + + // BigIntegers constructed with a byte[] + { + int byteLength = 17; + var byteArray1 = new byte[byteLength]; + var byteArray2 = new byte[byteLength]; + + byteArray1.AsSpan().Fill(1); + byteArray2.AsSpan().Fill(1); + + // Equals + byteArray1[0] = 2; + byteArray2[0] = 2; + VerifyComparison(new BigInteger(byteArray1), false, new BigInteger(byteArray2), false, 0); + VerifyComparison(new BigInteger(byteArray1), true, new BigInteger(byteArray2), true, 0); + VerifyComparison(new BigInteger(byteArray1), false, new BigInteger(byteArray2), true, 1); + VerifyComparison(new BigInteger(byteArray1), true, new BigInteger(byteArray2), false, -1); + + // Smaller + byteArray1[0] = 2; + byteArray2[0] = 3; + VerifyComparison(new BigInteger(byteArray1), false, new BigInteger(byteArray2), false, -1); + VerifyComparison(new BigInteger(byteArray1), true, new BigInteger(byteArray2), true, 1); + VerifyComparison(new BigInteger(byteArray1), false, new BigInteger(byteArray2), true, 1); + VerifyComparison(new BigInteger(byteArray1), true, new BigInteger(byteArray2), false, -1); + + // Larger + byteArray1[0] = 3; + byteArray2[0] = 2; + VerifyComparison(new BigInteger(byteArray1), false, new BigInteger(byteArray2), false, 1); + VerifyComparison(new BigInteger(byteArray1), true, new BigInteger(byteArray2), true, -1); + VerifyComparison(new BigInteger(byteArray1), false, new BigInteger(byteArray2), true, 1); + VerifyComparison(new BigInteger(byteArray1), true, new BigInteger(byteArray2), false, -1); + } } private static void RunNegativeTests(Random random) @@ -636,7 +670,7 @@ private static void VerifyComparison(BigInteger x, bool IsXNegative, BigInteger Assert.Equal(expectedGreaterThan || expectedEquals, x >= y); Assert.Equal(expectedLessThan || expectedEquals, y >= x); } - + private static void VerifyCompareResult(int expected, int actual) { if (0 == expected)