diff --git a/benches/boxed_uint.rs b/benches/boxed_uint.rs index b34eaa33..dbdf3dc1 100644 --- a/benches/boxed_uint.rs +++ b/benches/boxed_uint.rs @@ -19,7 +19,7 @@ fn bench_shifts(c: &mut Criterion) { group.bench_function("shl", |b| { b.iter_batched( || BoxedUint::random(&mut OsRng, UINT_BITS), - |x| x.shl(UINT_BITS / 2 + 10), + |x| x.overflowing_shl(UINT_BITS / 2 + 10), BatchSize::SmallInput, ) }); @@ -35,7 +35,7 @@ fn bench_shifts(c: &mut Criterion) { group.bench_function("shr", |b| { b.iter_batched( || BoxedUint::random(&mut OsRng, UINT_BITS), - |x| x.shr(UINT_BITS / 2 + 10), + |x| x.overflowing_shr(UINT_BITS / 2 + 10), BatchSize::SmallInput, ) }); diff --git a/benches/uint.rs b/benches/uint.rs index 5fbd5c60..1d154f71 100644 --- a/benches/uint.rs +++ b/benches/uint.rs @@ -79,13 +79,17 @@ fn bench_shl(c: &mut Criterion) { let mut group = c.benchmark_group("left shift"); group.bench_function("shl_vartime, small, U2048", |b| { - b.iter_batched(|| U2048::ONE, |x| x.shl_vartime(10), BatchSize::SmallInput) + b.iter_batched( + || U2048::ONE, + |x| x.overflowing_shl_vartime(10), + BatchSize::SmallInput, + ) }); group.bench_function("shl_vartime, large, U2048", |b| { b.iter_batched( || U2048::ONE, - |x| black_box(x.shl_vartime(1024 + 10)), + |x| black_box(x.overflowing_shl_vartime(1024 + 10)), BatchSize::SmallInput, ) }); @@ -93,13 +97,17 @@ fn bench_shl(c: &mut Criterion) { group.bench_function("shl_vartime_wide, large, U2048", |b| { b.iter_batched( || (U2048::ONE, U2048::ONE), - |x| Uint::shl_vartime_wide(x, 1024 + 10), + |x| Uint::overflowing_shl_vartime_wide(x, 1024 + 10), BatchSize::SmallInput, ) }); group.bench_function("shl, U2048", |b| { - b.iter_batched(|| U2048::ONE, |x| x.shl(1024 + 10), BatchSize::SmallInput) + b.iter_batched( + || U2048::ONE, + |x| x.overflowing_shl(1024 + 10), + BatchSize::SmallInput, + ) }); group.finish(); @@ -109,13 +117,17 @@ fn bench_shr(c: &mut Criterion) { let mut group = c.benchmark_group("right shift"); group.bench_function("shr_vartime, small, U2048", |b| { - b.iter_batched(|| U2048::ONE, |x| x.shr_vartime(10), BatchSize::SmallInput) + b.iter_batched( + || U2048::ONE, + |x| x.overflowing_shr_vartime(10), + BatchSize::SmallInput, + ) }); group.bench_function("shr_vartime, large, U2048", |b| { b.iter_batched( || U2048::ONE, - |x| x.shr_vartime(1024 + 10), + |x| x.overflowing_shr_vartime(1024 + 10), BatchSize::SmallInput, ) }); @@ -123,13 +135,17 @@ fn bench_shr(c: &mut Criterion) { group.bench_function("shr_vartime_wide, large, U2048", |b| { b.iter_batched( || (U2048::ONE, U2048::ONE), - |x| Uint::shr_vartime_wide(x, 1024 + 10), + |x| Uint::overflowing_shr_vartime_wide(x, 1024 + 10), BatchSize::SmallInput, ) }); group.bench_function("shr, U2048", |b| { - b.iter_batched(|| U2048::ONE, |x| x.shr(1024 + 10), BatchSize::SmallInput) + b.iter_batched( + || U2048::ONE, + |x| x.overflowing_shr(1024 + 10), + BatchSize::SmallInput, + ) }); group.finish(); diff --git a/src/lib.rs b/src/lib.rs index ece30708..5b806322 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -45,7 +45,7 @@ //! U256::from_be_hex("ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551"); //! //! // Compute `MODULUS` shifted right by 1 at compile time -//! pub const MODULUS_SHR1: U256 = MODULUS.shr(1).0; +//! pub const MODULUS_SHR1: U256 = MODULUS.shr(1); //! ``` //! //! Note that large constant computations may accidentally trigger a the `const_eval_limit` of the compiler. diff --git a/src/uint/boxed/div.rs b/src/uint/boxed/div.rs index d82bb982..5d20a232 100644 --- a/src/uint/boxed/div.rs +++ b/src/uint/boxed/div.rs @@ -78,7 +78,7 @@ impl BoxedUint { let bits_precision = self.bits_precision(); let mut rem = self.clone(); let mut quo = Self::zero_with_precision(bits_precision); - let (mut c, _overflow) = rhs.shl(bits_precision - mb); + let (mut c, _overflow) = rhs.overflowing_shl(bits_precision - mb); let mut i = bits_precision; let mut done = Choice::from(0u8); diff --git a/src/uint/boxed/shl.rs b/src/uint/boxed/shl.rs index 3c25e68b..0aea2642 100644 --- a/src/uint/boxed/shl.rs +++ b/src/uint/boxed/shl.rs @@ -9,7 +9,7 @@ impl BoxedUint { /// /// Returns a zero and a truthy `Choice` if `shift >= self.bits_precision()`, /// or the result and a falsy `Choice` otherwise. - pub fn shl(&self, shift: u32) -> (Self, Choice) { + pub fn overflowing_shl(&self, shift: u32) -> (Self, Choice) { let mut result = self.clone(); let overflow = result.overflowing_shl_assign(shift); (result, overflow) @@ -125,7 +125,7 @@ impl Shl for &BoxedUint { type Output = BoxedUint; fn shl(self, shift: u32) -> BoxedUint { - let (result, overflow) = self.shl(shift); + let (result, overflow) = self.overflowing_shl(shift); assert!(!bool::from(overflow), "attempt to shift left with overflow"); result } @@ -154,8 +154,8 @@ mod tests { fn shl() { let one = BoxedUint::one_with_precision(128); - assert_eq!(BoxedUint::from(2u8), one.shl(1).0); - assert_eq!(BoxedUint::from(4u8), one.shl(2).0); + assert_eq!(BoxedUint::from(2u8), &one << 1); + assert_eq!(BoxedUint::from(4u8), &one << 2); assert_eq!( BoxedUint::from(0x80000000000000000u128), one.shl_vartime(67).unwrap() diff --git a/src/uint/boxed/shr.rs b/src/uint/boxed/shr.rs index e9d2c478..ffd293dd 100644 --- a/src/uint/boxed/shr.rs +++ b/src/uint/boxed/shr.rs @@ -9,7 +9,7 @@ impl BoxedUint { /// /// Returns a zero and a truthy `Choice` if `shift >= self.bits_precision()`, /// or the result and a falsy `Choice` otherwise. - pub fn shr(&self, shift: u32) -> (Self, Choice) { + pub fn overflowing_shr(&self, shift: u32) -> (Self, Choice) { let mut result = self.clone(); let overflow = result.overflowing_shr_assign(shift); (result, overflow) @@ -129,7 +129,7 @@ impl Shr for &BoxedUint { type Output = BoxedUint; fn shr(self, shift: u32) -> BoxedUint { - let (result, overflow) = self.shr(shift); + let (result, overflow) = self.overflowing_shr(shift); assert!( !bool::from(overflow), "attempt to shift right with overflow" @@ -163,10 +163,10 @@ mod tests { #[test] fn shr() { let n = BoxedUint::from(0x80000000000000000u128); - assert_eq!(BoxedUint::zero(), n.shr(68).0); - assert_eq!(BoxedUint::one(), n.shr(67).0); - assert_eq!(BoxedUint::from(2u8), n.shr(66).0); - assert_eq!(BoxedUint::from(4u8), n.shr(65).0); + assert_eq!(BoxedUint::zero(), &n >> 68); + assert_eq!(BoxedUint::one(), &n >> 67); + assert_eq!(BoxedUint::from(2u8), &n >> 66); + assert_eq!(BoxedUint::from(4u8), &n >> 65); } #[test] diff --git a/src/uint/div.rs b/src/uint/div.rs index 98f6f3c8..2ceea32c 100644 --- a/src/uint/div.rs +++ b/src/uint/div.rs @@ -28,7 +28,7 @@ impl Uint { let mut rem = *self; let mut quo = Self::ZERO; // If there is overflow, it means `mb == 0`, so `rhs == 0`. - let (mut c, _overflow) = rhs.0.shl(Self::BITS - mb); + let (mut c, _overflow) = rhs.0.overflowing_shl(Self::BITS - mb); let mut i = Self::BITS; let mut done = ConstChoice::FALSE; @@ -64,7 +64,7 @@ impl Uint { let mut rem = *self; let mut quo = Self::ZERO; // If there is overflow, it means `mb == 0`, so `rhs == 0`. - let (mut c, _overflow) = rhs.0.shl_vartime(bd); + let (mut c, _overflow) = rhs.0.overflowing_shl_vartime(bd); loop { let (mut r, borrow) = rem.sbb(&c, Limb::ZERO); @@ -92,7 +92,7 @@ impl Uint { let mb = rhs.0.bits_vartime(); let mut bd = Self::BITS - mb; let mut rem = *self; - let (mut c, _overflow) = rhs.0.shl_vartime(bd); + let (mut c, _overflow) = rhs.0.overflowing_shl_vartime(bd); loop { let (r, borrow) = rem.sbb(&c, Limb::ZERO); @@ -123,7 +123,7 @@ impl Uint { let (mut lower, mut upper) = lower_upper; // Factor of the modulus, split into two halves - let (mut c, _overflow) = Self::shl_vartime_wide((rhs.0, Uint::ZERO), bd); + let (mut c, _overflow) = Self::overflowing_shl_vartime_wide((rhs.0, Uint::ZERO), bd); loop { let (lower_sub, borrow) = lower.sbb(&c.0, Limb::ZERO); @@ -135,7 +135,7 @@ impl Uint { break; } bd -= 1; - let (new_c, _overflow) = Self::shr_vartime_wide(c, 1); + let (new_c, _overflow) = Self::overflowing_shr_vartime_wide(c, 1); c = new_c; } @@ -634,8 +634,8 @@ mod tests { fn div() { let mut rng = ChaChaRng::from_seed([7u8; 32]); for _ in 0..25 { - let (num, _) = U256::random(&mut rng).shr_vartime(128); - let den = NonZero::new(U256::random(&mut rng).shr_vartime(128).0).unwrap(); + let (num, _) = U256::random(&mut rng).overflowing_shr_vartime(128); + let den = NonZero::new(U256::random(&mut rng).overflowing_shr_vartime(128).0).unwrap(); let n = num.checked_mul(den.as_ref()); if n.is_some().into() { let (q, _) = n.unwrap().div_rem(&den); @@ -724,7 +724,7 @@ mod tests { for _ in 0..25 { let num = U256::random(&mut rng); let k = rng.next_u32() % 256; - let (den, _) = U256::ONE.shl_vartime(k); + let (den, _) = U256::ONE.overflowing_shl_vartime(k); let a = num.rem2k(k); let e = num.wrapping_rem(&den); diff --git a/src/uint/inv_mod.rs b/src/uint/inv_mod.rs index 80e7ecbe..c0ba8948 100644 --- a/src/uint/inv_mod.rs +++ b/src/uint/inv_mod.rs @@ -30,7 +30,7 @@ impl Uint { // b_{i+1} = (b_i - a * X_i) / 2 b = Self::select(&b, &b.wrapping_sub(self), x_i_choice).shr1(); // Store the X_i bit in the result (x = x | (1 << X_i)) - let (shifted, _overflow) = Uint::from_word(x_i).shl_vartime(i); + let (shifted, _overflow) = Uint::from_word(x_i).overflowing_shl_vartime(i); x = x.bitor(&shifted); i += 1; @@ -162,7 +162,7 @@ impl Uint { pub const fn inv_mod(&self, modulus: &Self) -> (Self, ConstChoice) { // Decompose `modulus = s * 2^k` where `s` is odd let k = modulus.trailing_zeros(); - let (s, _overflow) = modulus.shr(k); + let (s, _overflow) = modulus.overflowing_shr(k); // Decompose `self` into RNS with moduli `2^k` and `s` and calculate the inverses. // Using the fact that `(z^{-1} mod (m1 * m2)) mod m1 == z^{-1} mod m1` @@ -178,7 +178,7 @@ impl Uint { // This part is mod 2^k // Will not overflow since `modulus` is nonzero, and therefore `k < BITS`. - let (shifted, _overflow) = Uint::ONE.shl(k); + let (shifted, _overflow) = Uint::ONE.overflowing_shl(k); let mask = shifted.wrapping_sub(&Uint::ONE); let t = (b.wrapping_sub(&a).wrapping_mul(&m_odd_inv)).bitand(&mask); diff --git a/src/uint/mul.rs b/src/uint/mul.rs index 54d78cc5..5347ead9 100644 --- a/src/uint/mul.rs +++ b/src/uint/mul.rs @@ -135,7 +135,7 @@ impl Uint { // Double the current result, this accounts for the other half of the multiplication grid. // TODO: The top word is empty so we can also use a special purpose shl. - (lo, hi) = Self::shl_vartime_wide((lo, hi), 1).0; + (lo, hi) = Self::overflowing_shl_vartime_wide((lo, hi), 1).0; // Handle the diagonal of the multiplication grid, which finishes the multiplication grid. let mut carry = Limb::ZERO; diff --git a/src/uint/shl.rs b/src/uint/shl.rs index 23c74ade..03a5b6e1 100644 --- a/src/uint/shl.rs +++ b/src/uint/shl.rs @@ -5,9 +5,22 @@ use core::ops::{Shl, ShlAssign}; impl Uint { /// Computes `self << shift`. + /// + /// Panics if `shift >= Self::BITS`. + pub const fn shl(&self, shift: u32) -> Self { + let (result, overflow) = self.overflowing_shl(shift); + assert!( + !overflow.is_true_vartime(), + "attempt to shift left with overflow" + ); + result + } + + /// Computes `self << shift`. + /// /// If `shift >= Self::BITS`, returns zero as the first tuple element, /// and `ConstChoice::TRUE` as the second element. - pub const fn shl(&self, shift: u32) -> (Self, ConstChoice) { + pub const fn overflowing_shl(&self, shift: u32) -> (Self, ConstChoice) { // `floor(log2(BITS - 1))` is the number of bits in the representation of `shift` // (which lies in range `0 <= shift < BITS`). let shift_bits = u32::BITS - (Self::BITS - 1).leading_zeros(); @@ -17,7 +30,7 @@ impl Uint { let mut i = 0; while i < shift_bits { let bit = ConstChoice::from_u32_lsb((shift >> i) & 1); - result = Uint::select(&result, &result.shl_vartime(1 << i).0, bit); + result = Uint::select(&result, &result.overflowing_shl_vartime(1 << i).0, bit); i += 1; } @@ -25,6 +38,7 @@ impl Uint { } /// Computes `self << shift`. + /// /// If `shift >= Self::BITS`, returns zero as the first tuple element, /// and `ConstChoice::TRUE` as the second element. /// @@ -33,7 +47,7 @@ impl Uint { /// When used with a fixed `shift`, this function is constant-time with respect /// to `self`. #[inline(always)] - pub const fn shl_vartime(&self, shift: u32) -> (Self, ConstChoice) { + pub const fn overflowing_shl_vartime(&self, shift: u32) -> (Self, ConstChoice) { let mut limbs = [Limb::ZERO; LIMBS]; if shift >= Self::BITS { @@ -68,6 +82,7 @@ impl Uint { } /// Computes a left shift on a wide input as `(lo, hi)`. + /// /// If `shift >= Self::BITS`, returns a tuple of zeros as the first element, /// and `ConstChoice::TRUE` as the second element. /// @@ -76,7 +91,7 @@ impl Uint { /// When used with a fixed `shift`, this function is constant-time with respect /// to `self`. #[inline(always)] - pub const fn shl_vartime_wide( + pub const fn overflowing_shl_vartime_wide( lower_upper: (Self, Self), shift: u32, ) -> ((Self, Self), ConstChoice) { @@ -84,12 +99,12 @@ impl Uint { if shift >= 2 * Self::BITS { ((Self::ZERO, Self::ZERO), ConstChoice::TRUE) } else if shift >= Self::BITS { - let (upper, _) = lower.shl_vartime(shift - Self::BITS); + let (upper, _) = lower.overflowing_shl_vartime(shift - Self::BITS); ((Self::ZERO, upper), ConstChoice::FALSE) } else { - let (new_lower, _) = lower.shl_vartime(shift); - let (upper_lo, _) = lower.shr_vartime(Self::BITS - shift); - let (upper_hi, _) = upper.shl_vartime(shift); + let (new_lower, _) = lower.overflowing_shl_vartime(shift); + let (upper_lo, _) = lower.overflowing_shr_vartime(Self::BITS - shift); + let (upper_hi, _) = upper.overflowing_shl_vartime(shift); ((new_lower, upper_lo.bitor(&upper_hi)), ConstChoice::FALSE) } } @@ -118,6 +133,11 @@ impl Uint { (Uint::::new(limbs), Limb(carry)) } + /// Computes `self << 1` in constant-time. + pub(crate) const fn shl1(&self) -> Self { + self.shl1_with_carry().0 + } + /// Computes `self << 1` in constant-time, returning [`ConstChoice::TRUE`] /// if the most significant bit was set, and [`ConstChoice::FALSE`] otherwise. #[inline(always)] @@ -134,12 +154,6 @@ impl Uint { (ret, ConstChoice::from_word_lsb(carry.0)) } - - /// Computes `self << 1` in constant-time. - pub(crate) const fn shl1(&self) -> Self { - // TODO(tarcieri): optimized implementation - self.shl1_with_carry().0 - } } impl Shl for Uint { @@ -154,12 +168,7 @@ impl Shl for &Uint { type Output = Uint; fn shl(self, shift: u32) -> Uint { - let (result, overflow) = Uint::::shl(self, shift); - assert!( - !overflow.is_true_vartime(), - "attempt to shift left with overflow" - ); - result + Uint::::shl(self, shift) } } @@ -222,8 +231,11 @@ mod tests { #[test] fn shl256_const() { - assert_eq!(N.shl(256), (U256::ZERO, ConstChoice::TRUE)); - assert_eq!(N.shl_vartime(256), (U256::ZERO, ConstChoice::TRUE)); + assert_eq!(N.overflowing_shl(256), (U256::ZERO, ConstChoice::TRUE)); + assert_eq!( + N.overflowing_shl_vartime(256), + (U256::ZERO, ConstChoice::TRUE) + ); } #[test] @@ -240,11 +252,11 @@ mod tests { #[test] fn shl_wide_1_1_128() { assert_eq!( - Uint::shl_vartime_wide((U128::ONE, U128::ONE), 128), + Uint::overflowing_shl_vartime_wide((U128::ONE, U128::ONE), 128), ((U128::ZERO, U128::ONE), ConstChoice::FALSE) ); assert_eq!( - Uint::shl_vartime_wide((U128::ONE, U128::ONE), 128), + Uint::overflowing_shl_vartime_wide((U128::ONE, U128::ONE), 128), ((U128::ZERO, U128::ONE), ConstChoice::FALSE) ); } @@ -252,7 +264,7 @@ mod tests { #[test] fn shl_wide_max_0_1() { assert_eq!( - Uint::shl_vartime_wide((U128::MAX, U128::ZERO), 1), + Uint::overflowing_shl_vartime_wide((U128::MAX, U128::ZERO), 1), ( (U128::MAX.sbb(&U128::ONE, Limb::ZERO).0, U128::ONE), ConstChoice::FALSE @@ -263,7 +275,7 @@ mod tests { #[test] fn shl_wide_max_max_256() { assert_eq!( - Uint::shl_vartime_wide((U128::MAX, U128::MAX), 256), + Uint::overflowing_shl_vartime_wide((U128::MAX, U128::MAX), 256), ((U128::ZERO, U128::ZERO), ConstChoice::TRUE) ); } diff --git a/src/uint/shr.rs b/src/uint/shr.rs index 3b0c83c2..47f2f154 100644 --- a/src/uint/shr.rs +++ b/src/uint/shr.rs @@ -5,9 +5,22 @@ use core::ops::{Shr, ShrAssign}; impl Uint { /// Computes `self >> shift`. + /// + /// Panics if `shift >= Self::BITS`. + pub const fn shr(&self, shift: u32) -> Self { + let (result, overflow) = self.overflowing_shr(shift); + assert!( + !overflow.is_true_vartime(), + "attempt to shift right with overflow" + ); + result + } + + /// Computes `self >> shift`. + /// /// If `shift >= Self::BITS`, returns zero as the first tuple element, /// and `ConstChoice::TRUE` as the second element. - pub const fn shr(&self, shift: u32) -> (Self, ConstChoice) { + pub const fn overflowing_shr(&self, shift: u32) -> (Self, ConstChoice) { // `floor(log2(BITS - 1))` is the number of bits in the representation of `shift` // (which lies in range `0 <= shift < BITS`). let shift_bits = u32::BITS - (Self::BITS - 1).leading_zeros(); @@ -17,7 +30,7 @@ impl Uint { let mut i = 0; while i < shift_bits { let bit = ConstChoice::from_u32_lsb((shift >> i) & 1); - result = Uint::select(&result, &result.shr_vartime(1 << i).0, bit); + result = Uint::select(&result, &result.overflowing_shr_vartime(1 << i).0, bit); i += 1; } @@ -25,6 +38,7 @@ impl Uint { } /// Computes `self >> shift`. + /// /// If `shift >= Self::BITS`, returns zero as the first tuple element, /// and `ConstChoice::TRUE` as the second element. /// @@ -33,7 +47,7 @@ impl Uint { /// When used with a fixed `shift`, this function is constant-time with respect /// to `self`. #[inline(always)] - pub const fn shr_vartime(&self, shift: u32) -> (Self, ConstChoice) { + pub const fn overflowing_shr_vartime(&self, shift: u32) -> (Self, ConstChoice) { let mut limbs = [Limb::ZERO; LIMBS]; if shift >= Self::BITS { @@ -67,6 +81,7 @@ impl Uint { } /// Computes a right shift on a wide input as `(lo, hi)`. + /// /// If `shift >= Self::BITS`, returns a tuple of zeros as the first element, /// and `ConstChoice::TRUE` as the second element. /// @@ -75,7 +90,7 @@ impl Uint { /// When used with a fixed `shift`, this function is constant-time with respect /// to `self`. #[inline(always)] - pub const fn shr_vartime_wide( + pub const fn overflowing_shr_vartime_wide( lower_upper: (Self, Self), shift: u32, ) -> ((Self, Self), ConstChoice) { @@ -83,16 +98,21 @@ impl Uint { if shift >= 2 * Self::BITS { ((Self::ZERO, Self::ZERO), ConstChoice::TRUE) } else if shift >= Self::BITS { - let (lower, _) = upper.shr_vartime(shift - Self::BITS); + let (lower, _) = upper.overflowing_shr_vartime(shift - Self::BITS); ((lower, Self::ZERO), ConstChoice::FALSE) } else { - let (new_upper, _) = upper.shr_vartime(shift); - let (lower_hi, _) = upper.shl_vartime(Self::BITS - shift); - let (lower_lo, _) = lower.shr_vartime(shift); + let (new_upper, _) = upper.overflowing_shr_vartime(shift); + let (lower_hi, _) = upper.overflowing_shl_vartime(Self::BITS - shift); + let (lower_lo, _) = lower.overflowing_shr_vartime(shift); ((lower_lo.bitor(&lower_hi), new_upper), ConstChoice::FALSE) } } + /// Computes `self >> 1` in constant-time. + pub(crate) const fn shr1(&self) -> Self { + self.shr1_with_carry().0 + } + /// Computes `self >> 1` in constant-time, returning [`ConstChoice::TRUE`] /// if the least significant bit was set, and [`ConstChoice::FALSE`] otherwise. #[inline(always)] @@ -109,12 +129,6 @@ impl Uint { (ret, ConstChoice::from_word_lsb(carry.0 >> Limb::HI_BIT)) } - - /// Computes `self >> 1` in constant-time. - pub(crate) const fn shr1(&self) -> Self { - // TODO(tarcieri): optimized implementation - self.shr1_with_carry().0 - } } impl Shr for Uint { @@ -129,12 +143,7 @@ impl Shr for &Uint { type Output = Uint; fn shr(self, shift: u32) -> Uint { - let (result, overflow) = Uint::::shr(self, shift); - assert!( - !overflow.is_true_vartime(), - "attempt to shift right with overflow" - ); - result + Uint::::shr(self, shift) } } @@ -162,8 +171,11 @@ mod tests { #[test] fn shr256_const() { - assert_eq!(N.shr(256), (U256::ZERO, ConstChoice::TRUE)); - assert_eq!(N.shr_vartime(256), (U256::ZERO, ConstChoice::TRUE)); + assert_eq!(N.overflowing_shr(256), (U256::ZERO, ConstChoice::TRUE)); + assert_eq!( + N.overflowing_shr_vartime(256), + (U256::ZERO, ConstChoice::TRUE) + ); } #[test] @@ -175,7 +187,7 @@ mod tests { #[test] fn shr_wide_1_1_128() { assert_eq!( - Uint::shr_vartime_wide((U128::ONE, U128::ONE), 128), + Uint::overflowing_shr_vartime_wide((U128::ONE, U128::ONE), 128), ((U128::ONE, U128::ZERO), ConstChoice::FALSE) ); } @@ -183,7 +195,7 @@ mod tests { #[test] fn shr_wide_0_max_1() { assert_eq!( - Uint::shr_vartime_wide((U128::ZERO, U128::MAX), 1), + Uint::overflowing_shr_vartime_wide((U128::ZERO, U128::MAX), 1), ((U128::ONE << 127, U128::MAX >> 1), ConstChoice::FALSE) ); } @@ -191,7 +203,7 @@ mod tests { #[test] fn shr_wide_max_max_256() { assert_eq!( - Uint::shr_vartime_wide((U128::MAX, U128::MAX), 256), + Uint::overflowing_shr_vartime_wide((U128::MAX, U128::MAX), 256), ((U128::ZERO, U128::ZERO), ConstChoice::TRUE) ); } diff --git a/src/uint/sqrt.rs b/src/uint/sqrt.rs index 5dfdb071..e402bd01 100644 --- a/src/uint/sqrt.rs +++ b/src/uint/sqrt.rs @@ -17,7 +17,7 @@ impl Uint { // The initial guess: `x_0 = 2^ceil(b/2)`, where `2^(b-1) <= self < b`. // Will not overflow since `b <= BITS`. - let (mut x, _overflow) = Self::ONE.shl((self.bits() + 1) >> 1); // ≥ √(`self`) + let (mut x, _overflow) = Self::ONE.overflowing_shl((self.bits() + 1) >> 1); // ≥ √(`self`) // Repeat enough times to guarantee result has stabilized. let mut i = 0; @@ -53,7 +53,7 @@ impl Uint { // The initial guess: `x_0 = 2^ceil(b/2)`, where `2^(b-1) <= self < b`. // Will not overflow since `b <= BITS`. - let (mut x, _overflow) = Self::ONE.shl((self.bits() + 1) >> 1); // ≥ √(`self`) + let (mut x, _overflow) = Self::ONE.overflowing_shl((self.bits() + 1) >> 1); // ≥ √(`self`) // Stop right away if `x` is zero to avoid divizion by zero. while !x.cmp_vartime(&Self::ZERO).is_eq() { diff --git a/tests/boxed_uint_proptests.rs b/tests/boxed_uint_proptests.rs index 1e9816cf..52b45c88 100644 --- a/tests/boxed_uint_proptests.rs +++ b/tests/boxed_uint_proptests.rs @@ -222,7 +222,7 @@ proptest! { let shift = u32::from(shift) % (a.bits_precision() * 2); let expected = to_uint((a_bi << shift as usize) & ((BigUint::one() << a.bits_precision() as usize) - BigUint::one())); - let (actual, overflow) = a.shl(shift); + let (actual, overflow) = a.overflowing_shl(shift); assert_eq!(expected, actual); if shift >= a.bits_precision() { @@ -257,7 +257,7 @@ proptest! { let shift = u32::from(shift) % (a.bits_precision() * 2); let expected = to_uint(a_bi >> shift as usize); - let (actual, overflow) = a.shr(shift); + let (actual, overflow) = a.overflowing_shr(shift); assert_eq!(expected, actual); if shift >= a.bits_precision() { diff --git a/tests/uint_proptests.rs b/tests/uint_proptests.rs index 2430c70a..2ccc3bd0 100644 --- a/tests/uint_proptests.rs +++ b/tests/uint_proptests.rs @@ -64,7 +64,7 @@ proptest! { let shift = u32::from(shift) % (U256::BITS * 2); let expected = to_uint((a_bi << shift as usize) & ((BigUint::one() << U256::BITS as usize) - BigUint::one())); - let (actual, overflow) = a.shl_vartime(shift.into()); + let (actual, overflow) = a.overflowing_shl_vartime(shift.into()); assert_eq!(expected, actual); if shift >= U256::BITS { @@ -81,7 +81,7 @@ proptest! { let shift = u32::from(shift) % (U256::BITS * 2); let expected = to_uint((a_bi << shift as usize) & ((BigUint::one() << U256::BITS as usize) - BigUint::one())); - let (actual, overflow) = a.shl(shift); + let (actual, overflow) = a.overflowing_shl(shift); assert_eq!(expected, actual); if shift >= U256::BITS { @@ -98,7 +98,7 @@ proptest! { let shift = u32::from(shift) % (U256::BITS * 2); let expected = to_uint(a_bi >> shift as usize); - let (actual, overflow) = a.shr_vartime(shift); + let (actual, overflow) = a.overflowing_shr_vartime(shift); assert_eq!(expected, actual); if shift >= U256::BITS { @@ -115,7 +115,7 @@ proptest! { let shift = u32::from(shift) % (U256::BITS * 2); let expected = to_uint(a_bi >> shift as usize); - let (actual, overflow) = a.shr(shift); + let (actual, overflow) = a.overflowing_shr(shift); assert_eq!(expected, actual); if shift >= U256::BITS {