Skip to content

Commit 5d06451

Browse files
committed
Add Resize trait instead of BoxedUint::shorten()/widen()
1 parent 3f21087 commit 5d06451

File tree

12 files changed

+151
-61
lines changed

12 files changed

+151
-61
lines changed

src/modular/boxed_monty_form.rs

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ mod sub;
1111
use super::{ConstMontyParams, Retrieve, div_by_2};
1212
use mul::BoxedMontyMultiplier;
1313

14-
use crate::{BoxedUint, Limb, Monty, Odd, Word};
14+
use crate::{BoxedUint, Limb, Monty, Odd, Resize, Word};
1515
use alloc::sync::Arc;
1616
use subtle::Choice;
1717

@@ -58,8 +58,8 @@ impl BoxedMontyParams {
5858
// `R^2 mod modulus`, used to convert integers to Montgomery form.
5959
let r2 = one
6060
.square()
61-
.rem(&modulus.as_nz_ref().widen(bits_precision * 2))
62-
.shorten(bits_precision);
61+
.rem(&modulus.as_nz_ref().resize_unchecked(bits_precision * 2))
62+
.resize_unchecked(bits_precision);
6363

6464
// The modular inverse should always exist, because it was ensured odd above, which also ensures it's non-zero
6565
let (inv_mod_limb, inv_mod_limb_exists) = modulus.inv_mod2k_vartime(Word::BITS);
@@ -102,10 +102,7 @@ impl BoxedMontyParams {
102102
.wrapping_add(&BoxedUint::one());
103103

104104
// `R^2 mod modulus`, used to convert integers to Montgomery form.
105-
let r2 = one
106-
.square()
107-
.rem_vartime(&modulus.as_nz_ref().widen(bits_precision * 2))
108-
.shorten(bits_precision);
105+
let r2 = one.square().rem_vartime(modulus.as_nz_ref());
109106

110107
// The modular inverse should always exist, because it was ensured odd above, which also ensures it's non-zero
111108
let (inv_mod_limb, inv_mod_limb_exists) = modulus.inv_mod2k_full_vartime(Word::BITS);

src/modular/safegcd/boxed.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
//! See parent module for more information.
55
66
use super::{Matrix, inv_mod2_62, iterations, jump};
7-
use crate::{BoxedUint, Inverter, Limb, Odd, Word};
7+
use crate::{BoxedUint, Inverter, Limb, Odd, Resize, Word};
88
use alloc::boxed::Box;
99
use core::{
1010
cmp::max,
@@ -34,7 +34,7 @@ impl BoxedSafeGcdInverter {
3434
pub fn new(modulus: &Odd<BoxedUint>, adjuster: &BoxedUint) -> Self {
3535
Self {
3636
modulus: BoxedUnsatInt::from(&modulus.0),
37-
adjuster: BoxedUnsatInt::from(&adjuster.widen(modulus.bits_precision())),
37+
adjuster: BoxedUnsatInt::from(&adjuster.resize(modulus.bits_precision())),
3838
inverse: inv_mod2_62(modulus.0.as_words()),
3939
}
4040
}
@@ -339,7 +339,7 @@ impl BoxedUnsatInt {
339339

340340
if shorten {
341341
debug_assert!(ret.bits_vartime() <= 32);
342-
ret.shorten(32)
342+
ret.resize(32)
343343
} else {
344344
ret
345345
}

src/odd.rs

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ use core::{cmp::Ordering, fmt, ops::Deref};
55
use subtle::{Choice, ConditionallySelectable, ConstantTimeEq, CtOption};
66

77
#[cfg(feature = "alloc")]
8-
use crate::BoxedUint;
8+
use crate::{BoxedUint, Resize};
99

1010
#[cfg(feature = "rand_core")]
1111
use crate::{Random, rand_core::TryRngCore};
@@ -150,6 +150,32 @@ impl PartialOrd<Odd<BoxedUint>> for BoxedUint {
150150
}
151151
}
152152

153+
#[cfg(feature = "alloc")]
154+
impl Resize for Odd<BoxedUint> {
155+
type Output = Self;
156+
157+
fn resize_unchecked(self, at_least_bits_precision: u32) -> Self::Output {
158+
Odd(self.0.resize_unchecked(at_least_bits_precision))
159+
}
160+
161+
fn try_resize(self, at_least_bits_precision: u32) -> Option<Self::Output> {
162+
self.0.try_resize(at_least_bits_precision).map(Odd)
163+
}
164+
}
165+
166+
#[cfg(feature = "alloc")]
167+
impl Resize for &Odd<BoxedUint> {
168+
type Output = Odd<BoxedUint>;
169+
170+
fn resize_unchecked(self, at_least_bits_precision: u32) -> Self::Output {
171+
Odd((&self.0).resize_unchecked(at_least_bits_precision))
172+
}
173+
174+
fn try_resize(self, at_least_bits_precision: u32) -> Option<Self::Output> {
175+
(&self.0).try_resize(at_least_bits_precision).map(Odd)
176+
}
177+
}
178+
153179
#[cfg(feature = "rand_core")]
154180
impl<const LIMBS: usize> Random for Odd<Uint<LIMBS>> {
155181
/// Generate a random `Odd<Uint<T>>`.

src/traits.rs

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -851,6 +851,34 @@ pub trait ShrVartime: Sized {
851851
fn wrapping_shr_vartime(&self, shift: u32) -> Self;
852852
}
853853

854+
/// Methods for resizing the allocated storage.
855+
pub trait Resize: Sized {
856+
/// The result of the resizing.
857+
type Output;
858+
859+
/// Resizes to the minimum storage that fits `at_least_bits_precision`
860+
/// without checking if the bit size of `self` is larger than `at_least_bits_precision`.
861+
///
862+
/// Variable-time w.r.t. `at_least_bits_precision`.
863+
fn resize_unchecked(self, at_least_bits_precision: u32) -> Self::Output;
864+
865+
/// Resizes to the minimum storage that fits `at_least_bits_precision`
866+
/// returning `None` if the bit size of `self` is larger than `at_least_bits_precision`.
867+
///
868+
/// Variable-time w.r.t. `at_least_bits_precision`.
869+
fn try_resize(self, at_least_bits_precision: u32) -> Option<Self::Output>;
870+
871+
/// Resizes to the minimum storage that fits `at_least_bits_precision`
872+
/// panicking if the bit size of `self` is larger than `at_least_bits_precision`.
873+
///
874+
/// Variable-time w.r.t. `at_least_bits_precision`.
875+
fn resize(self, at_least_bits_precision: u32) -> Self::Output {
876+
self.try_resize(at_least_bits_precision).unwrap_or_else(|| {
877+
panic!("The bit size of `self` is larger than `at_least_bits_precision`")
878+
})
879+
}
880+
}
881+
854882
/// A representation of an integer optimized for the performance of modular operations.
855883
pub trait Monty:
856884
'static

src/uint/boxed.rs

Lines changed: 71 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ mod sub_mod;
2828
#[cfg(feature = "rand_core")]
2929
mod rand;
3030

31-
use crate::{Integer, Limb, NonZero, Odd, UintRef, Word, Zero, modular::BoxedMontyForm};
31+
use crate::{Integer, Limb, NonZero, Odd, Resize, UintRef, Word, Zero, modular::BoxedMontyForm};
3232
use alloc::{boxed::Box, vec, vec::Vec};
3333
use core::fmt;
3434
use subtle::{Choice, ConditionallySelectable, ConstantTimeEq, CtOption};
@@ -199,6 +199,7 @@ impl BoxedUint {
199199
///
200200
/// Panics if `at_least_bits_precision` is smaller than the current precision.
201201
#[must_use]
202+
#[deprecated(since = "0.7.0", note = "please use `resize` instead")]
202203
pub fn widen(&self, at_least_bits_precision: u32) -> BoxedUint {
203204
assert!(at_least_bits_precision >= self.bits_precision());
204205

@@ -211,6 +212,7 @@ impl BoxedUint {
211212
///
212213
/// Panics if `at_least_bits_precision` is larger than the current precision.
213214
#[must_use]
215+
#[deprecated(since = "0.7.0", note = "please use `resize` instead")]
214216
pub fn shorten(&self, at_least_bits_precision: u32) -> BoxedUint {
215217
assert!(at_least_bits_precision <= self.bits_precision());
216218
let mut ret = BoxedUint::zero_with_precision(at_least_bits_precision);
@@ -271,14 +273,76 @@ impl BoxedUint {
271273
limbs[i] = Limb::conditional_select(&limbs[i], &Limb::ZERO, choice);
272274
}
273275
}
276+
277+
/// Returns `true` if the integer's bit size is smaller or equal to `bits`.
278+
pub(crate) fn is_within_bits(&self, bits: u32) -> bool {
279+
bits >= self.bits_precision() || bits >= self.bits()
280+
}
274281
}
275282

276-
impl NonZero<BoxedUint> {
277-
/// Widen this type's precision to the given number of bits.
278-
///
279-
/// See [`BoxedUint::widen`] for more information, including panic conditions.
280-
pub fn widen(&self, bits_precision: u32) -> Self {
281-
NonZero(self.0.widen(bits_precision))
283+
impl Resize for BoxedUint {
284+
type Output = BoxedUint;
285+
286+
fn resize_unchecked(self, at_least_bits_precision: u32) -> Self::Output {
287+
let new_len = Self::limbs_for_precision(at_least_bits_precision);
288+
if new_len == self.limbs.len() {
289+
self
290+
} else {
291+
let mut limbs = self.limbs.into_vec();
292+
limbs.resize(new_len, Limb::ZERO);
293+
Self::from(limbs)
294+
}
295+
}
296+
297+
fn try_resize(self, at_least_bits_precision: u32) -> Option<BoxedUint> {
298+
if self.is_within_bits(at_least_bits_precision) {
299+
Some(self.resize_unchecked(at_least_bits_precision))
300+
} else {
301+
None
302+
}
303+
}
304+
}
305+
306+
impl Resize for &BoxedUint {
307+
type Output = BoxedUint;
308+
309+
fn resize_unchecked(self, at_least_bits_precision: u32) -> Self::Output {
310+
let mut ret = BoxedUint::zero_with_precision(at_least_bits_precision);
311+
let num_limbs_to_copy = core::cmp::min(ret.limbs.len(), self.limbs.len());
312+
ret.limbs[..num_limbs_to_copy].copy_from_slice(&self.limbs[..num_limbs_to_copy]);
313+
ret
314+
}
315+
316+
fn try_resize(self, at_least_bits_precision: u32) -> Option<BoxedUint> {
317+
if self.is_within_bits(at_least_bits_precision) {
318+
Some(self.resize_unchecked(at_least_bits_precision))
319+
} else {
320+
None
321+
}
322+
}
323+
}
324+
325+
impl Resize for NonZero<BoxedUint> {
326+
type Output = Self;
327+
328+
fn resize_unchecked(self, at_least_bits_precision: u32) -> Self::Output {
329+
NonZero(self.0.resize_unchecked(at_least_bits_precision))
330+
}
331+
332+
fn try_resize(self, at_least_bits_precision: u32) -> Option<Self::Output> {
333+
self.0.try_resize(at_least_bits_precision).map(NonZero)
334+
}
335+
}
336+
337+
impl Resize for &NonZero<BoxedUint> {
338+
type Output = NonZero<BoxedUint>;
339+
340+
fn resize_unchecked(self, at_least_bits_precision: u32) -> Self::Output {
341+
NonZero((&self.0).resize_unchecked(at_least_bits_precision))
342+
}
343+
344+
fn try_resize(self, at_least_bits_precision: u32) -> Option<Self::Output> {
345+
(&self.0).try_resize(at_least_bits_precision).map(NonZero)
282346
}
283347
}
284348

src/uint/boxed/add.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -231,6 +231,7 @@ impl AddAssign<u128> for BoxedUint {
231231
#[allow(clippy::unwrap_used)]
232232
mod tests {
233233
use super::{BoxedUint, CheckedAdd, Limb};
234+
use crate::Resize;
234235

235236
#[test]
236237
fn adc_no_carry() {
@@ -267,7 +268,7 @@ mod tests {
267268

268269
#[test]
269270
fn add_assign() {
270-
let mut h = BoxedUint::one().widen(1024);
271+
let mut h = BoxedUint::one().resize(1024);
271272

272273
h += BoxedUint::one();
273274
}

src/uint/boxed/gcd.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ impl Gcd<BoxedUint> for Odd<BoxedUint> {
4646

4747
#[cfg(test)]
4848
mod tests {
49-
use crate::{BoxedUint, Gcd};
49+
use crate::{BoxedUint, Gcd, Resize};
5050

5151
#[test]
5252
fn gcd_relatively_prime() {
@@ -95,7 +95,7 @@ mod tests {
9595
#[test]
9696
fn gcd_different_sizes() {
9797
// Test that gcd works for boxed Uints with different numbers of limbs
98-
let f = BoxedUint::from(4391633u32).widen(128).to_odd().unwrap();
98+
let f = BoxedUint::from(4391633u32).resize(128).to_odd().unwrap();
9999
let g = BoxedUint::from(2022161u32);
100100
let gcd = f.gcd(&g);
101101
assert_eq!(gcd, BoxedUint::from(1763u32));
@@ -104,7 +104,7 @@ mod tests {
104104
#[test]
105105
fn gcd_vartime_different_sizes() {
106106
// Test that gcd works for boxed Uints with different numbers of limbs
107-
let f = BoxedUint::from(4391633u32).widen(128).to_odd().unwrap();
107+
let f = BoxedUint::from(4391633u32).resize(128).to_odd().unwrap();
108108
let g = BoxedUint::from(2022161u32);
109109
let gcd = f.gcd_vartime(&g);
110110
assert_eq!(gcd, BoxedUint::from(1763u32));

src/uint/boxed/mul.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
//! [`BoxedUint`] multiplication operations.
22
33
use crate::{
4-
BoxedUint, CheckedMul, Limb, WideningMul, Wrapping, WrappingMul, Zero,
4+
BoxedUint, CheckedMul, Limb, Resize, WideningMul, Wrapping, WrappingMul, Zero,
55
uint::mul::{
66
karatsuba::{KARATSUBA_MIN_STARTING_LIMBS, karatsuba_mul_limbs, karatsuba_square_limbs},
77
mul_limbs, square_limbs,
@@ -33,7 +33,7 @@ impl BoxedUint {
3333

3434
/// Perform wrapping multiplication, wrapping to the width of `self`.
3535
pub fn wrapping_mul(&self, rhs: &Self) -> Self {
36-
self.mul(rhs).shorten(self.bits_precision())
36+
self.mul(rhs).resize_unchecked(self.bits_precision())
3737
}
3838

3939
/// Multiply `self` by itself.

src/uint/boxed/sub.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -236,6 +236,7 @@ impl SubAssign<u128> for BoxedUint {
236236
#[allow(clippy::unwrap_used)]
237237
mod tests {
238238
use super::{BoxedUint, CheckedSub, Limb};
239+
use crate::Resize;
239240

240241
#[test]
241242
fn sbb_no_borrow() {
@@ -276,7 +277,7 @@ mod tests {
276277

277278
#[test]
278279
fn sub_assign() {
279-
let mut h = BoxedUint::one().widen(1024);
280+
let mut h = BoxedUint::one().resize(1024);
280281
h -= BoxedUint::one();
281282
}
282283
}

tests/boxed_monty_form.rs

Lines changed: 2 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -6,31 +6,22 @@ mod common;
66

77
use common::to_biguint;
88
use crypto_bigint::{
9-
BoxedUint, Integer, Inverter, Limb, Odd, PrecomputeInverter,
9+
BoxedUint, Integer, Inverter, Limb, Odd, PrecomputeInverter, Resize,
1010
modular::{BoxedMontyForm, BoxedMontyParams},
1111
};
1212
use num_bigint::BigUint;
1313
use num_integer::Integer as _;
1414
use num_modular::ModularUnaryOps;
1515
use proptest::prelude::*;
16-
use std::cmp::Ordering;
1716

1817
fn retrieve_biguint(monty_form: &BoxedMontyForm) -> BigUint {
1918
to_biguint(&monty_form.retrieve())
2019
}
2120

2221
fn reduce(n: &BoxedUint, p: BoxedMontyParams) -> BoxedMontyForm {
23-
let bits_precision = p.modulus().bits_precision();
24-
25-
let n = match n.bits_precision().cmp(&bits_precision) {
26-
Ordering::Less => n.widen(bits_precision),
27-
Ordering::Equal => n.clone(),
28-
Ordering::Greater => n.shorten(bits_precision),
29-
};
30-
3122
let n_reduced = n
3223
.rem_vartime(p.modulus().as_nz_ref())
33-
.widen(p.bits_precision());
24+
.resize(p.bits_precision());
3425

3526
BoxedMontyForm::new(n_reduced, p)
3627
}

0 commit comments

Comments
 (0)