@@ -310,6 +310,42 @@ impl RemLimb for BoxedUint {
310310 }
311311}
312312
313+ /// Computes `limbs << shift` inplace, where `0 <= shift < Limb::BITS`, returning the carry.
314+ fn shl_limb_vartime ( limbs : & mut [ Limb ] , shift : u32 ) -> Limb {
315+ if shift == 0 {
316+ return Limb :: ZERO ;
317+ }
318+
319+ let lshift = shift;
320+ let rshift = Limb :: BITS - shift;
321+ let limbs_num = limbs. len ( ) ;
322+
323+ let carry = limbs[ limbs_num - 1 ] >> rshift;
324+ for i in ( 1 ..limbs_num) . rev ( ) {
325+ limbs[ i] = ( limbs[ i] << lshift) | ( limbs[ i - 1 ] >> rshift) ;
326+ }
327+ limbs[ 0 ] <<= lshift;
328+
329+ carry
330+ }
331+
332+ /// Computes `limbs >> shift` inplace, where `0 <= shift < Limb::BITS`.
333+ fn shr_limb_vartime ( limbs : & mut [ Limb ] , shift : u32 ) {
334+ if shift == 0 {
335+ return ;
336+ }
337+
338+ let lshift = Limb :: BITS - shift;
339+ let rshift = shift;
340+
341+ let limbs_num = limbs. len ( ) ;
342+
343+ for i in 0 ..limbs_num - 1 {
344+ limbs[ i] = ( limbs[ i] >> rshift) | ( limbs[ i + 1 ] << lshift) ;
345+ }
346+ limbs[ limbs_num - 1 ] >>= rshift;
347+ }
348+
313349/// Computes `x` / `y`, returning the quotient in `x` and the remainder in `y`.
314350///
315351/// This function operates in variable-time. It will panic if the divisor is zero
@@ -336,51 +372,44 @@ pub(crate) fn div_rem_vartime_in_place(x: &mut [Limb], y: &mut [Limb]) {
336372 }
337373
338374 let lshift = y[ yc - 1 ] . leading_zeros ( ) ;
339- let rshift = if lshift == 0 { 0 } else { Limb :: BITS - lshift } ;
340- let mut x_hi = Limb :: ZERO ;
341- let mut carry;
342-
343- if lshift != 0 {
344- // Shift divisor such that it has no leading zeros
345- // This means that div2by1 requires no extra shifts, and ensures that the high word >= b/2
346- carry = Limb :: ZERO ;
347- for i in 0 ..yc {
348- ( y[ i] , carry) = ( Limb ( ( y[ i] . 0 << lshift) | carry. 0 ) , Limb ( y[ i] . 0 >> rshift) ) ;
349- }
350375
351- // Shift the dividend to match
352- carry = Limb :: ZERO ;
353- for i in 0 ..xc {
354- ( x[ i] , carry) = ( Limb ( ( x[ i] . 0 << lshift) | carry. 0 ) , Limb ( x[ i] . 0 >> rshift) ) ;
355- }
356- x_hi = carry;
357- }
376+ // Shift divisor such that it has no leading zeros
377+ // This means that div2by1 requires no extra shifts, and ensures that the high word >= b/2
378+ shl_limb_vartime ( y, lshift) ;
379+
380+ // Shift the dividend to match
381+ let mut x_hi = shl_limb_vartime ( x, lshift) ;
358382
359383 let reciprocal = Reciprocal :: new ( y[ yc - 1 ] . to_nz ( ) . expect ( "zero divisor" ) ) ;
360384
361385 for xi in ( yc - 1 ..xc) . rev ( ) {
362386 // Divide high dividend words by the high divisor word to estimate the quotient word
363- let ( mut quo, _ ) = div3by2 ( x_hi. 0 , x[ xi] . 0 , x[ xi - 1 ] . 0 , & reciprocal, y[ yc - 2 ] . 0 ) ;
387+ let mut quo = div3by2 ( x_hi. 0 , x[ xi] . 0 , x[ xi - 1 ] . 0 , & reciprocal, y[ yc - 2 ] . 0 ) ;
364388
365389 // Subtract q*divisor from the dividend
366- carry = Limb :: ZERO ;
367- let mut borrow = Limb :: ZERO ;
368- let mut tmp;
369- for i in 0 ..yc {
370- ( tmp, carry) = Limb :: ZERO . mac ( y[ i] , Limb ( quo) , carry) ;
371- ( x[ xi + i + 1 - yc] , borrow) = x[ xi + i + 1 - yc] . sbb ( tmp, borrow) ;
372- }
373- ( _, borrow) = x_hi. sbb ( carry, borrow) ;
390+ let borrow = {
391+ let mut carry = Limb :: ZERO ;
392+ let mut borrow = Limb :: ZERO ;
393+ let mut tmp;
394+ for i in 0 ..yc {
395+ ( tmp, carry) = Limb :: ZERO . mac ( y[ i] , Limb ( quo) , carry) ;
396+ ( x[ xi + i + 1 - yc] , borrow) = x[ xi + i + 1 - yc] . sbb ( tmp, borrow) ;
397+ }
398+ ( _, borrow) = x_hi. sbb ( carry, borrow) ;
399+ borrow
400+ } ;
374401
375402 // If the subtraction borrowed, then decrement q and add back the divisor
376403 // The probability of this being needed is very low, about 2/(Limb::MAX+1)
377- let ct_borrow = ConstChoice :: from_word_mask ( borrow. 0 ) ;
378- carry = Limb :: ZERO ;
379- for i in 0 ..yc {
380- ( x[ xi + i + 1 - yc] , carry) =
381- x[ xi + i + 1 - yc] . adc ( Limb :: select ( Limb :: ZERO , y[ i] , ct_borrow) , carry) ;
382- }
383- quo = ct_borrow. select_word ( quo, quo. saturating_sub ( 1 ) ) ;
404+ quo = {
405+ let ct_borrow = ConstChoice :: from_word_mask ( borrow. 0 ) ;
406+ let mut carry = Limb :: ZERO ;
407+ for i in 0 ..yc {
408+ ( x[ xi + i + 1 - yc] , carry) =
409+ x[ xi + i + 1 - yc] . adc ( Limb :: select ( Limb :: ZERO , y[ i] , ct_borrow) , carry) ;
410+ }
411+ ct_borrow. select_word ( quo, quo. saturating_sub ( 1 ) )
412+ } ;
384413
385414 // Store the quotient within dividend and set x_hi to the current highest word
386415 x_hi = x[ xi] ;
@@ -392,12 +421,7 @@ pub(crate) fn div_rem_vartime_in_place(x: &mut [Limb], y: &mut [Limb]) {
392421 y[ yc - 1 ] = x_hi;
393422
394423 // Unshift the remainder from the earlier adjustment
395- if lshift != 0 {
396- carry = Limb :: ZERO ;
397- for i in ( 0 ..yc) . rev ( ) {
398- ( y[ i] , carry) = ( Limb ( ( y[ i] . 0 >> lshift) | carry. 0 ) , Limb ( y[ i] . 0 << rshift) ) ;
399- }
400- }
424+ shr_limb_vartime ( y, lshift) ;
401425
402426 // Shift the quotient to the low limbs within dividend
403427 // let x_size = xc - yc + 1;
0 commit comments