@@ -1701,7 +1701,7 @@ private static BigInteger Add(ReadOnlySpan<uint> leftBits, int leftSign, ReadOnl
1701
1701
}
1702
1702
1703
1703
if ( bitsFromPool != null )
1704
- ArrayPool < uint > . Shared . Return ( bitsFromPool ) ;
1704
+ ArrayPool < uint > . Shared . Return ( bitsFromPool ) ;
1705
1705
1706
1706
return result ;
1707
1707
}
@@ -2636,7 +2636,7 @@ public static implicit operator BigInteger(nuint value)
2636
2636
2637
2637
if ( zdFromPool != null )
2638
2638
ArrayPool < uint > . Shared . Return ( zdFromPool ) ;
2639
- exit :
2639
+ exit :
2640
2640
if ( xdFromPool != null )
2641
2641
ArrayPool < uint > . Shared . Return ( xdFromPool ) ;
2642
2642
@@ -3239,7 +3239,16 @@ public static BigInteger PopCount(BigInteger value)
3239
3239
public static BigInteger RotateLeft ( BigInteger value , int rotateAmount )
3240
3240
{
3241
3241
value . AssertValid ( ) ;
3242
- int byteCount = ( value . _bits is null ) ? sizeof ( int ) : ( value . _bits . Length * 4 ) ;
3242
+
3243
+ bool negx = value . _sign < 0 ;
3244
+ ReadOnlySpan < uint > bits = value . _bits ?? stackalloc uint [ 1 ] { NumericsHelpers . Abs ( value . _sign ) } ;
3245
+ int xl = bits . Length ;
3246
+
3247
+ if ( negx && bits [ ^ 1 ] >= kuMaskHighBit
3248
+ && ! ( bits . IndexOfAnyExcept ( 0u ) == bits . Length - 1 && bits [ ^ 1 ] == kuMaskHighBit ) )
3249
+ ++ xl ;
3250
+
3251
+ int byteCount = xl * 4 ;
3243
3252
3244
3253
// Normalize the rotate amount to drop full rotations
3245
3254
rotateAmount = ( int ) ( rotateAmount % ( byteCount * 8L ) ) ;
@@ -3256,14 +3265,13 @@ public static BigInteger RotateLeft(BigInteger value, int rotateAmount)
3256
3265
( int digitShift , int smallShift ) = Math . DivRem ( rotateAmount , kcbitUint ) ;
3257
3266
3258
3267
uint [ ] ? xdFromPool = null ;
3259
- int xl = value . _bits ? . Length ?? 1 ;
3260
-
3261
3268
Span < uint > xd = ( xl <= BigIntegerCalculator . StackAllocThreshold )
3262
3269
? stackalloc uint [ BigIntegerCalculator . StackAllocThreshold ]
3263
3270
: xdFromPool = ArrayPool < uint > . Shared . Rent ( xl ) ;
3264
3271
xd = xd . Slice ( 0 , xl ) ;
3272
+ xd [ ^ 1 ] = 0 ;
3265
3273
3266
- bool negx = value . GetPartsForBitManipulation ( xd ) ;
3274
+ bits . CopyTo ( xd ) ;
3267
3275
3268
3276
int zl = xl ;
3269
3277
uint [ ] ? zdFromPool = null ;
@@ -3374,7 +3382,17 @@ public static BigInteger RotateLeft(BigInteger value, int rotateAmount)
3374
3382
public static BigInteger RotateRight ( BigInteger value , int rotateAmount )
3375
3383
{
3376
3384
value . AssertValid ( ) ;
3377
- int byteCount = ( value . _bits is null ) ? sizeof ( int ) : ( value . _bits . Length * 4 ) ;
3385
+
3386
+
3387
+ bool negx = value . _sign < 0 ;
3388
+ ReadOnlySpan < uint > bits = value . _bits ?? stackalloc uint [ 1 ] { NumericsHelpers . Abs ( value . _sign ) } ;
3389
+ int xl = bits . Length ;
3390
+
3391
+ if ( negx && bits [ ^ 1 ] >= kuMaskHighBit
3392
+ && ! ( bits . IndexOfAnyExcept ( 0u ) == bits . Length - 1 && bits [ ^ 1 ] == kuMaskHighBit ) )
3393
+ ++ xl ;
3394
+
3395
+ int byteCount = xl * 4 ;
3378
3396
3379
3397
// Normalize the rotate amount to drop full rotations
3380
3398
rotateAmount = ( int ) ( rotateAmount % ( byteCount * 8L ) ) ;
@@ -3391,14 +3409,13 @@ public static BigInteger RotateRight(BigInteger value, int rotateAmount)
3391
3409
( int digitShift , int smallShift ) = Math . DivRem ( rotateAmount , kcbitUint ) ;
3392
3410
3393
3411
uint [ ] ? xdFromPool = null ;
3394
- int xl = value . _bits ? . Length ?? 1 ;
3395
-
3396
3412
Span < uint > xd = ( xl <= BigIntegerCalculator . StackAllocThreshold )
3397
3413
? stackalloc uint [ BigIntegerCalculator . StackAllocThreshold ]
3398
3414
: xdFromPool = ArrayPool < uint > . Shared . Rent ( xl ) ;
3399
3415
xd = xd . Slice ( 0 , xl ) ;
3416
+ xd [ ^ 1 ] = 0 ;
3400
3417
3401
- bool negx = value . GetPartsForBitManipulation ( xd ) ;
3418
+ bits . CopyTo ( xd ) ;
3402
3419
3403
3420
int zl = xl ;
3404
3421
uint [ ] ? zdFromPool = null ;
@@ -3445,19 +3462,12 @@ public static BigInteger RotateRight(BigInteger value, int rotateAmount)
3445
3462
{
3446
3463
int carryShift = kcbitUint - smallShift ;
3447
3464
3448
- int dstIndex = 0 ;
3449
- int srcIndex = digitShift ;
3450
-
3451
- uint carry = 0 ;
3465
+ int dstIndex = xd . Length - 1 ;
3466
+ int srcIndex = digitShift == 0
3467
+ ? xd . Length - 1
3468
+ : digitShift - 1 ;
3452
3469
3453
- if ( digitShift == 0 )
3454
- {
3455
- carry = xd [ ^ 1 ] << carryShift ;
3456
- }
3457
- else
3458
- {
3459
- carry = xd [ srcIndex - 1 ] << carryShift ;
3460
- }
3470
+ uint carry = xd [ digitShift ] << carryShift ;
3461
3471
3462
3472
do
3463
3473
{
@@ -3466,22 +3476,22 @@ public static BigInteger RotateRight(BigInteger value, int rotateAmount)
3466
3476
zd [ dstIndex ] = ( part >> smallShift ) | carry ;
3467
3477
carry = part << carryShift ;
3468
3478
3469
- dstIndex ++ ;
3470
- srcIndex ++ ;
3479
+ dstIndex -- ;
3480
+ srcIndex -- ;
3471
3481
}
3472
- while ( srcIndex < xd . Length ) ;
3482
+ while ( ( uint ) srcIndex < ( uint ) xd . Length ) ;
3473
3483
3474
- srcIndex = 0 ;
3484
+ srcIndex = xd . Length - 1 ;
3475
3485
3476
- while ( dstIndex < zd . Length )
3486
+ while ( ( uint ) dstIndex < ( uint ) zd . Length )
3477
3487
{
3478
3488
uint part = xd [ srcIndex ] ;
3479
3489
3480
3490
zd [ dstIndex ] = ( part >> smallShift ) | carry ;
3481
3491
carry = part << carryShift ;
3482
3492
3483
- dstIndex ++ ;
3484
- srcIndex ++ ;
3493
+ dstIndex -- ;
3494
+ srcIndex -- ;
3485
3495
}
3486
3496
}
3487
3497
0 commit comments