Skip to content

Commit df3acc0

Browse files
committed
Use the Hacker's Delight integer comparison for Limb's subtle impls
1 parent e69ba39 commit df3acc0

File tree

3 files changed

+27
-5
lines changed

3 files changed

+27
-5
lines changed

src/const_choice.rs

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,10 +71,19 @@ impl ConstChoice {
7171
/// Returns the truthy value if `x < y`, and the falsy value otherwise.
7272
#[inline]
7373
pub(crate) const fn from_word_lt(x: Word, y: Word) -> Self {
74+
// See "Hacker's Delight" 2nd ed, section 2-12 (Comparison predicates)
7475
let bit = (((!x) & y) | (((!x) | y) & (x.wrapping_sub(y)))) >> (Word::BITS - 1);
7576
Self::from_word_lsb(bit)
7677
}
7778

79+
/// Returns the truthy value if `x > y`, and the falsy value otherwise.
80+
#[inline]
81+
pub(crate) const fn from_word_gt(x: Word, y: Word) -> Self {
82+
// See "Hacker's Delight" 2nd ed, section 2-12 (Comparison predicates)
83+
let bit = (((!y) & x) | (((!y) | x) & (y.wrapping_sub(x)))) >> (Word::BITS - 1);
84+
Self::from_word_lsb(bit)
85+
}
86+
7887
/// Returns the truthy value if `x < y`, and the falsy value otherwise.
7988
#[inline]
8089
pub(crate) const fn from_u32_lt(x: u32, y: u32) -> Self {
@@ -147,6 +156,7 @@ impl ConstChoice {
147156
}
148157

149158
impl From<ConstChoice> for Choice {
159+
#[inline]
150160
fn from(choice: ConstChoice) -> Self {
151161
Choice::from(choice.to_u8())
152162
}
@@ -169,6 +179,20 @@ mod tests {
169179
use super::ConstChoice;
170180
use crate::Word;
171181

182+
#[test]
183+
fn from_word_lt() {
184+
assert_eq!(ConstChoice::from_word_lt(4, 5), ConstChoice::TRUE);
185+
assert_eq!(ConstChoice::from_word_lt(5, 5), ConstChoice::FALSE);
186+
assert_eq!(ConstChoice::from_word_lt(6, 5), ConstChoice::FALSE);
187+
}
188+
189+
#[test]
190+
fn from_word_gt() {
191+
assert_eq!(ConstChoice::from_word_gt(4, 5), ConstChoice::FALSE);
192+
assert_eq!(ConstChoice::from_word_gt(5, 5), ConstChoice::FALSE);
193+
assert_eq!(ConstChoice::from_word_gt(6, 5), ConstChoice::TRUE);
194+
}
195+
172196
#[test]
173197
fn select() {
174198
let a: Word = 1;

src/limb/cmp.rs

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -54,16 +54,14 @@ impl ConstantTimeEq for Limb {
5454
impl ConstantTimeGreater for Limb {
5555
#[inline]
5656
fn ct_gt(&self, other: &Self) -> Choice {
57-
let borrow = other.sbb(*self, Limb::ZERO).1;
58-
Choice::from(borrow.0 as u8 & 1)
57+
ConstChoice::from_word_gt(self.0, other.0).into()
5958
}
6059
}
6160

6261
impl ConstantTimeLess for Limb {
6362
#[inline]
6463
fn ct_lt(&self, other: &Self) -> Choice {
65-
let borrow = self.sbb(*other, Limb::ZERO).1;
66-
Choice::from(borrow.0 as u8 & 1)
64+
ConstChoice::from_word_lt(self.0, other.0).into()
6765
}
6866
}
6967

src/modular/boxed_residue/mul.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -247,7 +247,7 @@ fn sub_vv(z: &mut [Limb], x: &[Limb], y: &[Limb]) -> Limb {
247247
for (i, (&xi, &yi)) in x.iter().zip(y.iter()).enumerate().take(z.len()) {
248248
let zi = xi.wrapping_sub(yi).wrapping_sub(c);
249249
z[i] = zi;
250-
// see "Hacker's Delight", section 2-12 (overflow detection)
250+
// See "Hacker's Delight" 2nd ed, section 2-13 (Overflow detection)
251251
c = ((yi & !xi) | ((yi | !xi) & zi)) >> (Word::BITS - 1)
252252
}
253253

0 commit comments

Comments
 (0)