@@ -41,18 +41,19 @@ pub fn egcd(a: anytype, b: anytype) ExtendedGreatestCommonDivisor(@TypeOf(a, b))
4141 const toinv = @shrExact (other , @intCast (shift ));
4242 const ctrl = @shrExact (odd , @intCast (shift )); // Invariant: |s|, |t|, |ctrl| < |MIN_OF(S)|
4343 const half_ctrl = 1 + @shrExact (ctrl - 1 , 1 );
44+ const abs_ctrl = @abs (ctrl );
4445
4546 var s : S = std .math .sign (toinv );
4647 var t : S = 0 ;
4748
4849 var x = @abs (toinv );
49- var y = @abs ( ctrl ) ;
50+ var y = abs_ctrl ;
5051
5152 {
5253 const xz = @ctz (x );
5354 x = @shrExact (x , @intCast (xz ));
5455 for (0.. xz ) | _ | {
55- const half_s = @divFloor ( s , 2 ) ;
56+ const half_s = s >> 1 ;
5657 if (s & 1 == 0 )
5758 s = half_s
5859 else
@@ -78,12 +79,14 @@ pub fn egcd(a: anytype, b: anytype) ExtendedGreatestCommonDivisor(@TypeOf(a, b))
7879 }
7980 x = @shrExact (x , @intCast (xz ));
8081 for (0.. xz ) | _ | {
81- const half_s = @divFloor ( s , 2 ) ;
82+ const half_s = s >> 1 ;
8283 if (s & 1 == 0 )
8384 s = half_s
8485 else
8586 s = half_s + half_ctrl ;
8687 }
88+
89+ if (s < 0 ) s = @intCast (abs_ctrl - @abs (s ));
8790 }
8891
8992 // Using integer widening is only a temporary solution.
@@ -98,6 +101,24 @@ pub fn egcd(a: anytype, b: anytype) ExtendedGreatestCommonDivisor(@TypeOf(a, b))
98101}
99102
100103test {
104+ {
105+ const a : i2 = 0 ;
106+ const b : i2 = 1 ;
107+ const r = egcd (a , b );
108+ const g = r .gcd ;
109+ const s : i2 = r .bezout_coeff_1 ;
110+ const t : i2 = r .bezout_coeff_2 ;
111+ try std .testing .expect (s * a + t * b == g );
112+ }
113+ {
114+ const a : i8 = -128 ;
115+ const b : i8 = 127 ;
116+ const r = egcd (a , b );
117+ const g = r .gcd ;
118+ const s : i16 = r .bezout_coeff_1 ;
119+ const t : i16 = r .bezout_coeff_2 ;
120+ try std .testing .expect (s * a + t * b == g );
121+ }
101122 {
102123 const a : i16 = -32768 ;
103124 const b : i16 = -32768 ;
0 commit comments