Skip to content

Commit

Permalink
Fix the handling of UInt128.DivideSlow on big endian platforms (#71162)
Browse files Browse the repository at this point in the history
  • Loading branch information
tannergooding authored Jun 22, 2022
1 parent 08c0ea1 commit ccf1257
Showing 1 changed file with 22 additions and 2 deletions.
24 changes: 22 additions & 2 deletions src/libraries/System.Private.CoreLib/src/System/UInt128.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1041,12 +1041,32 @@ unsafe static UInt128 DivideSlow(UInt128 quotient, UInt128 divisor)
// we need to get a Span<uint> containing the value represented
// in the least number of elements possible.

// We need to ensure that we end up with 4x uints representing the bits from
// least significant to most significant so the math will be correct on both
// little and big endian systems. So we'll just allocate the relevant buffer
// space and then write out the four parts using the native endianness of the
// system.

uint* pLeft = stackalloc uint[Size / sizeof(uint)];
quotient.WriteLittleEndianUnsafe(new Span<byte>(pLeft, Size));

Unsafe.WriteUnaligned(ref *(byte*)(pLeft + 0), (uint)(quotient._lower >> 00));
Unsafe.WriteUnaligned(ref *(byte*)(pLeft + 1), (uint)(quotient._lower >> 32));

Unsafe.WriteUnaligned(ref *(byte*)(pLeft + 2), (uint)(quotient._upper >> 00));
Unsafe.WriteUnaligned(ref *(byte*)(pLeft + 3), (uint)(quotient._upper >> 32));

Span<uint> left = new Span<uint>(pLeft, (Size / sizeof(uint)) - (BitOperations.LeadingZeroCount(quotient) / 32));

// Repeat the same operation with the divisor

uint* pRight = stackalloc uint[Size / sizeof(uint)];
divisor.WriteLittleEndianUnsafe(new Span<byte>(pRight, Size));

Unsafe.WriteUnaligned(ref *(byte*)(pRight + 0), (uint)(divisor._lower >> 00));
Unsafe.WriteUnaligned(ref *(byte*)(pRight + 1), (uint)(divisor._lower >> 32));

Unsafe.WriteUnaligned(ref *(byte*)(pRight + 2), (uint)(divisor._upper >> 00));
Unsafe.WriteUnaligned(ref *(byte*)(pRight + 3), (uint)(divisor._upper >> 32));

Span<uint> right = new Span<uint>(pRight, (Size / sizeof(uint)) - (BitOperations.LeadingZeroCount(divisor) / 32));

Span<uint> rawBits = stackalloc uint[Size / sizeof(uint)];
Expand Down

0 comments on commit ccf1257

Please sign in to comment.