Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/dotnet/runtime.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDrew Kersnar <18474647+dakersnar@users.noreply.github.com>2022-11-10 19:52:53 +0300
committerGitHub <noreply@github.com>2022-11-10 19:52:53 +0300
commit97643fd6231c2168d6992c31c7f5293544d7e357 (patch)
treefe01913456b8f4deab82f680efe7c8f1c59be749
parent1205538e7a619e294fec7dc059df66072d302462 (diff)
Fix bug with BigInteger.TrailingZeroCount (#77727)
* Fix bug with BigInteger.TrailingZeroCount * Update src/libraries/System.Runtime.Numerics/tests/BigIntegerTests.GenericMath.cs Co-authored-by: Tommi Kekäläinen <76913562+tkekalainen@users.noreply.github.com> * Update negative code path * Simplify logic for handling negative values * Update src/libraries/System.Runtime.Numerics/src/System/Numerics/BigInteger.cs Co-authored-by: Tommi Kekäläinen <76913562+tkekalainen@users.noreply.github.com> * Update comment Co-authored-by: Tommi Kekäläinen <76913562+tkekalainen@users.noreply.github.com>
-rw-r--r--src/libraries/System.Runtime.Numerics/src/System/Numerics/BigInteger.cs39
-rw-r--r--src/libraries/System.Runtime.Numerics/tests/BigIntegerTests.GenericMath.cs3
2 files changed, 11 insertions, 31 deletions
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 532f1258897..78e3ec4f7e5 100644
--- a/src/libraries/System.Runtime.Numerics/src/System/Numerics/BigInteger.cs
+++ b/src/libraries/System.Runtime.Numerics/src/System/Numerics/BigInteger.cs
@@ -3481,42 +3481,19 @@ namespace System.Numerics
ulong result = 0;
- if (value._sign >= 0)
- {
- // When the value is positive, we simply need to do a tzcnt for all bits until we find one set
-
- uint part = value._bits[0];
+ // Both positive values and their two's-complement negative representation will share the same TrailingZeroCount,
+ // so the sign of value does not matter and both cases can be handled in the same way
- for (int i = 1; (part == 0) && (i < value._bits.Length); i++)
- {
- part = value._bits[i];
- result += (sizeof(uint) * 8);
+ uint part = value._bits[0];
- i++;
- }
-
- result += uint.TrailingZeroCount(part);
- }
- else
+ for (int i = 1; (part == 0) && (i < value._bits.Length); i++)
{
- // When the value is negative, we need to tzcnt the two's complement representation
- // We'll do this "inline" to avoid needing to unnecessarily allocate.
-
- uint part = ~value._bits[0] + 1;
-
- for (int i = 1; (part == 0) && (i < value._bits.Length); i++)
- {
- // Simply process bits, adding the carry while the previous value is zero
-
- part = ~value._bits[i] + 1;
- result += (sizeof(uint) * 8);
-
- i++;
- }
-
- result += uint.TrailingZeroCount(part);
+ part = value._bits[i];
+ result += (sizeof(uint) * 8);
}
+ result += uint.TrailingZeroCount(part);
+
return result;
}
diff --git a/src/libraries/System.Runtime.Numerics/tests/BigIntegerTests.GenericMath.cs b/src/libraries/System.Runtime.Numerics/tests/BigIntegerTests.GenericMath.cs
index d4e06061325..3e19f1cf22e 100644
--- a/src/libraries/System.Runtime.Numerics/tests/BigIntegerTests.GenericMath.cs
+++ b/src/libraries/System.Runtime.Numerics/tests/BigIntegerTests.GenericMath.cs
@@ -366,6 +366,9 @@ namespace System.Numerics.Tests
Assert.Equal((BigInteger)63, BinaryIntegerHelper<BigInteger>.TrailingZeroCount(Int64MaxValuePlusOne));
Assert.Equal((BigInteger)0, BinaryIntegerHelper<BigInteger>.TrailingZeroCount(UInt64MaxValue));
+
+ Assert.Equal((BigInteger)1000, BinaryIntegerHelper<BigInteger>.TrailingZeroCount(BigInteger.Pow(2, 1000)));
+ Assert.Equal((BigInteger)1000, BinaryIntegerHelper<BigInteger>.TrailingZeroCount(-BigInteger.Pow(2, 1000)));
}
[Fact]