10
10
11
11
#![ allow( clippy:: needless_range_loop) ]
12
12
13
+ #[ macro_use]
14
+ mod macros;
15
+
13
16
use crate :: { ConstChoice , Inverter , Limb , Uint , Word } ;
14
17
use subtle:: CtOption ;
15
18
@@ -59,13 +62,9 @@ impl<const SAT_LIMBS: usize, const UNSAT_LIMBS: usize>
59
62
/// Modulus must be odd. Returns `ConstChoice::FALSE` if it is not.
60
63
#[ allow( trivial_numeric_casts) ]
61
64
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
-
66
65
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) ,
69
68
inverse : inv_mod2_62 ( modulus. as_words ( ) ) ,
70
69
} ;
71
70
@@ -76,7 +75,7 @@ impl<const SAT_LIMBS: usize, const UNSAT_LIMBS: usize>
76
75
/// depending on invertibility of the argument, i.e. its coprimality with the modulus
77
76
pub const fn inv ( & self , value : & Uint < SAT_LIMBS > ) -> ( Uint < SAT_LIMBS > , ConstChoice ) {
78
77
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) ;
80
79
let ( mut delta, mut f) = ( 1 , self . modulus ) ;
81
80
let mut matrix;
82
81
@@ -89,9 +88,9 @@ impl<const SAT_LIMBS: usize, const UNSAT_LIMBS: usize>
89
88
// of the integer to be inverted and the modulus the inverter was created for.
90
89
// Thus, if "f" is neither 1 nor -1, then the sought inverse does not exist
91
90
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) ;
93
92
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)
95
94
}
96
95
97
96
/// 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 {
249
248
( x. wrapping_mul ( y. wrapping_add ( 1 ) ) & ( u64:: MAX >> 2 ) ) as i64
250
249
}
251
250
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
-
312
251
/// `Uint`-like (62 * LIMBS)-bit integer type, whose variables store numbers in the two's complement code as arrays of
313
252
/// 62-bit limbs.
314
253
///
@@ -338,6 +277,52 @@ impl<const LIMBS: usize> Uint62L<LIMBS> {
338
277
ret
339
278
} ;
340
279
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
+
341
326
/// Returns the result of applying 62-bit right arithmetical shift to the current number.
342
327
pub const fn shift ( & self ) -> Self {
343
328
let mut ret = Self :: ZERO ;
0 commit comments