@@ -310,6 +310,42 @@ impl RemLimb for BoxedUint {
310
310
}
311
311
}
312
312
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
+
313
349
/// Computes `x` / `y`, returning the quotient in `x` and the remainder in `y`.
314
350
///
315
351
/// 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]) {
336
372
}
337
373
338
374
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
- }
350
375
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) ;
358
382
359
383
let reciprocal = Reciprocal :: new ( y[ yc - 1 ] . to_nz ( ) . expect ( "zero divisor" ) ) ;
360
384
361
385
for xi in ( yc - 1 ..xc) . rev ( ) {
362
386
// 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 ) ;
364
388
365
389
// 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
+ } ;
374
401
375
402
// If the subtraction borrowed, then decrement q and add back the divisor
376
403
// 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
+ } ;
384
413
385
414
// Store the quotient within dividend and set x_hi to the current highest word
386
415
x_hi = x[ xi] ;
@@ -392,12 +421,7 @@ pub(crate) fn div_rem_vartime_in_place(x: &mut [Limb], y: &mut [Limb]) {
392
421
y[ yc - 1 ] = x_hi;
393
422
394
423
// 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) ;
401
425
402
426
// Shift the quotient to the low limbs within dividend
403
427
// let x_size = xc - yc + 1;
0 commit comments