Skip to content

Commit

Permalink
Simplify implementation of BoxedUint::chain (#319)
Browse files Browse the repository at this point in the history
  • Loading branch information
tarcieri authored Nov 26, 2023
1 parent 46238ee commit 887ffc7
Show file tree
Hide file tree
Showing 2 changed files with 15 additions and 33 deletions.
43 changes: 12 additions & 31 deletions src/boxed/uint.rs
Original file line number Diff line number Diff line change
Expand Up @@ -170,47 +170,28 @@ impl BoxedUint {
self.limbs.len() * Limb::BITS
}

/// Sort two [`BoxedUint`]s by precision, returning a tuple of the shorter
/// followed by the longer, or the original order if their precision is
/// equal.
fn sort_by_precision<'a>(a: &'a Self, b: &'a Self) -> (&'a Self, &'a Self, bool) {
if a.limbs.len() <= b.limbs.len() {
(a, b, false)
} else {
(b, a, true)
}
}

/// Perform a carry chain-like operation over the limbs of the inputs,
/// constructing a result from the returned limbs and carry.
/// constructing a result from the returned limbs and carry which is
/// widened to the same width as the widest input.
///
/// If one of the two values has fewer limbs than the other, passes
/// If one of the two values has fewer limbs than the other, pads with
/// [`Limb::ZERO`] as the value for that limb.
fn chain<F>(a: &Self, b: &Self, mut carry: Limb, f: F) -> (Self, Limb)
fn chain<F>(lhs: &Self, rhs: &Self, mut carry: Limb, f: F) -> (Self, Limb)
where
F: Fn(Limb, Limb, Limb) -> (Limb, Limb),
{
let (shorter, longer, swapped) = Self::sort_by_precision(a, b);
let mut limbs = Vec::with_capacity(longer.limbs.len());

for i in 0..longer.limbs.len() {
let &a = shorter.limbs.get(i).unwrap_or(&Limb::ZERO);
let &b = longer.limbs.get(i).unwrap_or(&Limb::ZERO);
let (limb, c) = if swapped {
f(b, a, carry)
} else {
f(a, b, carry)
};
let nlimbs = cmp::max(lhs.nlimbs(), rhs.nlimbs());
let mut limbs = Vec::with_capacity(nlimbs);

for i in 0..nlimbs {
let &a = lhs.limbs.get(i).unwrap_or(&Limb::ZERO);
let &b = rhs.limbs.get(i).unwrap_or(&Limb::ZERO);
let (limb, c) = f(a, b, carry);
limbs.push(limb);
carry = c;
}

(
Self {
limbs: limbs.into(),
},
carry,
)
(limbs.into(), carry)
}
}

Expand Down
5 changes: 3 additions & 2 deletions src/boxed/uint/cmp.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,18 @@
//!
//! By default these are all constant-time and use the `subtle` crate.
pub(super) use core::cmp::{max, Ordering};

use super::BoxedUint;
use crate::{CtChoice, Limb};
use core::cmp::{self, Ordering};
use subtle::{
Choice, ConditionallySelectable, ConstantTimeEq, ConstantTimeGreater, ConstantTimeLess,
};

impl ConstantTimeEq for BoxedUint {
#[inline]
fn ct_eq(&self, other: &Self) -> Choice {
let limbs = cmp::max(self.nlimbs(), other.nlimbs());
let limbs = max(self.nlimbs(), other.nlimbs());
let mut ret = Choice::from(1u8);

for i in 0..limbs {
Expand Down

0 comments on commit 887ffc7

Please sign in to comment.