@@ -382,42 +382,6 @@ impl RemLimb for BoxedUint {
382
382
}
383
383
}
384
384
385
- /// Computes `limbs << shift` inplace, where `0 <= shift < Limb::BITS`, returning the carry.
386
- fn shl_limb_vartime ( limbs : & mut [ Limb ] , shift : u32 ) -> Limb {
387
- if shift == 0 {
388
- return Limb :: ZERO ;
389
- }
390
-
391
- let lshift = shift;
392
- let rshift = Limb :: BITS - shift;
393
- let limbs_num = limbs. len ( ) ;
394
-
395
- let carry = limbs[ limbs_num - 1 ] >> rshift;
396
- for i in ( 1 ..limbs_num) . rev ( ) {
397
- limbs[ i] = ( limbs[ i] << lshift) | ( limbs[ i - 1 ] >> rshift) ;
398
- }
399
- limbs[ 0 ] <<= lshift;
400
-
401
- carry
402
- }
403
-
404
- /// Computes `limbs >> shift` inplace, where `0 <= shift < Limb::BITS`.
405
- fn shr_limb_vartime ( limbs : & mut [ Limb ] , shift : u32 ) {
406
- if shift == 0 {
407
- return ;
408
- }
409
-
410
- let lshift = Limb :: BITS - shift;
411
- let rshift = shift;
412
-
413
- let limbs_num = limbs. len ( ) ;
414
-
415
- for i in 0 ..limbs_num - 1 {
416
- limbs[ i] = ( limbs[ i] >> rshift) | ( limbs[ i + 1 ] << lshift) ;
417
- }
418
- limbs[ limbs_num - 1 ] >>= rshift;
419
- }
420
-
421
385
/// Computes `x` / `y`, returning the quotient in `x` and the remainder in `y`.
422
386
///
423
387
/// This function operates in variable-time. It will panic if the divisor is zero
@@ -444,44 +408,51 @@ pub(crate) fn div_rem_vartime_in_place(x: &mut [Limb], y: &mut [Limb]) {
444
408
}
445
409
446
410
let lshift = y[ yc - 1 ] . leading_zeros ( ) ;
411
+ let rshift = if lshift == 0 { 0 } else { Limb :: BITS - lshift } ;
412
+ let mut x_hi = Limb :: ZERO ;
413
+ let mut carry;
414
+
415
+ if lshift != 0 {
416
+ // Shift divisor such that it has no leading zeros
417
+ // This means that div2by1 requires no extra shifts, and ensures that the high word >= b/2
418
+ carry = Limb :: ZERO ;
419
+ for i in 0 ..yc {
420
+ ( y[ i] , carry) = ( Limb ( ( y[ i] . 0 << lshift) | carry. 0 ) , Limb ( y[ i] . 0 >> rshift) ) ;
421
+ }
447
422
448
- // Shift divisor such that it has no leading zeros
449
- // This means that div2by1 requires no extra shifts, and ensures that the high word >= b/2
450
- shl_limb_vartime ( y, lshift) ;
451
-
452
- // Shift the dividend to match
453
- let mut x_hi = shl_limb_vartime ( x, lshift) ;
423
+ // Shift the dividend to match
424
+ carry = Limb :: ZERO ;
425
+ for i in 0 ..xc {
426
+ ( x[ i] , carry) = ( Limb ( ( x[ i] . 0 << lshift) | carry. 0 ) , Limb ( x[ i] . 0 >> rshift) ) ;
427
+ }
428
+ x_hi = carry;
429
+ }
454
430
455
431
let reciprocal = Reciprocal :: new ( y[ yc - 1 ] . to_nz ( ) . expect ( "zero divisor" ) ) ;
456
432
457
433
for xi in ( yc - 1 ..xc) . rev ( ) {
458
434
// Divide high dividend words by the high divisor word to estimate the quotient word
459
- let mut quo = div3by2 ( x_hi. 0 , x[ xi] . 0 , x[ xi - 1 ] . 0 , & reciprocal, y[ yc - 2 ] . 0 ) ;
435
+ let ( mut quo, _ ) = div3by2 ( x_hi. 0 , x[ xi] . 0 , x[ xi - 1 ] . 0 , & reciprocal, y[ yc - 2 ] . 0 ) ;
460
436
461
437
// Subtract q*divisor from the dividend
462
- let borrow = {
463
- let mut carry = Limb :: ZERO ;
464
- let mut borrow = Limb :: ZERO ;
465
- let mut tmp;
466
- for i in 0 ..yc {
467
- ( tmp, carry) = Limb :: ZERO . mac ( y[ i] , Limb ( quo) , carry) ;
468
- ( x[ xi + i + 1 - yc] , borrow) = x[ xi + i + 1 - yc] . sbb ( tmp, borrow) ;
469
- }
470
- ( _, borrow) = x_hi. sbb ( carry, borrow) ;
471
- borrow
472
- } ;
438
+ carry = Limb :: ZERO ;
439
+ let mut borrow = Limb :: ZERO ;
440
+ let mut tmp;
441
+ for i in 0 ..yc {
442
+ ( tmp, carry) = Limb :: ZERO . mac ( y[ i] , Limb ( quo) , carry) ;
443
+ ( x[ xi + i + 1 - yc] , borrow) = x[ xi + i + 1 - yc] . sbb ( tmp, borrow) ;
444
+ }
445
+ ( _, borrow) = x_hi. sbb ( carry, borrow) ;
473
446
474
447
// If the subtraction borrowed, then decrement q and add back the divisor
475
448
// The probability of this being needed is very low, about 2/(Limb::MAX+1)
476
- quo = {
477
- let ct_borrow = ConstChoice :: from_word_mask ( borrow. 0 ) ;
478
- let mut carry = Limb :: ZERO ;
479
- for i in 0 ..yc {
480
- ( x[ xi + i + 1 - yc] , carry) =
481
- x[ xi + i + 1 - yc] . adc ( Limb :: select ( Limb :: ZERO , y[ i] , ct_borrow) , carry) ;
482
- }
483
- ct_borrow. select_word ( quo, quo. wrapping_sub ( 1 ) )
484
- } ;
449
+ let ct_borrow = ConstChoice :: from_word_mask ( borrow. 0 ) ;
450
+ carry = Limb :: ZERO ;
451
+ for i in 0 ..yc {
452
+ ( x[ xi + i + 1 - yc] , carry) =
453
+ x[ xi + i + 1 - yc] . adc ( Limb :: select ( Limb :: ZERO , y[ i] , ct_borrow) , carry) ;
454
+ }
455
+ quo = ct_borrow. select_word ( quo, quo. saturating_sub ( 1 ) ) ;
485
456
486
457
// Store the quotient within dividend and set x_hi to the current highest word
487
458
x_hi = x[ xi] ;
@@ -493,7 +464,12 @@ pub(crate) fn div_rem_vartime_in_place(x: &mut [Limb], y: &mut [Limb]) {
493
464
y[ yc - 1 ] = x_hi;
494
465
495
466
// Unshift the remainder from the earlier adjustment
496
- shr_limb_vartime ( y, lshift) ;
467
+ if lshift != 0 {
468
+ carry = Limb :: ZERO ;
469
+ for i in ( 0 ..yc) . rev ( ) {
470
+ ( y[ i] , carry) = ( Limb ( ( y[ i] . 0 >> lshift) | carry. 0 ) , Limb ( y[ i] . 0 << rshift) ) ;
471
+ }
472
+ }
497
473
498
474
// Shift the quotient to the low limbs within dividend
499
475
// let x_size = xc - yc + 1;
0 commit comments