@@ -3231,6 +3231,223 @@ impl BigInt {
3231
3231
BigInt :: from_biguint ( sign, mag)
3232
3232
}
3233
3233
3234
+ /// Returns `(1 / self) % modulus` using Extended Euclidean Algorithm
3235
+ ///
3236
+ /// Panics if self and modulus are both even, either is zero, |self| == modulus, or no inverse is found
3237
+ ///
3238
+ /// From wolfSSL implementation: fp_invmod, fp_invmod_slow
3239
+ /// https://github.com/wolfSSL/wolfssl/blob/master/wolfcrypt/src/tfm.c
3240
+ pub fn invmod ( & self , modulus : & Self ) -> Self {
3241
+ if modulus. is_even ( ) {
3242
+ return self . invmod_slow ( modulus) ;
3243
+ }
3244
+
3245
+ if self . is_zero ( ) || modulus. is_zero ( ) {
3246
+ panic ! ( "base and/or modulus cannot be zero" ) ;
3247
+ }
3248
+
3249
+ if self . abs ( ) == * modulus {
3250
+ panic ! ( "cannot invert |a| == modulus" ) ;
3251
+ }
3252
+
3253
+ let x = modulus;
3254
+ let y = if self > modulus {
3255
+ self . mod_floor ( modulus)
3256
+ } else {
3257
+ self . clone ( )
3258
+ } ;
3259
+
3260
+ /* 3. u=x, v=y, B=0, D=1 */
3261
+
3262
+ /* x == modulus, y == value to invert */
3263
+ let mut u = x. clone ( ) ;
3264
+ /* we need y = |a| */
3265
+ let mut v = y. abs ( ) ;
3266
+
3267
+ let mut bb = Self :: zero ( ) ;
3268
+ let mut bd = Self :: one ( ) ;
3269
+
3270
+ // here an infinite loop takes the place of `goto top`
3271
+ // where a condition calls for `goto top`, simply continue
3272
+ //
3273
+ // NOTE: need to be cautious to always break/return, else infinite loop
3274
+ loop {
3275
+ /* 4. while u is even do */
3276
+ while u. is_even ( ) {
3277
+ /* 4.1 u = u / 2 */
3278
+ u /= 2_u32 ;
3279
+
3280
+ /* 4.2 if B is odd then */
3281
+ if bb. is_odd ( ) {
3282
+ /* B = (B-x)/2 */
3283
+ bb -= x;
3284
+ }
3285
+
3286
+ /* B = B/2 */
3287
+ bb /= 2_u32 ;
3288
+ }
3289
+
3290
+ /* 5. while v is even do */
3291
+ while v. is_even ( ) {
3292
+ /* 5.1 v = v/2 */
3293
+ v /= 2_u32 ;
3294
+
3295
+ /* 5.2 if D is odd then */
3296
+ if bd. is_odd ( ) {
3297
+ /* D = (D-x)/2 */
3298
+ bd -= x;
3299
+ }
3300
+
3301
+ /* D = D/2 */
3302
+ bd /= 2_u32 ;
3303
+ }
3304
+
3305
+ /* 6. if u >= v then */
3306
+ if u >= v {
3307
+ /* u = u - v, B = B - D */
3308
+ u -= & v;
3309
+ bb -= & bd;
3310
+ } else {
3311
+ /* v = v - u, D = D - B */
3312
+ v -= & u;
3313
+ bd -= & bb;
3314
+ }
3315
+
3316
+ /* if u != 0, goto step 4 */
3317
+ if !u. is_zero ( ) {
3318
+ continue ;
3319
+ }
3320
+
3321
+ /* now a = B, b = D, gcd == g*v */
3322
+ if !v. is_one ( ) {
3323
+ // if v != 1, there is no inverse
3324
+ panic ! ( "no inverse, GCD != 1" ) ;
3325
+ }
3326
+
3327
+ /* while D is too low */
3328
+ while bd. sign ( ) == Minus {
3329
+ bd += modulus;
3330
+ }
3331
+
3332
+ /* while D is too big */
3333
+ let mod_mag = modulus. magnitude ( ) ;
3334
+ while bd. magnitude ( ) >= mod_mag {
3335
+ bd -= modulus;
3336
+ }
3337
+
3338
+ if self . sign ( ) == Minus {
3339
+ bd = bd. neg ( ) ;
3340
+ }
3341
+
3342
+ /* D is now the inverse */
3343
+ break ;
3344
+ }
3345
+
3346
+ bd
3347
+ }
3348
+
3349
+ fn invmod_slow ( & self , modulus : & Self ) -> Self {
3350
+ if self . is_even ( ) && modulus. is_even ( ) {
3351
+ panic ! ( "base and modulus are both even" ) ;
3352
+ }
3353
+
3354
+ if self . is_zero ( ) || modulus. is_zero ( ) {
3355
+ panic ! ( "base and/or modulus cannot be zero" ) ;
3356
+ }
3357
+
3358
+ let x = self . mod_floor ( modulus) ;
3359
+ let y = modulus;
3360
+
3361
+ /* 3. u=x, v=y, A=1, B=0, C=0, D-1 */
3362
+ let mut u = x. clone ( ) ;
3363
+ let mut v = y. clone ( ) ;
3364
+ let mut ba = Self :: one ( ) ;
3365
+ let mut bb = Self :: zero ( ) ;
3366
+ let mut bc = Self :: zero ( ) ;
3367
+ let mut bd = Self :: one ( ) ;
3368
+
3369
+ // here an infinite loop takes the place of `goto top`
3370
+ // where a condition calls for `goto top`, simply continue
3371
+ //
3372
+ // NOTE: need to be cautious to always break/return, else infinite loop
3373
+ loop {
3374
+ /* 4. while u is even do */
3375
+ while u. is_even ( ) {
3376
+ /* 4.1 u = u / 2 */
3377
+ u /= 2_u32 ;
3378
+
3379
+ /* 4.2 if A or B is odd then */
3380
+ if ba. is_odd ( ) || bb. is_odd ( ) {
3381
+ /* A = (A+y)/2, B = (B-x)/2*/
3382
+ // div 2 happens unconditionally below
3383
+ ba += y;
3384
+ bb -= & x;
3385
+ }
3386
+
3387
+ ba /= 2_u32 ;
3388
+ bb /= 2_u32 ;
3389
+ }
3390
+
3391
+ /* 5. while v is even do */
3392
+ while v. is_even ( ) {
3393
+ /* 5.1 v = v / 2 */
3394
+ v /= 2_u32 ;
3395
+
3396
+ /* 5.2 if C or D is odd then */
3397
+ if bc. is_odd ( ) || bd. is_odd ( ) {
3398
+ /* C = (C+y)/2, D = (D-x)/2 */
3399
+ // div 2 happens unconditionally below
3400
+ bc += y;
3401
+ bd -= & x;
3402
+ }
3403
+
3404
+ /* C = C/2, D = D/2 */
3405
+ bc /= 2_u32 ;
3406
+ bd /= 2_u32 ;
3407
+ }
3408
+
3409
+ /* 6. if u >= v then */
3410
+ if u >= v {
3411
+ /* u = u - v, A = A - C, B = B - D */
3412
+ u -= & v;
3413
+ ba -= & bc;
3414
+ bb -= & bd;
3415
+ } else {
3416
+ /* v = v - u, C = C - A, D = D - B */
3417
+ v -= & u;
3418
+ bc -= & ba;
3419
+ bd -= & bb;
3420
+ }
3421
+
3422
+ /* if u != 0, goto step 4 */
3423
+ if !u. is_zero ( ) {
3424
+ continue ;
3425
+ }
3426
+
3427
+ /* now a = C, b = D, gcd == g*v */
3428
+ if !v. is_one ( ) {
3429
+ // if v != 1, there is no inverse
3430
+ panic ! ( "no inverse, GCD != 1" ) ;
3431
+ }
3432
+
3433
+ /* while C is too low */
3434
+ while bc. sign ( ) == Minus {
3435
+ bc += y;
3436
+ }
3437
+
3438
+ /* while C is too big */
3439
+ let mod_mag = y. magnitude ( ) ;
3440
+ while bc. magnitude ( ) > mod_mag {
3441
+ bc -= y;
3442
+ }
3443
+
3444
+ /* C is now the inverse */
3445
+ break ;
3446
+ }
3447
+
3448
+ bc
3449
+ }
3450
+
3234
3451
/// Returns the truncated principal square root of `self` --
3235
3452
/// see [Roots::sqrt](https://docs.rs/num-integer/0.1/num_integer/trait.Roots.html#method.sqrt).
3236
3453
pub fn sqrt ( & self ) -> Self {
0 commit comments