Skip to content

Commit a65b9c4

Browse files
committed
Add comment
1 parent aee797d commit a65b9c4

File tree

1 file changed

+20
-8
lines changed
  • src/libraries/System.Runtime.Numerics/src/System/Numerics

1 file changed

+20
-8
lines changed

src/libraries/System.Runtime.Numerics/src/System/Numerics/BigInteger.cs

Lines changed: 20 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3247,11 +3247,17 @@ public static BigInteger RotateLeft(BigInteger value, int rotateAmount)
32473247
{
32483248
bits = new ReadOnlySpan<uint>(in smallBits);
32493249
}
3250-
int xl = bits.Length;
32513250

3252-
if (negx && bits[^1] >= kuMaskHighBit
3253-
&& !(bits.IndexOfAnyExcept(0u) == bits.Length - 1 && bits[^1] == kuMaskHighBit))
3251+
int xl = bits.Length;
3252+
if (negx && (bits[^1] >= kuMaskHighBit) && ((bits[^1] != kuMaskHighBit) || bits.IndexOfAnyExcept(0u) != (bits.Length - 1)))
3253+
{
3254+
// We check for a special case where its sign bit could be outside the uint array after 2's complement conversion.
3255+
// For example given [0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF], its 2's complement is [0x01, 0x00, 0x00]
3256+
// After a 32 bit right shift, it becomes [0x00, 0x00] which is [0x00, 0x00] when converted back.
3257+
// The expected result is [0x00, 0x00, 0xFFFFFFFF] (2's complement) or [0x00, 0x00, 0x01] when converted back
3258+
// If the 2's component's last element is a 0, we will track the sign externally
32543259
++xl;
3260+
}
32553261

32563262
int byteCount = xl * 4;
32573263

@@ -3396,11 +3402,17 @@ public static BigInteger RotateRight(BigInteger value, int rotateAmount)
33963402
{
33973403
bits = new ReadOnlySpan<uint>(in smallBits);
33983404
}
3399-
int xl = bits.Length;
34003405

3401-
if (negx && bits[^1] >= kuMaskHighBit
3402-
&& !(bits.IndexOfAnyExcept(0u) == bits.Length - 1 && bits[^1] == kuMaskHighBit))
3406+
int xl = bits.Length;
3407+
if (negx && (bits[^1] >= kuMaskHighBit) && ((bits[^1] != kuMaskHighBit) || bits.IndexOfAnyExcept(0u) != (bits.Length - 1)))
3408+
{
3409+
// We check for a special case where its sign bit could be outside the uint array after 2's complement conversion.
3410+
// For example given [0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF], its 2's complement is [0x01, 0x00, 0x00]
3411+
// After a 32 bit right shift, it becomes [0x00, 0x00] which is [0x00, 0x00] when converted back.
3412+
// The expected result is [0x00, 0x00, 0xFFFFFFFF] (2's complement) or [0x00, 0x00, 0x01] when converted back
3413+
// If the 2's component's last element is a 0, we will track the sign externally
34033414
++xl;
3415+
}
34043416

34053417
int byteCount = xl * 4;
34063418

@@ -3489,11 +3501,11 @@ public static BigInteger RotateRight(BigInteger value, int rotateAmount)
34893501
dstIndex--;
34903502
srcIndex--;
34913503
}
3492-
while ((uint)srcIndex < (uint)xd.Length);
3504+
while ((uint)srcIndex < (uint)xd.Length); // is equivalent to (srcIndex >= 0 && srcIndex < xd.Length)
34933505

34943506
srcIndex = xd.Length - 1;
34953507

3496-
while ((uint)dstIndex < (uint)zd.Length)
3508+
while ((uint)dstIndex < (uint)zd.Length) // is equivalent to (dstIndex >= 0 && dstIndex < zd.Length)
34973509
{
34983510
uint part = xd[srcIndex];
34993511

0 commit comments

Comments
 (0)