@@ -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