From f2ccc491882f19e24192b13c07ef8f218bcbafa3 Mon Sep 17 00:00:00 2001 From: LEI Hongfaan Date: Thu, 25 Jul 2024 06:56:37 +0000 Subject: [PATCH 1/5] Add a missing = --- .../System.Runtime.Numerics/src/System/Numerics/BigInteger.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 e4d8845dd05e81..f58c9877d3d53a 100644 --- a/src/libraries/System.Runtime.Numerics/src/System/Numerics/BigInteger.cs +++ b/src/libraries/System.Runtime.Numerics/src/System/Numerics/BigInteger.cs @@ -544,7 +544,7 @@ private BigInteger(Span value) isNegative = true; length = value.LastIndexOfAnyExcept(uint.MaxValue) + 1; - if ((length == 0) || ((int)value[length - 1] > 0)) + if ((length == 0) || ((int)value[length - 1] >= 0)) { // We ne need to preserve the sign bit length++; From 76459dc0074e484eb7bf308b0be50824b3476147 Mon Sep 17 00:00:00 2001 From: LEI-Hongfaan Date: Sat, 27 Jul 2024 00:01:23 +0000 Subject: [PATCH 2/5] Add some tests for bigint AND. --- .../tests/BigInteger/MyBigInt.cs | 5 + .../tests/BigInteger/SampleGeneration.cs | 82 +++++++++++ .../tests/BigInteger/UInt32Samples.cs | 138 ++++++++++++++++++ .../tests/BigInteger/op_and.cs | 28 ++++ .../System.Runtime.Numerics.Tests.csproj | 2 + 5 files changed, 255 insertions(+) create mode 100644 src/libraries/System.Runtime.Numerics/tests/BigInteger/SampleGeneration.cs create mode 100644 src/libraries/System.Runtime.Numerics/tests/BigInteger/UInt32Samples.cs diff --git a/src/libraries/System.Runtime.Numerics/tests/BigInteger/MyBigInt.cs b/src/libraries/System.Runtime.Numerics/tests/BigInteger/MyBigInt.cs index cd4a578fab910e..58d4afdc819f71 100644 --- a/src/libraries/System.Runtime.Numerics/tests/BigInteger/MyBigInt.cs +++ b/src/libraries/System.Runtime.Numerics/tests/BigInteger/MyBigInt.cs @@ -877,6 +877,11 @@ public static List GetBytes(BitArray ba) } public static string Print(byte[] bytes) + { + return Print(bytes.AsSpan()); + } + + public static string Print(ReadOnlySpan bytes) { string ret = "make "; diff --git a/src/libraries/System.Runtime.Numerics/tests/BigInteger/SampleGeneration.cs b/src/libraries/System.Runtime.Numerics/tests/BigInteger/SampleGeneration.cs new file mode 100644 index 00000000000000..94d71ec1b6be57 --- /dev/null +++ b/src/libraries/System.Runtime.Numerics/tests/BigInteger/SampleGeneration.cs @@ -0,0 +1,82 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace System.Numerics.Tests +{ + public static partial class SampleGeneration + { + + public static IEnumerable> EnumerateSequence(IEnumerable elementSource, int minLength, int maxLengthExclusive) + { + return EnumerateSequence(elementSource.ToArray(), minLength, maxLengthExclusive); + } + + public static IEnumerable> EnumerateSequence(T[] elementSource, int minLength, int maxLengthExclusive) + { + for (var i = minLength; maxLengthExclusive > i; ++i) + { + foreach (var item in EnumerateSequence(elementSource, i)) + { + yield return item; + } + } + } + + public static IEnumerable> EnumerateSequence(IEnumerable elementSource, int length) + { + return EnumerateSequence(elementSource.ToArray(), length); + } + + public static IEnumerable> EnumerateSequence(T[] elementSource, int length) + { + var a = new T[length]; + var r = new ReadOnlyMemory(a); + foreach (var _ in EnumerateSequenceYieldsCurrentCount(elementSource, a)) + { + yield return r; + } + } + + private static IEnumerable EnumerateSequenceYieldsCurrentCount(T[] elementSource, T[] buffer) + { + var c = 0L; + var b = elementSource.Length; + if (b != 0) + { + var stack = new int[buffer.Length]; + for (var i = 0; i < buffer.Length; ++i) + { + buffer[i] = elementSource[0]; + } + { + L:; + yield return c++; + for (var i = 0; stack.Length != i; ++i) + { + var en = ++stack[i]; + if (b == en) + { + } + else + { + buffer[i] = elementSource[en]; + for (; 0 <= --i;) + { + buffer[i] = elementSource[0]; + stack[i] = 0; + } + goto L; + } + } + } + } + } + } +} diff --git a/src/libraries/System.Runtime.Numerics/tests/BigInteger/UInt32Samples.cs b/src/libraries/System.Runtime.Numerics/tests/BigInteger/UInt32Samples.cs new file mode 100644 index 00000000000000..658c68ae2c9811 --- /dev/null +++ b/src/libraries/System.Runtime.Numerics/tests/BigInteger/UInt32Samples.cs @@ -0,0 +1,138 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.Linq; +using Xunit; + +namespace System.Numerics.Tests +{ + + public static partial class UInt32Samples + { + private static readonly uint[] set1 = new uint[] { + 0B00000000000000000000000000000000U, + 0B00000000000000000000000000000001U, + 0B00111111111111111111111111111110U, + 0B00111111111111111111111111111111U, + + 0B01000000000000000000000000000000U, + 0B01000000000000000000000000000001U, + 0B01111111111111111111111111111110U, + 0B01111111111111111111111111111111U, + + 0B10000000000000000000000000000000U, + 0B10000000000000000000000000000001U, + 0B10111111111111111111111111111110U, + 0B10111111111111111111111111111111U, + + 0B11000000000000000000000000000000U, + 0B11000000000000000000000000000001U, + 0B11111111111111111111111111111110U, + 0B11111111111111111111111111111111U, + }; + + private static IEnumerable GetSet1() + { + foreach (var item in set1) + { + yield return item; + } + } + + public static readonly IEnumerable Set1 = GetSet1(); + + private static readonly uint[] set2 = new uint[] { + 0B00000000000000000000000000000000U, + 0B00000000000000000000000000000001U, + 0B00000000000000000100000000000000U, + 0B00000000000000000100000000000001U, + + 0B00000000000000010000000000000000U, + 0B00000000000000010000000000000001U, + 0B00000000000000010100000000000000U, + 0B00000000000000010100000000000001U, + + 0B00111111111111111111111111111110U, + 0B00111111111111111111111111111111U, + 0B00111111111111111011111111111110U, + 0B00111111111111111011111111111111U, + + 0B00111111111111101111111111111110U, + 0B00111111111111101111111111111111U, + 0B00111111111111101011111111111110U, + 0B00111111111111101011111111111111U, + + 0B01000000000000000000000000000000U, + 0B01000000000000000000000000000001U, + 0B01000000000000000100000000000000U, + 0B01000000000000000100000000000001U, + + 0B01000000000000010000000000000000U, + 0B01000000000000010000000000000001U, + 0B01000000000000010100000000000000U, + 0B01000000000000010100000000000001U, + + 0B01111111111111111111111111111110U, + 0B01111111111111111111111111111111U, + 0B01111111111111111011111111111110U, + 0B01111111111111111011111111111111U, + + 0B01111111111111101111111111111110U, + 0B01111111111111101111111111111111U, + 0B01111111111111101011111111111110U, + 0B01111111111111101011111111111111U, + + 0B10000000000000000000000000000000U, + 0B10000000000000000000000000000001U, + 0B10000000000000000100000000000000U, + 0B10000000000000000100000000000001U, + + 0B10000000000000010000000000000000U, + 0B10000000000000010000000000000001U, + 0B10000000000000010100000000000000U, + 0B10000000000000010100000000000001U, + + 0B10111111111111111111111111111110U, + 0B10111111111111111111111111111111U, + 0B10111111111111111011111111111110U, + 0B10111111111111111011111111111111U, + + 0B10111111111111101111111111111110U, + 0B10111111111111101111111111111111U, + 0B10111111111111101011111111111110U, + 0B10111111111111101011111111111111U, + + 0B11000000000000000000000000000000U, + 0B11000000000000000000000000000001U, + 0B11000000000000000100000000000000U, + 0B11000000000000000100000000000001U, + + 0B11000000000000010000000000000000U, + 0B11000000000000010000000000000001U, + 0B11000000000000010100000000000000U, + 0B11000000000000010100000000000001U, + + 0B11111111111111111111111111111110U, + 0B11111111111111111111111111111111U, + 0B11111111111111111011111111111110U, + 0B11111111111111111011111111111111U, + + 0B11111111111111101111111111111110U, + 0B11111111111111101111111111111111U, + 0B11111111111111101011111111111110U, + 0B11111111111111101011111111111111U, + }; + + private static IEnumerable GetSet2() + { + foreach (var item in set2) + { + yield return item; + } + } + + public static readonly IEnumerable Set2 = GetSet2(); + } +} diff --git a/src/libraries/System.Runtime.Numerics/tests/BigInteger/op_and.cs b/src/libraries/System.Runtime.Numerics/tests/BigInteger/op_and.cs index ed25708e2d0c6d..2bc182aeaeada1 100644 --- a/src/libraries/System.Runtime.Numerics/tests/BigInteger/op_and.cs +++ b/src/libraries/System.Runtime.Numerics/tests/BigInteger/op_and.cs @@ -1,6 +1,9 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using System.Collections.Generic; +using System.Linq; +using System.Runtime.InteropServices; using Xunit; namespace System.Numerics.Tests @@ -117,6 +120,26 @@ public static void RunAndTests() } } + [Fact] + public static void RunAndTestsForSampleSet1() + { + var s = SampleGeneration.EnumerateSequence(UInt32Samples.Set1, 2); + var t = SampleGeneration.EnumerateSequence(UInt32Samples.Set1, 3); + + foreach (var i in s) + { + foreach (var j in t) + { + var a = MemoryMarshal.AsBytes(i.Span); + var b = MemoryMarshal.AsBytes(j.Span); + + VerifyAndString(Print(a) + Print(b) + "b&"); + + VerifyAndString(Print(b) + Print(a) + "b&"); + } + } + } + private static void VerifyAndString(string opstring) { StackCalc sc = new StackCalc(opstring); @@ -139,5 +162,10 @@ private static string Print(byte[] bytes) { return MyBigIntImp.Print(bytes); } + + private static string Print(ReadOnlySpan bytes) + { + return MyBigIntImp.Print(bytes); + } } } diff --git a/src/libraries/System.Runtime.Numerics/tests/System.Runtime.Numerics.Tests.csproj b/src/libraries/System.Runtime.Numerics/tests/System.Runtime.Numerics.Tests.csproj index 8e2c0ce29543bb..4224f0ac83414f 100644 --- a/src/libraries/System.Runtime.Numerics/tests/System.Runtime.Numerics.Tests.csproj +++ b/src/libraries/System.Runtime.Numerics/tests/System.Runtime.Numerics.Tests.csproj @@ -48,10 +48,12 @@ + + From e228e7fb2c54d7a768d505880969e07953bd4ace Mon Sep 17 00:00:00 2001 From: LEI-Hongfaan Date: Sat, 27 Jul 2024 00:01:23 +0000 Subject: [PATCH 3/5] Add some tests for bigint AND. --- .../System.Runtime.Numerics/tests/BigInteger/op_and.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libraries/System.Runtime.Numerics/tests/BigInteger/op_and.cs b/src/libraries/System.Runtime.Numerics/tests/BigInteger/op_and.cs index 2bc182aeaeada1..86bc8b59c0d29c 100644 --- a/src/libraries/System.Runtime.Numerics/tests/BigInteger/op_and.cs +++ b/src/libraries/System.Runtime.Numerics/tests/BigInteger/op_and.cs @@ -124,7 +124,7 @@ public static void RunAndTests() public static void RunAndTestsForSampleSet1() { var s = SampleGeneration.EnumerateSequence(UInt32Samples.Set1, 2); - var t = SampleGeneration.EnumerateSequence(UInt32Samples.Set1, 3); + var t = SampleGeneration.EnumerateSequence(UInt32Samples.Set1, 2); foreach (var i in s) { From e9a8202b31bfaa7ad4743ef17310f6f8d1171631 Mon Sep 17 00:00:00 2001 From: LEI Hongfaan Date: Sat, 27 Jul 2024 02:54:48 +0000 Subject: [PATCH 4/5] Update src/libraries/System.Runtime.Numerics/tests/BigInteger/SampleGeneration.cs Co-authored-by: Dan Moseley --- .../System.Runtime.Numerics/tests/BigInteger/SampleGeneration.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/libraries/System.Runtime.Numerics/tests/BigInteger/SampleGeneration.cs b/src/libraries/System.Runtime.Numerics/tests/BigInteger/SampleGeneration.cs index 94d71ec1b6be57..7d778be2141f8a 100644 --- a/src/libraries/System.Runtime.Numerics/tests/BigInteger/SampleGeneration.cs +++ b/src/libraries/System.Runtime.Numerics/tests/BigInteger/SampleGeneration.cs @@ -12,7 +12,6 @@ namespace System.Numerics.Tests { public static partial class SampleGeneration { - public static IEnumerable> EnumerateSequence(IEnumerable elementSource, int minLength, int maxLengthExclusive) { return EnumerateSequence(elementSource.ToArray(), minLength, maxLengthExclusive); From 75f628659f6be05b346c879083cbcaa623846d31 Mon Sep 17 00:00:00 2001 From: Rob Hague Date: Wed, 13 Nov 2024 17:25:20 +0000 Subject: [PATCH 5/5] Fix BigInteger bitwise operators on certain negative numbers (#109684) Co-authored-by: Tanner Gooding --- .../src/System/Numerics/BigInteger.cs | 2 +- .../tests/BigInteger/op_and.cs | 16 ++++++++++++++++ 2 files changed, 17 insertions(+), 1 deletion(-) 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 f58c9877d3d53a..b3355ff68678ca 100644 --- a/src/libraries/System.Runtime.Numerics/src/System/Numerics/BigInteger.cs +++ b/src/libraries/System.Runtime.Numerics/src/System/Numerics/BigInteger.cs @@ -546,7 +546,7 @@ private BigInteger(Span value) if ((length == 0) || ((int)value[length - 1] >= 0)) { - // We ne need to preserve the sign bit + // We need to preserve the sign bit length++; } Debug.Assert((int)value[length - 1] < 0); diff --git a/src/libraries/System.Runtime.Numerics/tests/BigInteger/op_and.cs b/src/libraries/System.Runtime.Numerics/tests/BigInteger/op_and.cs index 86bc8b59c0d29c..235d75d44d7c92 100644 --- a/src/libraries/System.Runtime.Numerics/tests/BigInteger/op_and.cs +++ b/src/libraries/System.Runtime.Numerics/tests/BigInteger/op_and.cs @@ -120,6 +120,22 @@ public static void RunAndTests() } } + [Fact] + public void Issue109669() + { + // Operations on numbers whose result is of the form 0xFFFFFFFF 00000000 ... 00000000 + // in two's complement. + + Assert.Equal(-4294967296, new BigInteger(-4294967296) & new BigInteger(-1919810)); + Assert.Equal(-4294967296, new BigInteger(-4042322161) & new BigInteger(-252645136)); + Assert.Equal(-4294967296, new BigInteger(-8589934592) | new BigInteger(-21474836480)); + + BigInteger a = new BigInteger(MemoryMarshal.AsBytes([uint.MaxValue, 0u, 0u]), isBigEndian: true); + Assert.Equal(a, a & a); + Assert.Equal(a, a | a); + Assert.Equal(a, a ^ 0); + } + [Fact] public static void RunAndTestsForSampleSet1() {