It removes the common factor 2k from A=2ka and B=2kb.
Then, it applies the Binary GCD rules starting from u=a and v=b, and reduces u and v until they become equal. The case where both u and v are even has already been handled in the previous step, so it's excluded here.
gcd(u,v)=⎩⎨⎧gcd(u,v)gcd(2u,v)gcd(u,2v)gcd(u−v,v)gcd(u,v−u) if u=v if u≡0(mod2)∧v≡1(mod2) if u≡1(mod2)∧v≡0(mod2) if u>v∧u≡1(mod2)∧v≡1(mod2) if v>u∧u≡1(mod2)∧v≡1(mod2)
Meanwhile, we set the variables as x1=1,y1=0,x2=0,y2=1, and maintain the following two invariants:
ax1+by1=u,ax2+by2=v
At each step, we update the expressions in a way that preserves these invariants. Let’s consider only case 2 and case 4 as examples.
Case 2: When u is even and v is odd
If x1 and y1 are both even, we update as follows:
ax1+by1=u⇔a2x1+b2y1=2u
Otherwise (if either is odd), we update as:
ax1+by1=u⇔a2(x1+b)+b2(y1−a)=2u
Why are x1+b and y1−a always even?
Since u is even, the expression ax1+by1 must also be even. A sum is even only if both terms are even or both are odd.
Now, note that a and b cannot both be even — because we already factored out the common power of 2 beforehand.
a
x₁
a * x₁
b
y₁
b * y₁
odd
odd
odd
odd
odd
odd
even
odd
even
odd
even
even
odd
even
even
even
odd
even
In each of these cases, the sum ax1+by1 is even, and both x1+b and y1−a are even as well.
Case 4: When u>v and both u and v are odd
ax1+by1=u,ax2+by2=v⇔a(x1−x2)+b(y1−y2)=u−v
Code
def binary_extended_gcd(a, b):
# base case: if a or b is 0, return the other number as gcd, with appropriate coefficients
if a == 0: return (b, 0, 1)
if b == 0: return (a, 1, 0)
# Step 1: Remove common factors of 2
# gcd(2a, 2b) = 2 * gcd(a, b), so we factor out all common 2s
shift = 0
while a % 2 == 0 and b % 2 == 0:
a //= 2
b //= 2
shift += 1 # keep track of how many times we factored out 2
# Step 2: Initialize variables for the extended GCD
u, v = a, b # Working values to reduce down to GCD
x1, y1 = 1, 0 # Bézout coefficients for u
x2, y2 = 0, 1 # Bézout coefficients for v
# Step 3: Main loop to compute GCD while updating Bézout coefficients
while u != v:
if u % 2 == 0:
# If u is even, divide by 2
u //= 2
# Adjust (x1, y1) to keep Bézout identity valid
if x1 % 2 == 0 and y1 % 2 == 0:
x1 //= 2
y1 //= 2
else:
# If odd, we adjust using the original a, b to keep x1, y1 as integers
x1 = (x1 + b) // 2
y1 = (y1 - a) // 2
elif v % 2 == 0:
# Same logic for v if it is even
v //= 2
if x2 % 2 == 0 and y2 % 2 == 0:
x2 //= 2
y2 //= 2
else:
x2 = (x2 + b) // 2
y2 = (y2 - a) // 2
elif u > v:
# Reduce u by subtracting v
u -= v
x1 -= x2
y1 -= y2
else:
# Reduce v by subtracting u
v -= u
x2 -= x1
y2 -= y1
# Step 4: Multiply back the common factor of 2 (if any)
# At this point, u == v == gcd(a, b)
return (u << shift, x1, y1) # gcd * 2^shift, x, y