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

Add Tuple-based Math.DivRem overloads #45074

Merged
merged 8 commits into from
Dec 4, 2020
Merged
Show file tree
Hide file tree
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 @@ -182,7 +182,8 @@ internal int Format(Span<char> destination)

if (precision >= 10)
{
uint div = Math.DivRem(precision, 10, out precision);
uint div;
(div, precision) = Math.DivRem(precision, 10);
destination[1] = (char)('0' + div % 10);
count = 2;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,8 @@ private static bool TryFormatStandard(TimeSpan value, StandardFormat format, str
}
}

totalSecondsRemaining = Math.DivRem((ulong)ticks, TimeSpan.TicksPerSecond, out ulong fraction64);
ulong fraction64;
(totalSecondsRemaining, fraction64) = Math.DivRem((ulong)ticks, TimeSpan.TicksPerSecond);
fraction = (uint)fraction64;
}

Expand Down Expand Up @@ -170,15 +171,15 @@ private static bool TryFormatStandard(TimeSpan value, StandardFormat format, str
if (totalSecondsRemaining > 0)
{
// Only compute minutes if the TimeSpan has an absolute value of >= 1 minute.
totalMinutesRemaining = Math.DivRem(totalSecondsRemaining, 60 /* seconds per minute */, out seconds);
(totalMinutesRemaining, seconds) = Math.DivRem(totalSecondsRemaining, 60 /* seconds per minute */);
Debug.Assert(seconds < 60);
}

ulong totalHoursRemaining = 0, minutes = 0;
if (totalMinutesRemaining > 0)
{
// Only compute hours if the TimeSpan has an absolute value of >= 1 hour.
totalHoursRemaining = Math.DivRem(totalMinutesRemaining, 60 /* minutes per hour */, out minutes);
(totalHoursRemaining, minutes) = Math.DivRem(totalMinutesRemaining, 60 /* minutes per hour */);
Debug.Assert(minutes < 60);
}

Expand All @@ -189,7 +190,7 @@ private static bool TryFormatStandard(TimeSpan value, StandardFormat format, str
if (totalHoursRemaining > 0)
{
// Only compute days if the TimeSpan has an absolute value of >= 1 day.
days = Math.DivRem((uint)totalHoursRemaining, 24 /* hours per day */, out hours);
(days, hours) = Math.DivRem((uint)totalHoursRemaining, 24 /* hours per day */);
Debug.Assert(hours < 24);
}

Expand Down
127 changes: 119 additions & 8 deletions src/libraries/System.Private.CoreLib/src/System/Math.cs
Original file line number Diff line number Diff line change
Expand Up @@ -271,18 +271,129 @@ public static long DivRem(long a, long b, out long result)
return div;
}

internal static uint DivRem(uint a, uint b, out uint result)
/// <summary>Produces the quotient and the remainder of two signed 8-bit numbers.</summary>
/// <param name="left">The dividend.</param>
/// <param name="right">The divisor.</param>
/// <returns>The quotient and the remainder of the specified numbers.</returns>
[NonVersionable]
[CLSCompliant(false)]
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static (sbyte Quotient, sbyte Remainder) DivRem(sbyte left, sbyte right)
{
uint div = a / b;
result = a - (div * b);
return div;
sbyte quotient = (sbyte)(left / right);
return (quotient, (sbyte)(left - (quotient * right)));
}

/// <summary>Produces the quotient and the remainder of two unsigned 8-bit numbers.</summary>
/// <param name="left">The dividend.</param>
/// <param name="right">The divisor.</param>
/// <returns>The quotient and the remainder of the specified numbers.</returns>
[NonVersionable]
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static (byte Quotient, byte Remainder) DivRem(byte left, byte right)
{
byte quotient = (byte)(left / right);
return (quotient, (byte)(left - (quotient * right)));
}

internal static ulong DivRem(ulong a, ulong b, out ulong result)
/// <summary>Produces the quotient and the remainder of two signed 16-bit numbers.</summary>
/// <param name="left">The dividend.</param>
/// <param name="right">The divisor.</param>
/// <returns>The quotient and the remainder of the specified numbers.</returns>
[NonVersionable]
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static (short Quotient, short Remainder) DivRem(short left, short right)
{
ulong div = a / b;
result = a - (div * b);
return div;
short quotient = (short)(left / right);
return (quotient, (short)(left - (quotient * right)));
}

/// <summary>Produces the quotient and the remainder of two unsigned 16-bit numbers.</summary>
/// <param name="left">The dividend.</param>
/// <param name="right">The divisor.</param>
/// <returns>The quotient and the remainder of the specified numbers.</returns>
[NonVersionable]
[CLSCompliant(false)]
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static (ushort Quotient, ushort Remainder) DivRem(ushort left, ushort right)
{
ushort quotient = (ushort)(left / right);
return (quotient, (ushort)(left - (quotient * right)));
}

/// <summary>Produces the quotient and the remainder of two signed 32-bit numbers.</summary>
/// <param name="left">The dividend.</param>
/// <param name="right">The divisor.</param>
/// <returns>The quotient and the remainder of the specified numbers.</returns>
[NonVersionable]
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static (int Quotient, int Remainder) DivRem(int left, int right)
{
int quotient = left / right;
return (quotient, left - (quotient * right));
}

/// <summary>Produces the quotient and the remainder of two unsigned 32-bit numbers.</summary>
/// <param name="left">The dividend.</param>
/// <param name="right">The divisor.</param>
/// <returns>The quotient and the remainder of the specified numbers.</returns>
[NonVersionable]
[CLSCompliant(false)]
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static (uint Quotient, uint Remainder) DivRem(uint left, uint right)
{
uint quotient = left / right;
return (quotient, left - (quotient * right));
}

/// <summary>Produces the quotient and the remainder of two signed 64-bit numbers.</summary>
/// <param name="left">The dividend.</param>
/// <param name="right">The divisor.</param>
/// <returns>The quotient and the remainder of the specified numbers.</returns>
[NonVersionable]
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static (long Quotient, long Remainder) DivRem(long left, long right)
{
long quotient = left / right;
return (quotient, left - (quotient * right));
}

/// <summary>Produces the quotient and the remainder of two unsigned 64-bit numbers.</summary>
/// <param name="left">The dividend.</param>
/// <param name="right">The divisor.</param>
/// <returns>The quotient and the remainder of the specified numbers.</returns>
[NonVersionable]
[CLSCompliant(false)]
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static (ulong Quotient, ulong Remainder) DivRem(ulong left, ulong right)
{
ulong quotient = left / right;
return (quotient, left - (quotient * right));
}

/// <summary>Produces the quotient and the remainder of two signed native-size numbers.</summary>
/// <param name="left">The dividend.</param>
/// <param name="right">The divisor.</param>
/// <returns>The quotient and the remainder of the specified numbers.</returns>
[NonVersionable]
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static (nint Quotient, nint Remainder) DivRem(nint left, nint right)
{
nint quotient = left / right;
return (quotient, left - (quotient * right));
}

/// <summary>Produces the quotient and the remainder of two unsigned native-size numbers.</summary>
/// <param name="left">The dividend.</param>
/// <param name="right">The divisor.</param>
/// <returns>The quotient and the remainder of the specified numbers.</returns>
[NonVersionable]
[CLSCompliant(false)]
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static (nuint Quotient, nuint Remainder) DivRem(nuint left, nuint right)
{
nuint quotient = left / right;
return (quotient, left - (quotient * right));
}

[MethodImpl(MethodImplOptions.AggressiveInlining)]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -446,7 +446,7 @@ public static void DivRem(ref BigInteger lhs, ref BigInteger rhs, out BigInteger

if ((lhsLength == 1) && (rhsLength == 1))
{
uint quotient = Math.DivRem(lhs._blocks[0], rhs._blocks[0], out uint remainder);
(uint quotient, uint remainder) = Math.DivRem(lhs._blocks[0], rhs._blocks[0]);
SetUInt32(out quo, quotient);
SetUInt32(out rem, remainder);
return;
Expand All @@ -464,7 +464,8 @@ public static void DivRem(ref BigInteger lhs, ref BigInteger rhs, out BigInteger
for (int i = quoLength - 1; i >= 0; i--)
{
ulong value = (carry << 32) | lhs._blocks[i];
ulong digit = Math.DivRem(value, rhsValue, out carry);
ulong digit;
(digit, carry) = Math.DivRem(value, rhsValue);

if ((digit == 0) && (i == (quoLength - 1)))
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1334,7 +1334,8 @@ private static unsafe void UInt32ToNumber(uint value, ref NumberBuffer number)
{
while (--digits >= 0 || value != 0)
{
value = Math.DivRem(value, 10, out uint remainder);
uint remainder;
(value, remainder) = Math.DivRem(value, 10);
*(--bufferEnd) = (byte)(remainder + '0');
}
return bufferEnd;
Expand All @@ -1344,7 +1345,8 @@ private static unsafe void UInt32ToNumber(uint value, ref NumberBuffer number)
{
while (--digits >= 0 || value != 0)
{
value = Math.DivRem(value, 10, out uint remainder);
uint remainder;
(value, remainder) = Math.DivRem(value, 10);
*(--bufferEnd) = (char)(remainder + '0');
}
return bufferEnd;
Expand All @@ -1367,7 +1369,8 @@ internal static unsafe string UInt32ToDecStr(uint value)
char* p = buffer + bufferLength;
do
{
value = Math.DivRem(value, 10, out uint remainder);
uint remainder;
(value, remainder) = Math.DivRem(value, 10);
*(--p) = (char)(remainder + '0');
}
while (value != 0);
Expand Down Expand Up @@ -1409,7 +1412,8 @@ private static unsafe bool TryUInt32ToDecStr(uint value, int digits, Span<char>
{
do
{
value = Math.DivRem(value, 10, out uint remainder);
uint remainder;
(value, remainder) = Math.DivRem(value, 10);
*(--p) = (char)(remainder + '0');
}
while (value != 0);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -624,7 +624,8 @@ private static bool TryDigitGenCounted(in DiyFp w, int requestedDigits, Span<byt
// The divisor is the biggest power of ten that is smaller than integrals
while (kappa > 0)
{
uint digit = Math.DivRem(integrals, divisor, out integrals);
uint digit;
(digit, integrals) = Math.DivRem(integrals, divisor);
Debug.Assert(digit <= 9);
buffer[length] = (byte)('0' + digit);

Expand Down Expand Up @@ -802,7 +803,8 @@ private static bool TryDigitGenShortest(in DiyFp low, in DiyFp w, in DiyFp high,
// The divisor is the biggest power of ten that is smaller than integrals
while (kappa > 0)
{
uint digit = Math.DivRem(integrals, divisor, out integrals);
uint digit;
(digit, integrals) = Math.DivRem(integrals, divisor);
Debug.Assert(digit <= 9);
buffer[length] = (byte)('0' + digit);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -261,7 +261,7 @@ private static ulong ConvertBigIntegerToFloatingPointBits(ref BigInteger value,
return AssembleFloatingPointBits(in info, value.ToUInt64(), baseExponent, !hasNonZeroFractionalPart);
}

uint topBlockIndex = Math.DivRem(integerBitsOfPrecision, 32, out uint topBlockBits);
(uint topBlockIndex, uint topBlockBits) = Math.DivRem(integerBitsOfPrecision, 32);
uint middleBlockIndex = topBlockIndex - 1;
uint bottomBlockIndex = middleBlockIndex - 1;

Expand Down
Loading