Skip to content

Commit 325e16b

Browse files
authored
Revert "Some simplifications of vartime division (#646)" (#658)
This reverts commit e7d3b16. This needs changes as upstream diverged.
1 parent e7d3b16 commit 325e16b

File tree

3 files changed

+190
-224
lines changed

3 files changed

+190
-224
lines changed

src/uint/boxed/div.rs

Lines changed: 40 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -382,42 +382,6 @@ 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-
421385
/// Computes `x` / `y`, returning the quotient in `x` and the remainder in `y`.
422386
///
423387
/// 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]) {
444408
}
445409

446410
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+
}
447422

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+
}
454430

455431
let reciprocal = Reciprocal::new(y[yc - 1].to_nz().expect("zero divisor"));
456432

457433
for xi in (yc - 1..xc).rev() {
458434
// 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);
460436

461437
// 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);
473446

474447
// If the subtraction borrowed, then decrement q and add back the divisor
475448
// 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));
485456

486457
// Store the quotient within dividend and set x_hi to the current highest word
487458
x_hi = x[xi];
@@ -493,7 +464,12 @@ pub(crate) fn div_rem_vartime_in_place(x: &mut [Limb], y: &mut [Limb]) {
493464
y[yc - 1] = x_hi;
494465

495466
// 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+
}
497473

498474
// Shift the quotient to the low limbs within dividend
499475
// let x_size = xc - yc + 1;

0 commit comments

Comments
 (0)