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

Use DivRem in Decimal.DecCalc #97619

Merged
merged 2 commits into from
Jan 30, 2024
Merged
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
77 changes: 32 additions & 45 deletions src/libraries/System.Private.CoreLib/src/System/Decimal.DecCalc.cs
Original file line number Diff line number Diff line change
Expand Up @@ -232,20 +232,20 @@ private static bool Div96ByConst(ref ulong high64, ref uint low, uint pow)
#else
// 32-bit RyuJIT doesn't convert 64-bit division by constant into multiplication by reciprocal. Do half-width divisions instead.
Debug.Assert(pow <= ushort.MaxValue);
uint num, mid32, low16, div;
uint num, mid32, low16, div, rem;
if (high64 <= uint.MaxValue)
{
num = (uint)high64;
mid32 = num / pow;
num = (num - mid32 * pow) << 16;
(mid32, rem) = Math.DivRem(num, pow);
num = rem << 16;

num += low >> 16;
low16 = num / pow;
num = (num - low16 * pow) << 16;
(low16, rem) = Math.DivRem(num, pow);
num = rem << 16;

num += (ushort)low;
div = num / pow;
if (num == div * pow)
(div, rem) = Math.DivRem(num, pow);
if (rem == 0)
{
high64 = mid32;
low = (low16 << 16) + div;
Expand All @@ -255,25 +255,25 @@ private static bool Div96ByConst(ref ulong high64, ref uint low, uint pow)
else
{
num = (uint)(high64 >> 32);
uint high32 = num / pow;
num = (num - high32 * pow) << 16;
(uint high32, rem) = Math.DivRem(num, pow);
num = rem << 16;

num += (uint)high64 >> 16;
mid32 = num / pow;
num = (num - mid32 * pow) << 16;
(mid32, rem) = Math.DivRem(num, pow);
num = rem << 16;

num += (ushort)high64;
div = num / pow;
num = (num - div * pow) << 16;
(div, rem) = Math.DivRem(num, pow);
num = rem << 16;
mid32 = div + (mid32 << 16);

num += low >> 16;
low16 = num / pow;
num = (num - low16 * pow) << 16;
(low16, rem) = Math.DivRem(num, pow);
num = rem << 16;

num += (ushort)low;
div = num / pow;
if (num == div * pow)
(div, rem) = Math.DivRem(num, pow);
if (rem == 0)
{
high64 = ((ulong)high32 << 32) | mid32;
low = (low16 << 16) + div;
Expand Down Expand Up @@ -322,7 +322,6 @@ private static void Unscale(ref uint low, ref ulong high64, ref int scale)
private static uint Div96By64(ref Buf12 bufNum, ulong den)
{
Debug.Assert(den > bufNum.High64);
uint quo;
ulong num;
uint num2 = bufNum.U2;
if (num2 == 0)
Expand All @@ -332,13 +331,11 @@ private static uint Div96By64(ref Buf12 bufNum, ulong den)
// Result is zero. Entire dividend is remainder.
return 0;

// TODO: https://github.com/dotnet/runtime/issues/5213
quo = (uint)(num / den);
num -= quo * den; // remainder
bufNum.Low64 = num;
return quo;
(ulong quo64, bufNum.Low64) = Math.DivRem(num, den);
return (uint)quo64;
}

uint quo;
uint denHigh32 = (uint)(den >> 32);
if (num2 >= denHigh32)
{
Expand Down Expand Up @@ -674,7 +671,7 @@ private static unsafe int ScaleResult(Buf24* bufRes, uint hiRes, int scale)
private static unsafe uint DivByConst(uint* result, uint hiRes, out uint quotient, out uint remainder, uint power)
{
uint high = result[hiRes];
remainder = high - (quotient = high / power) * power;
(quotient, remainder) = Math.DivRem(high, power);
for (uint i = hiRes - 1; (int)i >= 0; i--)
{
#if TARGET_64BIT
Expand All @@ -690,13 +687,11 @@ private static unsafe uint DivByConst(uint* result, uint hiRes, out uint quotien
#endif
// byte* is used here because Roslyn doesn't do constant propagation for pointer arithmetic
uint num = *(ushort*)((byte*)result + i * 4 + high16) + (remainder << 16);
uint div = num / power;
remainder = num - div * power;
(uint div, remainder) = Math.DivRem(num, power);
*(ushort*)((byte*)result + i * 4 + high16) = (ushort)div;

num = *(ushort*)((byte*)result + i * 4 + low16) + (remainder << 16);
div = num / power;
remainder = num - div * power;
(div, remainder) = Math.DivRem(num, power);
*(ushort*)((byte*)result + i * 4 + low16) = (ushort)div;
#endif
}
Expand Down Expand Up @@ -1332,10 +1327,7 @@ internal static unsafe void VarDecMul(ref DecCalc d1, ref DecCalc d2)
scale -= DEC_SCALE_MAX + 1;
ulong power = UInt64Powers10[scale];

// TODO: https://github.com/dotnet/runtime/issues/5213
tmp = low64 / power;
ulong remainder = low64 - tmp * power;
low64 = tmp;
(low64, ulong remainder) = Math.DivRem(low64, power);

// Round result. See if remainder >= 1/2 of divisor.
// Divisor is a power of 10, so it is always even.
Expand Down Expand Up @@ -1629,9 +1621,8 @@ internal static void VarDecFromR4(float input, out DecCalc result)

if ((mant & 0xF) == 0 && lmax >= 4)
{
const uint den = 10000;
uint div = mant / den;
if (mant == div * den)
(uint div, uint rem) = Math.DivRem(mant, 10000);
if (rem == 0)
{
mant = div;
power -= 4;
Expand All @@ -1641,9 +1632,8 @@ internal static void VarDecFromR4(float input, out DecCalc result)

if ((mant & 3) == 0 && lmax >= 2)
{
const uint den = 100;
uint div = mant / den;
if (mant == div * den)
(uint div, uint rem) = Math.DivRem(mant, 100);
if (rem == 0)
{
mant = div;
power -= 2;
Expand All @@ -1653,9 +1643,8 @@ internal static void VarDecFromR4(float input, out DecCalc result)

if ((mant & 1) == 0 && lmax >= 1)
{
const uint den = 10;
uint div = mant / den;
if (mant == div * den)
(uint div, uint rem) = Math.DivRem(mant, 10);
if (rem == 0)
{
mant = div;
power--;
Expand Down Expand Up @@ -2372,8 +2361,7 @@ internal static void InternalRound(ref DecCalc d, uint scale, MidpointRounding m
else
{
uint q;
d.uhi = q = n / divisor;
remainder = n - q * divisor;
(d.uhi, remainder) = Math.DivRem(n, divisor);
n = d.umid;
if ((n | remainder) != 0)
{
Expand Down Expand Up @@ -2414,8 +2402,7 @@ internal static void InternalRound(ref DecCalc d, uint scale, MidpointRounding m
else
{
uint q;
d.uhi = q = n / power;
remainder = n - q * power;
(d.uhi, remainder) = Math.DivRem(n, power);
n = d.umid;
if ((n | remainder) != 0)
{
Expand Down
Loading