Skip to content

Commit 342f7f2

Browse files
use UintRef methods for Uint bit shifts
Signed-off-by: Andrew Whitehead <cywolf@gmail.com>
1 parent d1d70be commit 342f7f2

8 files changed

Lines changed: 167 additions & 281 deletions

File tree

benches/uint.rs

Lines changed: 40 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -740,6 +740,26 @@ fn bench_mod_symbols(c: &mut Criterion) {
740740
fn bench_shl(c: &mut Criterion) {
741741
let mut group = c.benchmark_group("left shift");
742742

743+
group.bench_function("shl, U256", |b| {
744+
b.iter_batched(|| U256::ONE, |x| x.shl(30), BatchSize::SmallInput);
745+
});
746+
747+
group.bench_function("unbounded_shl, U256", |b| {
748+
b.iter_batched(|| U256::ONE, |x| x.unbounded_shl(30), BatchSize::SmallInput);
749+
});
750+
751+
group.bench_function("shl, U2048", |b| {
752+
b.iter_batched(|| U2048::ONE, |x| x.shl(1024 + 10), BatchSize::SmallInput);
753+
});
754+
755+
group.bench_function("unbounded_shl, U2048", |b| {
756+
b.iter_batched(
757+
|| U2048::ONE,
758+
|x| x.unbounded_shl(1024 + 10),
759+
BatchSize::SmallInput,
760+
);
761+
});
762+
743763
group.bench_function("shl_vartime, small, U2048", |b| {
744764
b.iter_batched(|| U2048::ONE, |x| x.shl_vartime(10), BatchSize::SmallInput);
745765
});
@@ -760,16 +780,32 @@ fn bench_shl(c: &mut Criterion) {
760780
);
761781
});
762782

763-
group.bench_function("shl, U2048", |b| {
764-
b.iter_batched(|| U2048::ONE, |x| x.shl(1024 + 10), BatchSize::SmallInput);
765-
});
766-
767783
group.finish();
768784
}
769785

770786
fn bench_shr(c: &mut Criterion) {
771787
let mut group = c.benchmark_group("right shift");
772788

789+
group.bench_function("shr, U256", |b| {
790+
b.iter_batched(|| U256::ONE, |x| x.shr(30), BatchSize::SmallInput);
791+
});
792+
793+
group.bench_function("unbounded_shr, U256", |b| {
794+
b.iter_batched(|| U256::ONE, |x| x.unbounded_shr(30), BatchSize::SmallInput);
795+
});
796+
797+
group.bench_function("shr, U2048", |b| {
798+
b.iter_batched(|| U2048::ONE, |x| x.shr(1024 + 10), BatchSize::SmallInput);
799+
});
800+
801+
group.bench_function("unbounded_shr, U2048", |b| {
802+
b.iter_batched(
803+
|| U2048::ONE,
804+
|x| x.unbounded_shr(1024 + 10),
805+
BatchSize::SmallInput,
806+
);
807+
});
808+
773809
group.bench_function("shr_vartime, small, U2048", |b| {
774810
b.iter_batched(|| U2048::ONE, |x| x.shr_vartime(10), BatchSize::SmallInput);
775811
});
@@ -790,10 +826,6 @@ fn bench_shr(c: &mut Criterion) {
790826
);
791827
});
792828

793-
group.bench_function("shr, U2048", |b| {
794-
b.iter_batched(|| U2048::ONE, |x| x.shr(1024 + 10), BatchSize::SmallInput);
795-
});
796-
797829
group.finish();
798830
}
799831

src/modular/bingcd/extension.rs

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -95,19 +95,17 @@ impl<const LIMBS: usize, const EXTRA: usize> ExtendedUint<LIMBS, EXTRA> {
9595
pub const fn shr_vartime(&self, shift: u32) -> Self {
9696
debug_assert!(shift <= Uint::<EXTRA>::BITS);
9797

98-
let shift_is_zero = Choice::from_u32_eq(shift, 0);
99-
let left_shift = shift_is_zero.select_u32(Uint::<EXTRA>::BITS - shift, 0);
100-
10198
let hi = self.1.shr_vartime(shift);
102-
// TODO: replace with carrying_shl
103-
let carry = Uint::select(&self.1, &Uint::ZERO, shift_is_zero).shl_vartime(left_shift);
99+
let carry = self.1.unbounded_shl_vartime(Uint::<EXTRA>::BITS - shift);
104100
let mut lo = self.0.shr_vartime(shift);
105101

106102
// Apply carry
107-
let limb_diff = LIMBS.wrapping_sub(EXTRA) as u32;
103+
let limb_diff = LIMBS.saturating_sub(EXTRA) as u32;
108104
// safe to vartime; shr_vartime is variable in the value of shift only. Since this shift
109105
// is a public constant, the constant time property of this algorithm is not impacted.
110-
let carry = carry.resize::<LIMBS>().shl_vartime(limb_diff * Limb::BITS);
106+
let carry = carry
107+
.resize::<LIMBS>()
108+
.unbounded_shl_by_limbs_vartime(limb_diff);
111109
lo = lo.bitxor(&carry);
112110

113111
Self(lo, hi)

src/uint/boxed/shl.rs

Lines changed: 3 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -165,14 +165,9 @@ impl BoxedUint {
165165
/// Computes `self << 1` in constant-time.
166166
pub(crate) fn shl1(&self) -> (Self, Limb) {
167167
let mut ret = self.clone();
168-
let carry = Limb::select(Limb::ZERO, Limb::ONE, ret.shl1_assign());
168+
let carry = ret.as_mut_uint_ref().shl1_assign();
169169
(ret, carry)
170170
}
171-
172-
/// Computes `self <<= 1` in constant-time.
173-
pub(crate) fn shl1_assign(&mut self) -> Choice {
174-
self.as_mut_uint_ref().shl1_assign()
175-
}
176171
}
177172

178173
macro_rules! impl_shl {
@@ -246,10 +241,9 @@ mod tests {
246241

247242
#[test]
248243
fn shl1_assign() {
249-
let mut n = BoxedUint::from(0x3c442b21f19185fe433f0a65af902b8fu128);
244+
let n = BoxedUint::from(0x3c442b21f19185fe433f0a65af902b8fu128);
250245
let n_shl1 = BoxedUint::from(0x78885643e3230bfc867e14cb5f20571eu128);
251-
n.shl1_assign();
252-
assert_eq!(n, n_shl1);
246+
assert_eq!(n.shl1().0, n_shl1);
253247
}
254248

255249
#[test]

src/uint/boxed/shr.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -178,7 +178,7 @@ impl BoxedUint {
178178

179179
/// Computes `self >>= 1` in-place in constant-time.
180180
pub(crate) fn shr1_assign(&mut self) -> Choice {
181-
self.as_mut_uint_ref().shr1_assign()
181+
self.as_mut_uint_ref().shr1_assign().lsb_to_choice()
182182
}
183183
}
184184

src/uint/ref_type/shl.rs

Lines changed: 24 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
use core::num::NonZeroU32;
44

55
use super::UintRef;
6-
use crate::{Choice, Limb, primitives::u32_bits, word};
6+
use crate::{Choice, Limb, primitives::u32_bits};
77

88
#[cfg(feature = "alloc")]
99
use crate::primitives::u32_rem;
@@ -50,15 +50,16 @@ impl UintRef {
5050
pub(crate) const fn bounded_shl_assign(&mut self, shift: u32, shift_upper_bound: u32) {
5151
assert!(shift < shift_upper_bound, "`shift` exceeds upper bound");
5252

53-
if shift_upper_bound <= Limb::BITS {
54-
self.shl_assign_limb(shift);
53+
let bit_shift = if shift_upper_bound <= Limb::BITS {
54+
shift
5555
} else {
5656
self.bounded_shl_by_limbs_assign(
5757
shift >> Limb::LOG2_BITS,
5858
shift_upper_bound.div_ceil(Limb::BITS),
5959
);
60-
self.shl_assign_limb(shift & (Limb::BITS - 1));
61-
}
60+
shift & (Limb::BITS - 1)
61+
};
62+
self.shl_assign_limb_with_carry(bit_shift, Limb::ZERO);
6263
}
6364

6465
/// Left-shifts by `shift * Limb::BITS` bits where `shift < shift_upper_bound`.
@@ -107,7 +108,6 @@ impl UintRef {
107108
/// NOTE: this operation is variable time with respect to `shift` *ONLY*.
108109
///
109110
/// When used with a fixed `shift`, this function is constant-time with respect to `self`.
110-
#[cfg(feature = "alloc")]
111111
#[inline(always)]
112112
pub(crate) const fn unbounded_shl_assign_by_limbs_vartime(&mut self, shift: u32) {
113113
let shift = shift as usize;
@@ -128,7 +128,6 @@ impl UintRef {
128128
/// NOTE: this operation is variable time with respect to `shift` *ONLY*.
129129
///
130130
/// When used with a fixed `shift`, this function is constant-time with respect to `self`.
131-
#[cfg(feature = "alloc")]
132131
#[inline(always)]
133132
pub const fn unbounded_shl_assign_vartime(&mut self, shift: u32) {
134133
let shift_limbs = shift / Limb::BITS;
@@ -170,7 +169,7 @@ impl UintRef {
170169
/// Left-shifts by a single bit in constant-time, returning [`Choice::TRUE`]
171170
/// if the least significant bit was set, and [`Choice::FALSE`] otherwise.
172171
#[inline(always)]
173-
pub const fn shl1_assign(&mut self) -> Choice {
172+
pub const fn shl1_assign(&mut self) -> Limb {
174173
let mut carry = Limb::ZERO;
175174
let mut i = 0;
176175
while i < self.nlimbs() {
@@ -179,25 +178,25 @@ impl UintRef {
179178
carry = new_carry;
180179
i += 1;
181180
}
182-
word::choice_from_lsb(carry.0)
181+
carry
183182
}
184183

185184
/// Conditionally left-shifts by `shift` bits where `0 < shift < Limb::BITS`, returning
186185
/// the carry.
187186
///
188187
/// # Panics
189188
/// - if `shift >= Limb::BITS`.
190-
#[inline]
189+
#[inline(always)]
191190
pub(crate) const fn conditional_shl_assign_limb_nonzero(
192191
&mut self,
193192
shift: NonZeroU32,
193+
mut carry: Limb,
194194
choice: Choice,
195195
) -> Limb {
196196
assert!(shift.get() < Limb::BITS);
197197

198198
let lshift = shift.get();
199199
let rshift = Limb::BITS - lshift;
200-
let mut carry = Limb::ZERO;
201200

202201
let mut i = 0;
203202
while i < self.nlimbs() {
@@ -221,9 +220,19 @@ impl UintRef {
221220
/// - if `shift >= Limb::BITS`.
222221
#[inline(always)]
223222
pub const fn shl_assign_limb(&mut self, shift: u32) -> Limb {
223+
self.shl_assign_limb_with_carry(shift, Limb::ZERO)
224+
}
225+
226+
/// Left-shifts by `shift` bits where `0 < shift < Limb::BITS`, returning the carry.
227+
///
228+
/// # Panics
229+
/// - if `shift >= Limb::BITS`.
230+
#[inline(always)]
231+
pub const fn shl_assign_limb_with_carry(&mut self, shift: u32, carry: Limb) -> Limb {
224232
let nz = Choice::from_u32_nz(shift);
225233
self.conditional_shl_assign_limb_nonzero(
226234
NonZeroU32::new(nz.select_u32(1, shift)).expect("ensured non-zero"),
235+
carry,
227236
nz,
228237
)
229238
}
@@ -263,9 +272,7 @@ impl UintRef {
263272

264273
#[cfg(test)]
265274
mod tests {
266-
#[cfg(feature = "alloc")]
267-
use crate::Uint;
268-
use crate::{Limb, U256};
275+
use crate::{Limb, U256, Uint};
269276

270277
const N: U256 =
271278
U256::from_be_hex("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141");
@@ -278,17 +285,17 @@ mod tests {
278285
let mut n = N;
279286
let carry = n.as_mut_uint_ref().shl1_assign();
280287
assert_eq!(n, TWO_N);
281-
assert!(carry.to_bool());
288+
assert_eq!(carry, Limb::ONE);
282289

283290
let mut m = U256::MAX;
284291
let carry = m.as_mut_uint_ref().shl1_assign();
285292
assert_eq!(m, U256::MAX.shl_vartime(1));
286-
assert!(carry.to_bool());
293+
assert_eq!(carry, Limb::ONE);
287294

288295
let mut z = U256::ZERO;
289296
let carry = z.as_mut_uint_ref().shl1_assign();
290297
assert_eq!(z, U256::ZERO);
291-
assert!(!carry.to_bool());
298+
assert_eq!(carry, Limb::ZERO);
292299
}
293300

294301
#[test]
@@ -324,7 +331,6 @@ mod tests {
324331
assert_eq!(carry, N.limbs[U256::LIMBS - 1].shr(1));
325332
}
326333

327-
#[cfg(feature = "alloc")]
328334
#[test]
329335
fn unbounded_shl_by_limbs_vartime() {
330336
let refval = Uint::<2>::from_words([1, 99]);

0 commit comments

Comments
 (0)