@@ -382,6 +382,42 @@ impl RemLimb for BoxedUint {
382382 }
383383}
384384
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+
385421/// Computes `x` / `y`, returning the quotient in `x` and the remainder in `y`.
386422///
387423/// This function operates in variable-time. It will panic if the divisor is zero
@@ -408,51 +444,44 @@ pub(crate) fn div_rem_vartime_in_place(x: &mut [Limb], y: &mut [Limb]) {
408444 }
409445
410446 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- }
422447
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- }
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) ;
430454
431455 let reciprocal = Reciprocal :: new ( y[ yc - 1 ] . to_nz ( ) . expect ( "zero divisor" ) ) ;
432456
433457 for xi in ( yc - 1 ..xc) . rev ( ) {
434458 // Divide high dividend words by the high divisor word to estimate the quotient word
435- let ( mut quo, _ ) = div3by2 ( x_hi. 0 , x[ xi] . 0 , x[ xi - 1 ] . 0 , & reciprocal, y[ yc - 2 ] . 0 ) ;
459+ let mut quo = div3by2 ( x_hi. 0 , x[ xi] . 0 , x[ xi - 1 ] . 0 , & reciprocal, y[ yc - 2 ] . 0 ) ;
436460
437461 // Subtract q*divisor from the dividend
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) ;
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+ } ;
446473
447474 // If the subtraction borrowed, then decrement q and add back the divisor
448475 // The probability of this being needed is very low, about 2/(Limb::MAX+1)
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 ) ) ;
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+ } ;
456485
457486 // Store the quotient within dividend and set x_hi to the current highest word
458487 x_hi = x[ xi] ;
@@ -464,12 +493,7 @@ pub(crate) fn div_rem_vartime_in_place(x: &mut [Limb], y: &mut [Limb]) {
464493 y[ yc - 1 ] = x_hi;
465494
466495 // Unshift the remainder from the earlier adjustment
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- }
496+ shr_limb_vartime ( y, lshift) ;
473497
474498 // Shift the quotient to the low limbs within dividend
475499 // let x_size = xc - yc + 1;
0 commit comments