@@ -28,7 +28,7 @@ mod sub_mod;
28
28
#[ cfg( feature = "rand_core" ) ]
29
29
mod rand;
30
30
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 } ;
32
32
use alloc:: { boxed:: Box , vec, vec:: Vec } ;
33
33
use core:: fmt;
34
34
use subtle:: { Choice , ConditionallySelectable , ConstantTimeEq , CtOption } ;
@@ -195,30 +195,6 @@ impl BoxedUint {
195
195
CtOption :: new ( Odd ( self . clone ( ) ) , is_odd)
196
196
}
197
197
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
-
222
198
/// Perform a carry chain-like operation over the limbs of the inputs,
223
199
/// constructing a result from the returned limbs and carry which is
224
200
/// widened to the same width as the widest input.
@@ -271,14 +247,86 @@ impl BoxedUint {
271
247
limbs[ i] = Limb :: conditional_select ( & limbs[ i] , & Limb :: ZERO , choice) ;
272
248
}
273
249
}
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
+ }
274
257
}
275
258
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
+ }
282
330
}
283
331
}
284
332
0 commit comments