@@ -69,14 +69,26 @@ impl Inverter for BoxedBernsteinYangInverter {
69
69
}
70
70
}
71
71
72
+ /// Compute the number of unsaturated limbs needed to represent a saturated integer with the given
73
+ /// number of saturated limbs.
74
+ fn unsat_nlimbs_for_sat_nlimbs ( saturated_nlimbs : usize ) -> usize {
75
+ let saturated_nlimbs = if Word :: BITS == 32 && saturated_nlimbs == 1 {
76
+ 2
77
+ } else {
78
+ saturated_nlimbs
79
+ } ;
80
+
81
+ bernstein_yang_nlimbs ! ( saturated_nlimbs * Limb :: BITS as usize )
82
+ }
83
+
72
84
/// Returns the greatest common divisor (GCD) of the two given numbers.
73
85
pub ( crate ) fn gcd ( f : & BoxedUint , g : & BoxedUint ) -> BoxedUint {
74
- let nlimbs = bernstein_yang_nlimbs ! ( max( f. nlimbs( ) , g. nlimbs( ) ) * Limb :: BITS as usize ) ;
75
-
86
+ let nlimbs = unsat_nlimbs_for_sat_nlimbs ( max ( f. nlimbs ( ) , g. nlimbs ( ) ) ) ;
76
87
let bits_precision = f. bits_precision ( ) ;
88
+
77
89
let inverse = inv_mod2_62 ( f. as_words ( ) ) ;
78
- let f = BoxedUnsatInt :: from ( f ) . widen ( nlimbs) ;
79
- let mut g = BoxedUnsatInt :: from ( g ) . widen ( nlimbs) ;
90
+ let f = BoxedUnsatInt :: from_uint_widened ( f , nlimbs) ;
91
+ let mut g = BoxedUnsatInt :: from_uint_widened ( g , nlimbs) ;
80
92
let mut d = BoxedUnsatInt :: zero ( nlimbs) ;
81
93
let e = BoxedUnsatInt :: one ( nlimbs) ;
82
94
@@ -89,12 +101,12 @@ pub(crate) fn gcd(f: &BoxedUint, g: &BoxedUint) -> BoxedUint {
89
101
///
90
102
/// Variable time with respect to `g`.
91
103
pub ( crate ) fn gcd_vartime ( f : & BoxedUint , g : & BoxedUint ) -> BoxedUint {
92
- let nlimbs = bernstein_yang_nlimbs ! ( max( f. nlimbs( ) , g. nlimbs( ) ) * Limb :: BITS as usize ) ;
93
-
104
+ let nlimbs = unsat_nlimbs_for_sat_nlimbs ( max ( f. nlimbs ( ) , g. nlimbs ( ) ) ) ;
94
105
let bits_precision = f. bits_precision ( ) ;
106
+
95
107
let inverse = inv_mod2_62 ( f. as_words ( ) ) ;
96
- let f = BoxedUnsatInt :: from ( f ) . widen ( nlimbs) ;
97
- let mut g = BoxedUnsatInt :: from ( g ) . widen ( nlimbs) ;
108
+ let f = BoxedUnsatInt :: from_uint_widened ( f , nlimbs) ;
109
+ let mut g = BoxedUnsatInt :: from_uint_widened ( g , nlimbs) ;
98
110
let mut d = BoxedUnsatInt :: zero ( nlimbs) ;
99
111
let e = BoxedUnsatInt :: one ( nlimbs) ;
100
112
@@ -238,15 +250,31 @@ pub(crate) struct BoxedUnsatInt(Box<[u64]>);
238
250
///
239
251
/// The ordering of the chunks in these arrays is little-endian.
240
252
impl From < & BoxedUint > for BoxedUnsatInt {
241
- #[ allow( trivial_numeric_casts) ]
242
253
fn from ( input : & BoxedUint ) -> BoxedUnsatInt {
243
- let saturated_nlimbs = if Word :: BITS == 32 && input. nlimbs ( ) == 1 {
244
- 2
245
- } else {
246
- input. nlimbs ( )
247
- } ;
254
+ Self :: from_uint_widened ( input, unsat_nlimbs_for_sat_nlimbs ( input. nlimbs ( ) ) )
255
+ }
256
+ }
257
+
258
+ impl BoxedUnsatInt {
259
+ /// Number of bits in each limb.
260
+ pub const LIMB_BITS : usize = 62 ;
248
261
249
- let nlimbs = bernstein_yang_nlimbs ! ( saturated_nlimbs * Limb :: BITS as usize ) ;
262
+ /// Mask, in which the 62 lowest bits are 1.
263
+ pub const MASK : u64 = u64:: MAX >> ( 64 - Self :: LIMB_BITS ) ;
264
+
265
+ /// Convert from 32/64-bit saturated representation used by `BoxedUint` to the 62-bit
266
+ /// unsaturated representation used by `BoxedUnsatInt`.
267
+ ///
268
+ /// Returns a big unsigned integer as an array of 62-bit chunks, which is equal modulo
269
+ /// 2 ^ (62 * S) to the input big unsigned integer stored as an array of 64-bit chunks.
270
+ ///
271
+ /// The ordering of the chunks in these arrays is little-endian.
272
+ ///
273
+ /// The `nlimbs` parameter defines the number of unsaturated limbs in the output.
274
+ /// It's provided explicitly so multiple values can be padded to the same size.
275
+ #[ allow( trivial_numeric_casts) ]
276
+ fn from_uint_widened ( input : & BoxedUint , nlimbs : usize ) -> BoxedUnsatInt {
277
+ debug_assert ! ( nlimbs >= unsat_nlimbs_for_sat_nlimbs( input. nlimbs( ) ) ) ;
250
278
251
279
// Workaround for 32-bit platforms: if the input is a single limb, it will be smaller input
252
280
// than is usable for Bernstein-Yang with is currently natively 64-bits on all targets
@@ -263,14 +291,6 @@ impl From<&BoxedUint> for BoxedUnsatInt {
263
291
impl_limb_convert ! ( Word , Word :: BITS as usize , input, u64 , 62 , output) ;
264
292
Self ( output. into ( ) )
265
293
}
266
- }
267
-
268
- impl BoxedUnsatInt {
269
- /// Number of bits in each limb.
270
- pub const LIMB_BITS : usize = 62 ;
271
-
272
- /// Mask, in which the 62 lowest bits are 1.
273
- pub const MASK : u64 = u64:: MAX >> ( 64 - Self :: LIMB_BITS ) ;
274
294
275
295
/// Convert to a `BoxedUint` of the given precision.
276
296
#[ allow( trivial_numeric_casts) ]
0 commit comments