@@ -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
@@ -3227,7 +3227,6 @@ public static BigInteger PopCount(BigInteger value)
3227
3227
3228
3228
part = ~ value . _bits [ i ] ;
3229
3229
result += uint . PopCount ( part ) ;
3230
-
3231
3230
i ++ ;
3232
3231
}
3233
3232
}
@@ -3239,267 +3238,89 @@ public static BigInteger PopCount(BigInteger value)
3239
3238
public static BigInteger RotateLeft ( BigInteger value , int rotateAmount )
3240
3239
{
3241
3240
value . AssertValid ( ) ;
3242
- int byteCount = ( value . _bits is null ) ? sizeof ( int ) : ( value . _bits . Length * 4 ) ;
3243
-
3244
- // Normalize the rotate amount to drop full rotations
3245
- rotateAmount = ( int ) ( rotateAmount % ( byteCount * 8L ) ) ;
3246
3241
3247
3242
if ( rotateAmount == 0 )
3248
3243
return value ;
3249
3244
3250
- if ( rotateAmount == int . MinValue )
3251
- return RotateRight ( RotateRight ( value , int . MaxValue ) , 1 ) ;
3252
-
3253
- if ( rotateAmount < 0 )
3254
- return RotateRight ( value , - rotateAmount ) ;
3255
-
3256
- ( int digitShift , int smallShift ) = Math . DivRem ( rotateAmount , kcbitUint ) ;
3257
-
3258
- uint [ ] ? xdFromPool = null ;
3259
- int xl = value . _bits ? . Length ?? 1 ;
3260
-
3261
- Span < uint > xd = ( xl <= BigIntegerCalculator . StackAllocThreshold )
3262
- ? stackalloc uint [ BigIntegerCalculator . StackAllocThreshold ]
3263
- : xdFromPool = ArrayPool < uint > . Shared . Rent ( xl ) ;
3264
- xd = xd . Slice ( 0 , xl ) ;
3265
-
3266
- bool negx = value . GetPartsForBitManipulation ( xd ) ;
3267
-
3268
- int zl = xl ;
3269
- uint [ ] ? zdFromPool = null ;
3270
-
3271
- Span < uint > zd = ( zl <= BigIntegerCalculator . StackAllocThreshold )
3272
- ? stackalloc uint [ BigIntegerCalculator . StackAllocThreshold ]
3273
- : zdFromPool = ArrayPool < uint > . Shared . Rent ( zl ) ;
3274
- zd = zd . Slice ( 0 , zl ) ;
3275
-
3276
- zd . Clear ( ) ;
3277
-
3278
- if ( negx )
3279
- {
3280
- NumericsHelpers . DangerousMakeTwosComplement ( xd ) ;
3281
- }
3282
-
3283
- if ( smallShift == 0 )
3284
- {
3285
- int dstIndex = 0 ;
3286
- int srcIndex = xd . Length - digitShift ;
3287
-
3288
- do
3289
- {
3290
- // Copy last digitShift elements from xd to the start of zd
3291
- zd [ dstIndex ] = xd [ srcIndex ] ;
3292
-
3293
- dstIndex ++ ;
3294
- srcIndex ++ ;
3295
- }
3296
- while ( srcIndex < xd . Length ) ;
3297
-
3298
- srcIndex = 0 ;
3299
-
3300
- while ( dstIndex < zd . Length )
3301
- {
3302
- // Copy remaining elements from start of xd to end of zd
3303
- zd [ dstIndex ] = xd [ srcIndex ] ;
3245
+ bool neg = value . _sign < 0 ;
3304
3246
3305
- dstIndex ++ ;
3306
- srcIndex ++ ;
3307
- }
3308
- }
3309
- else
3310
- {
3311
- int carryShift = kcbitUint - smallShift ;
3312
-
3313
- int dstIndex = 0 ;
3314
- int srcIndex = 0 ;
3315
-
3316
- uint carry = 0 ;
3317
-
3318
- if ( digitShift == 0 )
3319
- {
3320
- carry = xd [ ^ 1 ] >> carryShift ;
3321
- }
3322
- else
3323
- {
3324
- srcIndex = xd . Length - digitShift ;
3325
- carry = xd [ srcIndex - 1 ] >> carryShift ;
3326
- }
3327
-
3328
- do
3329
- {
3330
- uint part = xd [ srcIndex ] ;
3331
-
3332
- zd [ dstIndex ] = ( part << smallShift ) | carry ;
3333
- carry = part >> carryShift ;
3334
-
3335
- dstIndex ++ ;
3336
- srcIndex ++ ;
3337
- }
3338
- while ( srcIndex < xd . Length ) ;
3339
-
3340
- srcIndex = 0 ;
3341
-
3342
- while ( dstIndex < zd . Length )
3343
- {
3344
- uint part = xd [ srcIndex ] ;
3345
-
3346
- zd [ dstIndex ] = ( part << smallShift ) | carry ;
3347
- carry = part >> carryShift ;
3348
-
3349
- dstIndex ++ ;
3350
- srcIndex ++ ;
3351
- }
3352
- }
3353
-
3354
- if ( negx && ( int ) zd [ ^ 1 ] < 0 )
3355
- {
3356
- NumericsHelpers . DangerousMakeTwosComplement ( zd ) ;
3357
- }
3358
- else
3247
+ if ( value . _bits is null )
3359
3248
{
3360
- negx = false ;
3249
+ uint rs = BitOperations . RotateLeft ( ( uint ) value . _sign , rotateAmount ) ;
3250
+ return neg
3251
+ ? new BigInteger ( ( int ) rs )
3252
+ : new BigInteger ( rs ) ;
3361
3253
}
3362
3254
3363
- var result = new BigInteger ( zd , negx ) ;
3364
-
3365
- if ( xdFromPool != null )
3366
- ArrayPool < uint > . Shared . Return ( xdFromPool ) ;
3367
- if ( zdFromPool != null )
3368
- ArrayPool < uint > . Shared . Return ( zdFromPool ) ;
3369
-
3370
- return result ;
3255
+ return Rotate ( value . _bits , neg , rotateAmount ) ;
3371
3256
}
3372
3257
3373
3258
/// <inheritdoc cref="IBinaryInteger{TSelf}.RotateRight(TSelf, int)" />
3374
3259
public static BigInteger RotateRight ( BigInteger value , int rotateAmount )
3375
3260
{
3376
3261
value . AssertValid ( ) ;
3377
- int byteCount = ( value . _bits is null ) ? sizeof ( int ) : ( value . _bits . Length * 4 ) ;
3378
-
3379
- // Normalize the rotate amount to drop full rotations
3380
- rotateAmount = ( int ) ( rotateAmount % ( byteCount * 8L ) ) ;
3381
3262
3382
3263
if ( rotateAmount == 0 )
3383
3264
return value ;
3384
3265
3385
- if ( rotateAmount == int . MinValue )
3386
- return RotateLeft ( RotateLeft ( value , int . MaxValue ) , 1 ) ;
3387
-
3388
- if ( rotateAmount < 0 )
3389
- return RotateLeft ( value , - rotateAmount ) ;
3390
-
3391
- ( int digitShift , int smallShift ) = Math . DivRem ( rotateAmount , kcbitUint ) ;
3266
+ bool neg = value . _sign < 0 ;
3392
3267
3393
- uint [ ] ? xdFromPool = null ;
3394
- int xl = value . _bits ? . Length ?? 1 ;
3395
-
3396
- Span < uint > xd = ( xl <= BigIntegerCalculator . StackAllocThreshold )
3397
- ? stackalloc uint [ BigIntegerCalculator . StackAllocThreshold ]
3398
- : xdFromPool = ArrayPool < uint > . Shared . Rent ( xl ) ;
3399
- xd = xd . Slice ( 0 , xl ) ;
3400
-
3401
- bool negx = value . GetPartsForBitManipulation ( xd ) ;
3402
-
3403
- int zl = xl ;
3404
- uint [ ] ? zdFromPool = null ;
3405
-
3406
- Span < uint > zd = ( zl <= BigIntegerCalculator . StackAllocThreshold )
3407
- ? stackalloc uint [ BigIntegerCalculator . StackAllocThreshold ]
3408
- : zdFromPool = ArrayPool < uint > . Shared . Rent ( zl ) ;
3409
- zd = zd . Slice ( 0 , zl ) ;
3410
-
3411
- zd . Clear ( ) ;
3412
-
3413
- if ( negx )
3268
+ if ( value . _bits is null )
3414
3269
{
3415
- NumericsHelpers . DangerousMakeTwosComplement ( xd ) ;
3270
+ uint rs = BitOperations . RotateRight ( ( uint ) value . _sign , rotateAmount ) ;
3271
+ return neg
3272
+ ? new BigInteger ( ( int ) rs )
3273
+ : new BigInteger ( rs ) ;
3416
3274
}
3417
3275
3418
- if ( smallShift == 0 )
3419
- {
3420
- int dstIndex = 0 ;
3421
- int srcIndex = digitShift ;
3422
-
3423
- do
3424
- {
3425
- // Copy first digitShift elements from xd to the end of zd
3426
- zd [ dstIndex ] = xd [ srcIndex ] ;
3427
-
3428
- dstIndex ++ ;
3429
- srcIndex ++ ;
3430
- }
3431
- while ( srcIndex < xd . Length ) ;
3432
-
3433
- srcIndex = 0 ;
3434
-
3435
- while ( dstIndex < zd . Length )
3436
- {
3437
- // Copy remaining elements from end of xd to start of zd
3438
- zd [ dstIndex ] = xd [ srcIndex ] ;
3439
-
3440
- dstIndex ++ ;
3441
- srcIndex ++ ;
3442
- }
3443
- }
3444
- else
3445
- {
3446
- int carryShift = kcbitUint - smallShift ;
3447
-
3448
- int dstIndex = 0 ;
3449
- int srcIndex = digitShift ;
3450
-
3451
- uint carry = 0 ;
3452
-
3453
- if ( digitShift == 0 )
3454
- {
3455
- carry = xd [ ^ 1 ] << carryShift ;
3456
- }
3457
- else
3458
- {
3459
- carry = xd [ srcIndex - 1 ] << carryShift ;
3460
- }
3276
+ return Rotate ( value . _bits , neg , - ( long ) rotateAmount ) ;
3277
+ }
3461
3278
3462
- do
3463
- {
3464
- uint part = xd [ srcIndex ] ;
3279
+ private static BigInteger Rotate ( ReadOnlySpan < uint > bits , bool negative , long rotateLeftAmount )
3280
+ {
3281
+ Debug . Assert ( bits . Length > 0 ) ;
3282
+ Debug . Assert ( Math . Abs ( rotateLeftAmount ) <= 0x80000000 ) ;
3465
3283
3466
- zd [ dstIndex ] = ( part >> smallShift ) | carry ;
3467
- carry = part << carryShift ;
3284
+ int zLength = bits . Length ;
3285
+ int leadingZeroCount = negative ? bits . IndexOfAnyExcept ( 0u ) : 0 ;
3468
3286
3469
- dstIndex ++ ;
3470
- srcIndex ++ ;
3471
- }
3472
- while ( srcIndex < xd . Length ) ;
3287
+ if ( negative && bits [ ^ 1 ] >= kuMaskHighBit
3288
+ && ! ( leadingZeroCount == bits . Length - 1 && bits [ ^ 1 ] == kuMaskHighBit ) )
3289
+ ++ zLength ;
3473
3290
3474
- srcIndex = 0 ;
3291
+ uint [ ] ? zFromPool = null ;
3292
+ Span < uint > zd = ( ( uint ) zLength <= BigIntegerCalculator . StackAllocThreshold
3293
+ ? stackalloc uint [ BigIntegerCalculator . StackAllocThreshold ]
3294
+ : zFromPool = ArrayPool < uint > . Shared . Rent ( zLength ) ) . Slice ( 0 , zLength ) ;
3475
3295
3476
- while ( dstIndex < zd . Length )
3477
- {
3478
- uint part = xd [ srcIndex ] ;
3296
+ zd [ ^ 1 ] = 0 ;
3297
+ bits . CopyTo ( zd ) ;
3479
3298
3480
- zd [ dstIndex ] = ( part >> smallShift ) | carry ;
3481
- carry = part << carryShift ;
3299
+ if ( negative )
3300
+ {
3301
+ Debug . Assert ( ( uint ) leadingZeroCount < ( uint ) zd . Length ) ;
3482
3302
3483
- dstIndex ++ ;
3484
- srcIndex ++ ;
3485
- }
3303
+ // Same as NumericsHelpers.DangerousMakeTwosComplement(zd);
3304
+ // Leading zero count are already calculated.
3305
+ zd [ leadingZeroCount ] = ( uint ) ( - ( int ) zd [ leadingZeroCount ] ) ;
3306
+ NumericsHelpers . DangerousMakeOnesComplement ( zd . Slice ( leadingZeroCount + 1 ) ) ;
3486
3307
}
3487
3308
3488
- if ( negx && ( int ) zd [ ^ 1 ] < 0 )
3309
+ BigIntegerCalculator . RotateLeft ( zd , rotateLeftAmount ) ;
3310
+
3311
+ if ( negative && ( int ) zd [ ^ 1 ] < 0 )
3489
3312
{
3490
3313
NumericsHelpers . DangerousMakeTwosComplement ( zd ) ;
3491
3314
}
3492
3315
else
3493
3316
{
3494
- negx = false ;
3317
+ negative = false ;
3495
3318
}
3496
3319
3497
- var result = new BigInteger ( zd , negx ) ;
3320
+ var result = new BigInteger ( zd , negative ) ;
3498
3321
3499
- if ( xdFromPool != null )
3500
- ArrayPool < uint > . Shared . Return ( xdFromPool ) ;
3501
- if ( zdFromPool != null )
3502
- ArrayPool < uint > . Shared . Return ( zdFromPool ) ;
3322
+ if ( zFromPool != null )
3323
+ ArrayPool < uint > . Shared . Return ( zFromPool ) ;
3503
3324
3504
3325
return result ;
3505
3326
}
0 commit comments