@@ -69,14 +69,26 @@ impl Inverter for BoxedBernsteinYangInverter {
6969 }
7070}
7171
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+
7284/// Returns the greatest common divisor (GCD) of the two given numbers.
7385pub ( 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 ( ) ) ) ;
7687 let bits_precision = f. bits_precision ( ) ;
88+
7789 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) ;
8092 let mut d = BoxedUnsatInt :: zero ( nlimbs) ;
8193 let e = BoxedUnsatInt :: one ( nlimbs) ;
8294
@@ -89,12 +101,12 @@ pub(crate) fn gcd(f: &BoxedUint, g: &BoxedUint) -> BoxedUint {
89101///
90102/// Variable time with respect to `g`.
91103pub ( 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 ( ) ) ) ;
94105 let bits_precision = f. bits_precision ( ) ;
106+
95107 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) ;
98110 let mut d = BoxedUnsatInt :: zero ( nlimbs) ;
99111 let e = BoxedUnsatInt :: one ( nlimbs) ;
100112
@@ -238,15 +250,31 @@ pub(crate) struct BoxedUnsatInt(Box<[u64]>);
238250///
239251/// The ordering of the chunks in these arrays is little-endian.
240252impl From < & BoxedUint > for BoxedUnsatInt {
241- #[ allow( trivial_numeric_casts) ]
242253 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 ;
248261
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( ) ) ) ;
250278
251279 // Workaround for 32-bit platforms: if the input is a single limb, it will be smaller input
252280 // than is usable for Bernstein-Yang with is currently natively 64-bits on all targets
@@ -263,14 +291,6 @@ impl From<&BoxedUint> for BoxedUnsatInt {
263291 impl_limb_convert ! ( Word , Word :: BITS as usize , input, u64 , 62 , output) ;
264292 Self ( output. into ( ) )
265293 }
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 ) ;
274294
275295 /// Convert to a `BoxedUint` of the given precision.
276296 #[ allow( trivial_numeric_casts) ]
0 commit comments