1010
1111#![ allow( clippy:: needless_range_loop) ]
1212
13+ #[ macro_use]
14+ mod macros;
15+
1316use crate :: { ConstChoice , Inverter , Limb , Uint , Word } ;
1417use subtle:: CtOption ;
1518
@@ -59,13 +62,9 @@ impl<const SAT_LIMBS: usize, const UNSAT_LIMBS: usize>
5962 /// Modulus must be odd. Returns `ConstChoice::FALSE` if it is not.
6063 #[ allow( trivial_numeric_casts) ]
6164 pub const fn new ( modulus : & Uint < SAT_LIMBS > , adjuster : & Uint < SAT_LIMBS > ) -> ( Self , ConstChoice ) {
62- if UNSAT_LIMBS != bernstein_yang_nlimbs ! ( SAT_LIMBS * Limb :: BITS as usize ) {
63- panic ! ( "BernsteinYangInverter has incorrect number of limbs" ) ;
64- }
65-
6665 let ret = Self {
67- modulus : Uint62L :: < UNSAT_LIMBS > ( sat_to_unsat :: < UNSAT_LIMBS > ( modulus. as_words ( ) ) ) ,
68- adjuster : Uint62L :: < UNSAT_LIMBS > ( sat_to_unsat :: < UNSAT_LIMBS > ( adjuster. as_words ( ) ) ) ,
66+ modulus : Uint62L :: from_uint ( modulus) ,
67+ adjuster : Uint62L :: from_uint ( adjuster) ,
6968 inverse : inv_mod2_62 ( modulus. as_words ( ) ) ,
7069 } ;
7170
@@ -76,7 +75,7 @@ impl<const SAT_LIMBS: usize, const UNSAT_LIMBS: usize>
7675 /// depending on invertibility of the argument, i.e. its coprimality with the modulus
7776 pub const fn inv ( & self , value : & Uint < SAT_LIMBS > ) -> ( Uint < SAT_LIMBS > , ConstChoice ) {
7877 let ( mut d, mut e) = ( Uint62L :: ZERO , self . adjuster ) ;
79- let mut g = Uint62L :: < UNSAT_LIMBS > ( sat_to_unsat :: < UNSAT_LIMBS > ( value. as_words ( ) ) ) ;
78+ let mut g = Uint62L :: from_uint ( value) ;
8079 let ( mut delta, mut f) = ( 1 , self . modulus ) ;
8180 let mut matrix;
8281
@@ -89,9 +88,9 @@ impl<const SAT_LIMBS: usize, const UNSAT_LIMBS: usize>
8988 // of the integer to be inverted and the modulus the inverter was created for.
9089 // Thus, if "f" is neither 1 nor -1, then the sought inverse does not exist
9190 let antiunit = f. eq ( & Uint62L :: MINUS_ONE ) ;
92- let words = unsat_to_sat :: < SAT_LIMBS > ( & self . norm ( d, antiunit) . 0 ) ;
91+ let ret = self . norm ( d, antiunit) ;
9392 let is_some = ConstChoice :: from_word_lsb ( ( f. eq ( & Uint62L :: ONE ) || antiunit) as Word ) ;
94- ( Uint :: from_words ( words ) , is_some)
93+ ( ret . to_uint ( ) , is_some)
9594 }
9695
9796 /// Returns the Bernstein-Yang transition matrix multiplied by 2^62 and the new value
@@ -249,66 +248,6 @@ const fn inv_mod2_62(value: &[Word]) -> i64 {
249248 ( x. wrapping_mul ( y. wrapping_add ( 1 ) ) & ( u64:: MAX >> 2 ) ) as i64
250249}
251250
252- /// Write an impl of a limb conversion function.
253- ///
254- /// Workaround for making this function generic around limb types while still allowing it to be `const fn`.
255- macro_rules! impl_limb_convert {
256- ( $input_type: ty, $input_bits: expr, $output_type: ty, $output_bits: expr, $output_size: expr, $input: expr) => { {
257- // This function is defined because the method "min" of the usize type is not constant
258- const fn min( a: usize , b: usize ) -> usize {
259- if a > b {
260- b
261- } else {
262- a
263- }
264- }
265-
266- let total = min( $input. len( ) * $input_bits, $output_size * $output_bits) ;
267- let mut output = [ 0 as $output_type; $output_size] ;
268- let mut bits = 0 ;
269-
270- while bits < total {
271- let ( i, o) = ( bits % $input_bits, bits % $output_bits) ;
272- output[ bits / $output_bits] |= ( $input[ bits / $input_bits] >> i) as $output_type << o;
273- bits += min( $input_bits - i, $output_bits - o) ;
274- }
275-
276- let mask = ( <$output_type>:: MAX as $output_type) >> ( <$output_type>:: BITS as usize - $output_bits) ;
277- let mut filled = total / $output_bits + if total % $output_bits > 0 { 1 } else { 0 } ;
278-
279- while filled > 0 {
280- filled -= 1 ;
281- output[ filled] &= mask;
282- }
283-
284- output
285- } } ;
286- }
287-
288- /// Convert from 64-bit saturated representation used by `Uint` to the 62-bit unsaturated representation used by
289- /// `Uint62`.
290- ///
291- /// Returns a big unsigned integer as an array of 62-bit chunks, which is equal modulo 2 ^ (62 * S) to the input big
292- /// unsigned integer stored as an array of 64-bit chunks.
293- ///
294- /// The ordering of the chunks in these arrays is little-endian.
295- #[ allow( trivial_numeric_casts) ]
296- const fn sat_to_unsat < const S : usize > ( input : & [ Word ] ) -> [ u64 ; S ] {
297- impl_limb_convert ! ( Word , Word :: BITS as usize , u64 , 62 , S , input)
298- }
299-
300- /// Convert from 62-bit unsaturated representation used by `Uint62` to the 64-bit saturated representation used by
301- /// `Uint`.
302- ///
303- /// Returns a big unsigned integer as an array of 64-bit chunks, which is equal modulo 2 ^ (64 * S) to the input big
304- /// unsigned integer stored as an array of 62-bit chunks.
305- ///
306- /// The ordering of the chunks in these arrays is little-endian
307- #[ allow( trivial_numeric_casts) ]
308- const fn unsat_to_sat < const S : usize > ( input : & [ u64 ] ) -> [ Word ; S ] {
309- impl_limb_convert ! ( u64 , 62 , Word , Word :: BITS as usize , S , input)
310- }
311-
312251/// `Uint`-like (62 * LIMBS)-bit integer type, whose variables store numbers in the two's complement code as arrays of
313252/// 62-bit limbs.
314253///
@@ -338,6 +277,52 @@ impl<const LIMBS: usize> Uint62L<LIMBS> {
338277 ret
339278 } ;
340279
280+ /// Convert from 64-bit saturated representation used by `Uint` to the 62-bit unsaturated representation used by
281+ /// `Uint62`.
282+ ///
283+ /// Returns a big unsigned integer as an array of 62-bit chunks, which is equal modulo 2 ^ (62 * S) to the input big
284+ /// unsigned integer stored as an array of 64-bit chunks.
285+ ///
286+ /// The ordering of the chunks in these arrays is little-endian.
287+ #[ allow( trivial_numeric_casts) ]
288+ pub const fn from_uint < const SAT_LIMBS : usize > ( input : & Uint < SAT_LIMBS > ) -> Self {
289+ if LIMBS != bernstein_yang_nlimbs ! ( SAT_LIMBS * Limb :: BITS as usize ) {
290+ panic ! ( "incorrect number of limbs" ) ;
291+ }
292+
293+ Self ( impl_limb_convert ! (
294+ Word ,
295+ Word :: BITS as usize ,
296+ u64 ,
297+ 62 ,
298+ LIMBS ,
299+ input. as_words( )
300+ ) )
301+ }
302+
303+ /// Convert from 62-bit unsaturated representation used by `Uint62` to the 64-bit saturated representation used by
304+ /// `Uint`.
305+ ///
306+ /// Returns a big unsigned integer as an array of 64-bit chunks, which is equal modulo 2 ^ (64 * S) to the input big
307+ /// unsigned integer stored as an array of 62-bit chunks.
308+ ///
309+ /// The ordering of the chunks in these arrays is little-endian
310+ #[ allow( trivial_numeric_casts, clippy:: wrong_self_convention) ]
311+ pub const fn to_uint < const SAT_LIMBS : usize > ( & self ) -> Uint < SAT_LIMBS > {
312+ if LIMBS != bernstein_yang_nlimbs ! ( SAT_LIMBS * Limb :: BITS as usize ) {
313+ panic ! ( "incorrect number of limbs" ) ;
314+ }
315+
316+ Uint :: from_words ( impl_limb_convert ! (
317+ u64 ,
318+ 62 ,
319+ Word ,
320+ Word :: BITS as usize ,
321+ SAT_LIMBS ,
322+ & self . 0
323+ ) )
324+ }
325+
341326 /// Returns the result of applying 62-bit right arithmetical shift to the current number.
342327 pub const fn shift ( & self ) -> Self {
343328 let mut ret = Self :: ZERO ;
0 commit comments