@@ -18,22 +18,22 @@ use subtle::CtOption;
18
18
19
19
/// Modular multiplicative inverter based on the Bernstein-Yang method.
20
20
///
21
- /// The inverter can be created for a specified modulus M and adjusting parameter A
22
- /// to compute the adjusted multiplicative inverses of positive integers, i.e. for
23
- /// computing (1 / x) * A (mod M) for a positive integer x.
21
+ /// The inverter can be created for a specified modulus M and adjusting parameter A to compute
22
+ /// the adjusted multiplicative inverses of positive integers, i.e. for computing
23
+ /// (1 / x) * A (mod M) for a positive integer x.
24
24
///
25
- /// The adjusting parameter allows computing the multiplicative inverses in the case of
26
- /// using the Montgomery representation for the input or the expected output. If R is
27
- /// the Montgomery factor, the multiplicative inverses in the appropriate representation
28
- /// can be computed provided that the value of A is chosen as follows:
25
+ /// The adjusting parameter allows computing the multiplicative inverses in the case of using the
26
+ /// Montgomery representation for the input or the expected output. If R is the Montgomery
27
+ /// factor, the multiplicative inverses in the appropriate representation can be computed
28
+ /// provided that the value of A is chosen as follows:
29
29
/// - A = 1, if both the input and the expected output are in the standard form
30
30
/// - A = R^2 mod M, if both the input and the expected output are in the Montgomery form
31
31
/// - A = R mod M, if either the input or the expected output is in the Montgomery form,
32
32
/// but not both of them
33
33
///
34
- /// The public methods of this type receive and return unsigned big integers as arrays of
35
- /// 64-bit chunks, the ordering of which is little-endian. Both the modulus and the integer
36
- /// to be inverted should not exceed 2 ^ (62 * L - 64)
34
+ /// The public methods of this type receive and return unsigned big integers as arrays of 64-bit
35
+ /// chunks, the ordering of which is little-endian. Both the modulus and the integer to be
36
+ /// inverted should not exceed 2 ^ (62 * L - 64).
37
37
///
38
38
/// For better understanding the implementation, the following resources are recommended:
39
39
/// - D. Bernstein, B.-Y. Yang, "Fast constant-time gcd computation and modular inversion",
@@ -45,7 +45,7 @@ pub struct BernsteinYangInverter<const SAT_LIMBS: usize, const UNSAT_LIMBS: usiz
45
45
/// Modulus
46
46
pub ( super ) modulus : Int62L < UNSAT_LIMBS > ,
47
47
48
- /// Adjusting parameter
48
+ /// Adjusting parameter (see toplevel documentation).
49
49
adjuster : Int62L < UNSAT_LIMBS > ,
50
50
51
51
/// Multiplicative inverse of the modulus modulo 2^62
@@ -86,9 +86,9 @@ impl<const SAT_LIMBS: usize, const UNSAT_LIMBS: usize>
86
86
( f, g) = fg ( f, g, matrix) ;
87
87
( d, e) = de ( & self . modulus , self . inverse , d, e, matrix) ;
88
88
}
89
- // At this point the absolute value of "f" equals the greatest common divisor
90
- // of the integer to be inverted and the modulus the inverter was created for.
91
- // Thus, if "f" is neither 1 nor -1, then the sought inverse does not exist
89
+ // At this point the absolute value of "f" equals the greatest common divisor of the
90
+ // integer to be inverted and the modulus the inverter was created for.
91
+ // Thus, if "f" is neither 1 nor -1, then the sought inverse does not exist.
92
92
let antiunit = f. eq ( & Int62L :: MINUS_ONE ) ;
93
93
let ret = self . norm ( d, antiunit) ;
94
94
let is_some = ConstChoice :: from_word_lsb ( ( f. eq ( & Int62L :: ONE ) || antiunit) as Word ) ;
@@ -97,8 +97,9 @@ impl<const SAT_LIMBS: usize, const UNSAT_LIMBS: usize>
97
97
98
98
/// Returns the greatest common divisor (GCD) of the two given numbers.
99
99
///
100
- /// This is defined on this type to piggyback on the definitions for `SAT_LIMBS` and `UNSAT_LIMBS` which are
101
- /// computed when defining `PrecomputeInverter::Inverter` for various `Uint` limb sizes.
100
+ /// This is defined on this type to piggyback on the definitions for `SAT_LIMBS` and
101
+ /// `UNSAT_LIMBS` which are computed when defining `PrecomputeInverter::Inverter` for various
102
+ /// `Uint` limb sizes.
102
103
pub ( crate ) const fn gcd ( f : & Uint < SAT_LIMBS > , g : & Uint < SAT_LIMBS > ) -> Uint < SAT_LIMBS > {
103
104
let f_0 = Int62L :: from_uint ( f) ;
104
105
let inverse = inv_mod2_62 ( f. as_words ( ) ) ;
@@ -123,9 +124,9 @@ impl<const SAT_LIMBS: usize, const UNSAT_LIMBS: usize>
123
124
f. to_uint ( )
124
125
}
125
126
126
- /// Returns the Bernstein-Yang transition matrix multiplied by 2^62 and the new value
127
- /// of the delta variable for the 62 basic steps of the Bernstein-Yang method, which
128
- /// are to be performed sequentially for specified initial values of f, g and delta
127
+ /// Returns the Bernstein-Yang transition matrix multiplied by 2^62 and the new value of the
128
+ /// delta variable for the 62 basic steps of the Bernstein-Yang method, which are to be
129
+ /// performed sequentially for specified initial values of f, g and delta
129
130
const fn jump (
130
131
f : & Int62L < UNSAT_LIMBS > ,
131
132
g : & Int62L < UNSAT_LIMBS > ,
@@ -156,9 +157,9 @@ impl<const SAT_LIMBS: usize, const UNSAT_LIMBS: usize>
156
157
( t[ 0 ] , t[ 1 ] ) = ( t[ 1 ] , [ -t[ 0 ] [ 0 ] , -t[ 0 ] [ 1 ] ] ) ;
157
158
}
158
159
159
- // The formula (3 * x) xor 28 = -1 / x (mod 32) for an odd integer x
160
- // in the two's complement code has been derived from the formula
161
- // (3 * x) xor 2 = 1 / x (mod 32) attributed to Peter Montgomery
160
+ // The formula (3 * x) xor 28 = -1 / x (mod 32) for an odd integer x in the two's
161
+ // complement code has been derived from the formula (3 * x) xor 2 = 1 / x (mod 32)
162
+ // attributed to Peter Montgomery.
162
163
let mask = ( 1 << min ( min ( steps, 1 - delta) , 5 ) ) - 1 ;
163
164
let w = ( g as i64 ) . wrapping_mul ( f. wrapping_mul ( 3 ) ^ 28 ) & mask;
164
165
@@ -169,9 +170,9 @@ impl<const SAT_LIMBS: usize, const UNSAT_LIMBS: usize>
169
170
( delta, t)
170
171
}
171
172
172
- /// Returns either "value (mod M)" or "-value (mod M)", where M is the modulus the
173
- /// inverter was created for, depending on "negate", which determines the presence
174
- /// of "-" in the used formula. The input integer lies in the interval (-2 * M, M)
173
+ /// Returns either "value (mod M)" or "-value (mod M)", where M is the modulus the inverter
174
+ /// was created for, depending on "negate", which determines the presence of "-" in the used
175
+ /// formula. The input integer lies in the interval (-2 * M, M).
175
176
const fn norm ( & self , mut value : Int62L < UNSAT_LIMBS > , negate : bool ) -> Int62L < UNSAT_LIMBS > {
176
177
if value. is_negative ( ) {
177
178
value = value. add ( & self . modulus ) ;
@@ -226,8 +227,9 @@ const fn inv_mod2_62(value: &[Word]) -> i64 {
226
227
( x. wrapping_mul ( y. wrapping_add ( 1 ) ) & ( u64:: MAX >> 2 ) ) as i64
227
228
}
228
229
229
- /// Returns the updated values of the variables f and g for specified initial ones and Bernstein-Yang transition
230
- /// matrix multiplied by 2^62. The returned vector is "matrix * (f, g)' / 2^62", where "'" is the transpose operator
230
+ /// Returns the updated values of the variables f and g for specified initial ones and
231
+ /// Bernstein-Yang transition matrix multiplied by 2^62. The returned vector is
232
+ /// "matrix * (f, g)' / 2^62", where "'" is the transpose operator.
231
233
const fn fg < const LIMBS : usize > (
232
234
f : Int62L < LIMBS > ,
233
235
g : Int62L < LIMBS > ,
@@ -239,10 +241,11 @@ const fn fg<const LIMBS: usize>(
239
241
)
240
242
}
241
243
242
- /// Returns the updated values of the variables d and e for specified initial ones and Bernstein-Yang transition
243
- /// matrix multiplied by 2^62. The returned vector is congruent modulo M to "matrix * (d, e)' / 2^62 (mod M)",
244
- /// where M is the modulus the inverter was created for and "'" stands for the transpose operator. Both the input
245
- /// and output values lie in the interval (-2 * M, M)
244
+ /// Returns the updated values of the variables d and e for specified initial ones and
245
+ /// Bernstein-Yang transition matrix multiplied by 2^62. The returned vector is congruent modulo
246
+ /// M to "matrix * (d, e)' / 2^62 (mod M)", where M is the modulus the inverter was created for
247
+ /// and "'" stands for the transpose operator. Both the input and output values lie in the
248
+ /// interval (-2 * M, M).
246
249
const fn de < const LIMBS : usize > (
247
250
modulus : & Int62L < LIMBS > ,
248
251
inverse : i64 ,
@@ -273,8 +276,8 @@ const fn de<const LIMBS: usize>(
273
276
( cd. shr ( ) , ce. shr ( ) )
274
277
}
275
278
276
- /// "Bigint"-like (62 * LIMBS)-bit signed integer type, whose variables store numbers in the two's complement code as
277
- /// arrays of 62-bit limbs in little endian order.
279
+ /// "Bigint"-like (62 * LIMBS)-bit signed integer type, whose variables store numbers in the two's
280
+ /// complement code as arrays of 62-bit limbs in little endian order.
278
281
///
279
282
/// The arithmetic operations for this type are wrapping ones.
280
283
#[ derive( Clone , Copy , Debug ) ]
@@ -300,11 +303,11 @@ impl<const LIMBS: usize> Int62L<LIMBS> {
300
303
ret
301
304
} ;
302
305
303
- /// Convert from 64-bit saturated representation used by `Uint` to the 62-bit unsaturated representation used by
304
- /// `Uint62L `.
306
+ /// Convert from 64-bit saturated representation used by `Uint` to the 62-bit unsaturated
307
+ /// representation used by `Int62L `.
305
308
///
306
- /// Returns a big unsigned integer as an array of 62-bit chunks, which is equal modulo 2 ^ (62 * S) to the input big
307
- /// unsigned integer stored as an array of 64-bit chunks.
309
+ /// Returns a big unsigned integer as an array of 62-bit chunks, which is equal modulo
310
+ /// 2 ^ (62 * S) to the input big unsigned integer stored as an array of 64-bit chunks.
308
311
///
309
312
/// The ordering of the chunks in these arrays is little-endian.
310
313
#[ allow( trivial_numeric_casts) ]
@@ -319,11 +322,11 @@ impl<const LIMBS: usize> Int62L<LIMBS> {
319
322
Self ( output)
320
323
}
321
324
322
- /// Convert from 62-bit unsaturated representation used by `Uint62L ` to the 64-bit saturated representation used by
323
- /// `Uint`.
325
+ /// Convert from 62-bit unsaturated representation used by `Int62L ` to the 64-bit saturated
326
+ /// representation used by `Uint`.
324
327
///
325
- /// Returns a big unsigned integer as an array of 64-bit chunks, which is equal modulo 2 ^ (64 * S) to the input big
326
- /// unsigned integer stored as an array of 62-bit chunks.
328
+ /// Returns a big unsigned integer as an array of 64-bit chunks, which is equal modulo
329
+ /// 2 ^ (64 * S) to the input big unsigned integer stored as an array of 62-bit chunks.
327
330
///
328
331
/// The ordering of the chunks in these arrays is little-endian
329
332
#[ allow( trivial_numeric_casts, clippy:: wrong_self_convention) ]
@@ -359,18 +362,18 @@ impl<const LIMBS: usize> Int62L<LIMBS> {
359
362
/// Const fn equivalent for `Mul::<i64>::mul`.
360
363
pub const fn mul ( & self , other : i64 ) -> Self {
361
364
let mut ret = Self :: ZERO ;
362
- // If the short multiplicand is non-negative, the standard multiplication
363
- // algorithm is performed. Otherwise, the product of the additively negated
364
- // multiplicands is found as follows. Since for the two's complement code
365
- // the additive negation is the result of adding 1 to the bitwise inverted
366
- // argument 's representation, for any encoded integers x and y we have
367
- // x * y = (-x) * (-y) = (!x + 1) * (-y) = !x * (-y) + (-y), where "!" is
368
- // the bitwise inversion and arithmetic operations are performed according
369
- // to the rules of the code. If the short multiplicand is negative, the
370
- // algorithm below uses this formula by substituting the short multiplicand
371
- // for y and turns into the modified standard multiplication algorithm,
372
- // where the carry flag is initialized with the additively negated short
373
- // multiplicand and the chunks of the long multiplicand are bitwise inverted
365
+ // If the short multiplicand is non-negative, the standard multiplication algorithm is
366
+ // performed. Otherwise, the product of the additively negated multiplicands is found as
367
+ // follows.
368
+ //
369
+ // Since for the two 's complement code the additive negation is the result of adding 1 to
370
+ // the bitwise inverted argument's representation, for any encoded integers x and y we have
371
+ // x * y = (-x) * (-y) = (!x + 1) * (-y) = !x * (-y) + (-y), where "!" is the bitwise
372
+ // inversion and arithmetic operations are performed according to the rules of the code.
373
+ // If the short multiplicand is negative, the algorithm below uses this formula by
374
+ // substituting the short multiplicand for y and turns into the modified standard
375
+ // multiplication algorithm, where the carry flag is initialized with the additively
376
+ // negated short multiplicand and the chunks of the long multiplicand are bitwise inverted.
374
377
let ( other, mut carry, mask) = if other < 0 {
375
378
( -other, -other as u64 , Self :: MASK )
376
379
} else {
@@ -390,8 +393,8 @@ impl<const LIMBS: usize> Int62L<LIMBS> {
390
393
391
394
/// Const fn equivalent for `Neg::neg`.
392
395
pub const fn neg ( & self ) -> Self {
393
- // For the two's complement code the additive negation is the result
394
- // of adding 1 to the bitwise inverted argument's representation
396
+ // For the two's complement code the additive negation is the result of adding 1 to the
397
+ // bitwise inverted argument's representation.
395
398
let ( mut ret, mut carry) = ( Self :: ZERO , 1 ) ;
396
399
let mut i = 0 ;
397
400
0 commit comments