@@ -3231,6 +3231,223 @@ impl BigInt {
32313231 BigInt :: from_biguint ( sign, mag)
32323232 }
32333233
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+
32343451 /// Returns the truncated principal square root of `self` --
32353452 /// see [Roots::sqrt](https://docs.rs/num-integer/0.1/num_integer/trait.Roots.html#method.sqrt).
32363453 pub fn sqrt ( & self ) -> Self {
0 commit comments