Skip to content

Commit 9966a72

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

File tree

11 files changed

+125
-38
lines changed

11 files changed

+125
-38
lines changed

src/modular/boxed_monty_form.rs

+1-1
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

src/modular/safegcd/boxed.rs

+1-1
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,

src/traits.rs

+37
Original file line numberDiff line numberDiff line change
@@ -851,6 +851,43 @@ 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 discarded limbs (if any) are non-zero.
861+
fn resize_unchecked(self, at_least_bits_precision: u32) -> Self::Output;
862+
863+
/// Resizes to the minimum storage that fits `at_least_bits_precision`
864+
/// returning `None` if resizing would result in a truncation of non-zero limbs.
865+
fn try_resize(self, at_least_bits_precision: u32) -> Option<Self::Output>;
866+
867+
/// Resizes to the minimum storage that fits `at_least_bits_precision`
868+
/// panicking if resizing would result in a truncation of non-zero limbs.
869+
fn resize(self, at_least_bits_precision: u32) -> Self::Output {
870+
self.try_resize(at_least_bits_precision)
871+
.unwrap_or_else(|| panic!("Cannot resize without truncation"))
872+
}
873+
874+
/// Widens this type's precision to the given number of bits.
875+
///
876+
/// Panics if `at_least_bits_precision` is smaller than the current precision.
877+
fn widen(self, at_least_bits_precision: u32) -> Self::Output {
878+
//assert!(at_least_bits_precision >= self.bits_precision());
879+
self.resize_unchecked(at_least_bits_precision)
880+
}
881+
882+
/// Shortens this type's precision to the given number of bits.
883+
///
884+
/// Panics if `at_least_bits_precision` is larger than the current precision.
885+
fn shorten(self, at_least_bits_precision: u32) -> Self::Output {
886+
//assert!(at_least_bits_precision <= self.bits_precision());
887+
self.resize_unchecked(at_least_bits_precision)
888+
}
889+
}
890+
854891
/// A representation of an integer optimized for the performance of modular operations.
855892
pub trait Monty:
856893
'static

src/uint/boxed.rs

+79-31
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};
@@ -195,30 +195,6 @@ impl BoxedUint {
195195
CtOption::new(Odd(self.clone()), is_odd)
196196
}
197197

198-
/// Widen this type's precision to the given number of bits.
199-
///
200-
/// Panics if `at_least_bits_precision` is smaller than the current precision.
201-
#[must_use]
202-
pub fn widen(&self, at_least_bits_precision: u32) -> BoxedUint {
203-
assert!(at_least_bits_precision >= self.bits_precision());
204-
205-
let mut ret = BoxedUint::zero_with_precision(at_least_bits_precision);
206-
ret.limbs[..self.nlimbs()].copy_from_slice(&self.limbs);
207-
ret
208-
}
209-
210-
/// Shortens this type's precision to the given number of bits.
211-
///
212-
/// Panics if `at_least_bits_precision` is larger than the current precision.
213-
#[must_use]
214-
pub fn shorten(&self, at_least_bits_precision: u32) -> BoxedUint {
215-
assert!(at_least_bits_precision <= self.bits_precision());
216-
let mut ret = BoxedUint::zero_with_precision(at_least_bits_precision);
217-
let nlimbs = ret.nlimbs();
218-
ret.limbs.copy_from_slice(&self.limbs[..nlimbs]);
219-
ret
220-
}
221-
222198
/// Perform a carry chain-like operation over the limbs of the inputs,
223199
/// constructing a result from the returned limbs and carry which is
224200
/// widened to the same width as the widest input.
@@ -271,14 +247,86 @@ impl BoxedUint {
271247
limbs[i] = Limb::conditional_select(&limbs[i], &Limb::ZERO, choice);
272248
}
273249
}
250+
251+
fn truncation_needed(&self, at_least_bits_precision: u32) -> bool {
252+
let new_len = Self::limbs_for_precision(at_least_bits_precision);
253+
// TODO: technically we just need to know the number of leading zero limbs,
254+
// so this can be done faster. Is the difference worth it?
255+
new_len < self.limbs.len() && self.bits() > at_least_bits_precision
256+
}
274257
}
275258

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))
259+
impl Resize for BoxedUint {
260+
type Output = BoxedUint;
261+
262+
fn resize_unchecked(self, at_least_bits_precision: u32) -> Self::Output {
263+
let new_len = Self::limbs_for_precision(at_least_bits_precision);
264+
if new_len == self.limbs.len() {
265+
self
266+
} else {
267+
let mut limbs = self.limbs.into_vec();
268+
limbs.resize(new_len, Limb::ZERO);
269+
Self::from(limbs)
270+
}
271+
}
272+
273+
fn try_resize(self, at_least_bits_precision: u32) -> Option<BoxedUint> {
274+
if self.truncation_needed(at_least_bits_precision) {
275+
None
276+
} else {
277+
Some(self.resize_unchecked(at_least_bits_precision))
278+
}
279+
}
280+
}
281+
282+
impl Resize for &BoxedUint {
283+
type Output = BoxedUint;
284+
285+
fn resize_unchecked(self, at_least_bits_precision: u32) -> Self::Output {
286+
let mut ret = BoxedUint::zero_with_precision(at_least_bits_precision);
287+
let num_limbs_to_copy = core::cmp::min(ret.limbs.len(), self.limbs.len());
288+
ret.limbs[..num_limbs_to_copy].copy_from_slice(&self.limbs[..num_limbs_to_copy]);
289+
ret
290+
}
291+
292+
fn try_resize(self, at_least_bits_precision: u32) -> Option<BoxedUint> {
293+
if self.truncation_needed(at_least_bits_precision) {
294+
None
295+
} else {
296+
Some(self.resize_unchecked(at_least_bits_precision))
297+
}
298+
}
299+
}
300+
301+
impl Resize for NonZero<BoxedUint> {
302+
type Output = Self;
303+
304+
fn resize_unchecked(self, at_least_bits_precision: u32) -> Self::Output {
305+
NonZero(self.0.widen(at_least_bits_precision))
306+
}
307+
308+
fn try_resize(self, at_least_bits_precision: u32) -> Option<Self::Output> {
309+
if self.0.truncation_needed(at_least_bits_precision) {
310+
None
311+
} else {
312+
Some(self.resize_unchecked(at_least_bits_precision))
313+
}
314+
}
315+
}
316+
317+
impl Resize for &NonZero<BoxedUint> {
318+
type Output = NonZero<BoxedUint>;
319+
320+
fn resize_unchecked(self, at_least_bits_precision: u32) -> Self::Output {
321+
NonZero((&self.0).widen(at_least_bits_precision))
322+
}
323+
324+
fn try_resize(self, at_least_bits_precision: u32) -> Option<Self::Output> {
325+
if self.0.truncation_needed(at_least_bits_precision) {
326+
None
327+
} else {
328+
Some(self.resize_unchecked(at_least_bits_precision))
329+
}
282330
}
283331
}
284332

src/uint/boxed/add.rs

+1
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() {

src/uint/boxed/gcd.rs

+1-1
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() {

src/uint/boxed/mul.rs

+1-1
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,

src/uint/boxed/sub.rs

+1
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() {

tests/boxed_monty_form.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ 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;

tests/boxed_uint.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ mod common;
66

77
use common::to_biguint;
88
use core::cmp::Ordering;
9-
use crypto_bigint::{BitOps, BoxedUint, CheckedAdd, Gcd, Integer, Limb, NonZero};
9+
use crypto_bigint::{BitOps, BoxedUint, CheckedAdd, Gcd, Integer, Limb, NonZero, Resize};
1010
use num_bigint::BigUint;
1111
use num_integer::Integer as _;
1212
use num_modular::ModularUnaryOps;

tests/safegcd.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ use num_traits::One;
1010
use proptest::prelude::*;
1111

1212
#[cfg(feature = "alloc")]
13-
use crypto_bigint::BoxedUint;
13+
use crypto_bigint::{BoxedUint, Resize};
1414

1515
/// Example prime number (NIST P-256 curve order)
1616
const P: Odd<U256> =

0 commit comments

Comments
 (0)