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

[DRAFT] BigInteger.Divide perf optimization #89211

Closed
wants to merge 2 commits into from
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@

using System.Buffers;
using System.Diagnostics;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;

namespace System.Numerics
{
Expand All @@ -16,14 +18,14 @@ public static void Divide(ReadOnlySpan<uint> left, uint right, Span<uint> quotie
// Executes the division for one big and one 32-bit integer.
// Thus, we've similar code than below, but there is no loop for
// processing the 32-bit integer, since it's a single element.

ref uint quotientPtr = ref MemoryMarshal.GetReference(quotient);
ulong carry = 0UL;

for (int i = left.Length - 1; i >= 0; i--)
{
ulong value = (carry << 32) | left[i];
ulong digit = value / right;
quotient[i] = (uint)digit;
Unsafe.Add(ref quotientPtr, i) = (uint)digit;
carry = value - digit * right;
}
remainder = (uint)carry;
Expand All @@ -35,13 +37,14 @@ public static void Divide(ReadOnlySpan<uint> left, uint right, Span<uint> quotie
Debug.Assert(quotient.Length == left.Length);

// Same as above, but only computing the quotient.

ref uint quotientPtr = ref MemoryMarshal.GetReference(quotient);
ulong carry = 0UL;

for (int i = left.Length - 1; i >= 0; i--)
{
ulong value = (carry << 32) | left[i];
ulong digit = value / right;
quotient[i] = (uint)digit;
Unsafe.Add(ref quotientPtr, i) = (uint)digit;
carry = value - digit * right;
}
}
Expand Down Expand Up @@ -199,11 +202,12 @@ private static uint AddDivisor(Span<uint> left, ReadOnlySpan<uint> right)

// Repairs the dividend, if the last subtract was too much

ref uint leftPtr = ref MemoryMarshal.GetReference(left);
ulong carry = 0UL;

for (int i = 0; i < right.Length; i++)
{
ref uint leftElement = ref left[i];
ref uint leftElement = ref Unsafe.Add(ref leftPtr, i);
ulong digit = (leftElement + carry) + right[i];
leftElement = unchecked((uint)digit);
carry = digit >> 32;
Expand All @@ -220,17 +224,18 @@ private static uint SubtractDivisor(Span<uint> left, ReadOnlySpan<uint> right, u
// Combines a subtract and a multiply operation, which is naturally
// more efficient than multiplying and then subtracting...

ref uint leftPtr = ref MemoryMarshal.GetReference(left);
ulong carry = 0UL;

for (int i = 0; i < right.Length; i++)
{
carry += right[i] * q;
uint digit = unchecked((uint)carry);
carry >>= 32;
ref uint leftElement = ref left[i];
if (leftElement < digit)
++carry;
leftElement = unchecked(leftElement - digit);
ref uint leftElement = ref Unsafe.Add(ref leftPtr, i);
ulong newDigit = unchecked((ulong)leftElement - digit);
carry += (newDigit >> 32) & 0x1; // This is the same as if (leftElement < digit) ++carry
leftElement = unchecked((uint)newDigit);
}

return (uint)carry;
Expand Down
Loading