Jump to content

Algorithm Implementation/Mathematics/Extended Euclidean algorithm

From Wikibooks, open books for an open world

Iterative algorithm

[edit | edit source]
#include <stdio.h> #include <stdlib.h> // strtol() function void xgcd(long *result, long a, long b){  long aa[2]={1,0}, bb[2]={0,1}, q;  for (;;) {  q = a / b;   a = a % b;  aa[0] = aa[0] - q*aa[1];   bb[0] = bb[0] - q*bb[1];  if (!a) {  result[0] = b;   result[1] = aa[1];   result[2] = bb[1];  return;  }  q = b / a;   b = b % a;  aa[1] = aa[1] - q*aa[0];   bb[1] = bb[1] - q*bb[0];  if (b == 0) {  result[0] = a;   result[1] = aa[0];   result[2] = bb[0];  return;  }  } }   int main(int argc, char** argv){  long a, b, c[3];  char *end;  if (argc < 3) {  printf("Usage: %s a b (compute xgcd(a,b))\n", argv[0]);  exit(-1);  }  printf("long int is %lu bytes (or %lu bits)\n", sizeof(long), 8 * sizeof(long));  a = strtol(argv[1], &end, 10);  b = strtol(argv[2], &end, 10);  printf("xgcd(%ld,%ld) = ", a, b);  xgcd(c, a, b);  printf("%ld = %ld*%ld + %ld*%ld\n", c[0], c[1], a, c[2], b);  return 0; } 

Recursive algorithm

[edit | edit source]
//https://en.wikipedia.org/wiki/Extended_Euclidean_algorithm //clrs p.937 #include <stdio.h> #include <stdlib.h> int mod (int a, int b){ return a %b;  } int *extendedEuclid (int a, int b){ int *dxy = (int *)malloc(sizeof(int) *3); if (b ==0){ dxy[0] =a; dxy[1] =1; dxy[2] =0;  return dxy; } else{ int t, t2; dxy = extendedEuclid(b, mod(a, b)); t =dxy[1]; t2 =dxy[2]; dxy[1] =dxy[2]; dxy[2] = t - a/b *t2; return dxy; } } int main(void) { int a =99, b =78; int *ptr; ptr =extendedEuclid (a, b); printf("%d = %d * %d + %d * %d \n",ptr[0], a, ptr[1], b, ptr[2] ); return 0; } 

Iterative algorithm

[edit | edit source]
public class xgcd {  public static long[] xgcd(long a, long b){ long[] retvals={0,0,0}; long aa[]={1,0}, bb[]={0,1}, q=0; while(true) {  q = a / b; a = a % b;  aa[0] = aa[0] - q*aa[1]; bb[0] = bb[0] - q*bb[1];  if (a == 0) {  retvals[0] = b; retvals[1] = aa[1]; retvals[2] = bb[1];  return retvals;  };  q = b / a; b = b % a;  aa[1] = aa[1] - q*aa[0]; bb[1] = bb[1] - q*bb[0];  if (b == 0) {  retvals[0] = a; retvals[1] = aa[0]; retvals[2] = bb[0];  return retvals;  };  }  }    public static void main(String[] args){ if(args.length < 2){  System.out.println("Usage: xgcd(a,b)"); System.exit(-1);}; long a = Integer.parseInt(args[0]); long b = Integer.parseInt(args[1]); long[] retvals; retvals = xgcd(a,b); System.out.println("xgcd("+args[0]+", "+args[1]+") = [" +String.valueOf(retvals[0])+", "+ String.valueOf(retvals[1])+", "+ String.valueOf(retvals[2])+"]"); System.out.println(" "+String.valueOf(retvals[0])+" = " +args[0]+"*("+String.valueOf(retvals[1])+") + " +args[1]+"*("+String.valueOf(retvals[2])+")");  }; } 

Iterative with BigInteger

[edit | edit source]
import java.math.BigInteger; public class XGCD {  // Assumes a and b are positive  public static BigInteger[] xgcd(BigInteger a, BigInteger b) {  BigInteger x = a, y=b;  BigInteger[] qrem = new BigInteger[2];  BigInteger[] result = new BigInteger[3];  BigInteger x0 = BigInteger.ONE, x1 = BigInteger.ZERO;  BigInteger y0 = BigInteger.ZERO, y1 = BigInteger.ONE;    while (true) {  qrem = x.divideAndRemainder(y);  x = qrem[1];  x0 = x0.subtract(y0.multiply(qrem[0]));  x1 = x1.subtract(y1.multiply(qrem[0]));  if (x.equals(BigInteger.ZERO)) {  result[0] = y;  result[1] = y0;  result[2] = y1;  return result;  }    qrem = y.divideAndRemainder(x);  y = qrem[1];  y0 = y0.subtract(x0.multiply(qrem[0]));  y1 = y1.subtract(x1.multiply(qrem[0]));  if (y.equals(BigInteger.ZERO)) {  result[0] = x;  result[1] = x0;  result[2] = x1;  return result;  }  }  }  public static void main(String[] args) {  BigInteger a = new BigInteger(args[0]);  BigInteger b = new BigInteger(args[1]);  BigInteger[] result = new BigInteger[3];  System.out.println("a = " + a.toString() + "; b = " + b.toString());  result = xgcd(a,b);  System.out.println("xgcd = " + result[0].toString() +   " [" + result[1].toString() + ", " + result[2].toString() + "]");  } } 

Python

[edit | edit source]

Both functions take positive integers a, b as input, and return a triple (g, x, y), such that ax + by = g = gcd(a, b).

Iterative algorithm

[edit | edit source]
from typing import Tuple def xgcd(a: int, b: int) -> Tuple[int, int, int]:  """return (g, x, y) such that a*x + b*y = g = gcd(a, b)""" x0, x1, y0, y1 = 0, 1, 1, 0 while a != 0: (q, a), b = divmod(b, a), a y0, y1 = y1, y0 - q * y1 x0, x1 = x1, x0 - q * x1 return b, x0, y0 

Recursive algorithm

[edit | edit source]
import sys from typing import Tuple sys.setrecursionlimit(1000000) # long type, 32bit OS 4B, 64bit OS 8B (1bit for sign) def egcd(a: int, b: int) -> Tuple[int, int, int]:  """return (g, x, y) such that a*x + b*y = g = gcd(a, b)""" if a == 0: return (b, 0, 1) else: b_div_a, b_mod_a = divmod(b, a) g, x, y = egcd(b_mod_a, a) return (g, y - b_div_a * x, x) 

Modular inverse

[edit | edit source]

An application of extended GCD algorithm to finding modular inverses:

def modinv(a: int, b: int) -> int:  """return x such that (x * a) % b == 1""" g, x, _ = egcd(a, b) if g != 1: raise Exception('gcd(a, b) != 1') return x % b 

Clojure

[edit | edit source]

Extended

[edit | edit source]
(defn xgcd  "Extended Euclidean Algorithm. Returns [gcd(a,b) x y] where ax + by = gcd(a,b)."  [a b]  (if (= a 0)  [b 0 1]  (let [[g x y] (xgcd (mod b a) a)]  [g (- y (* (Math/floorDiv b a) x)) x]))) 

Haskell

[edit | edit source]

Unextended

[edit | edit source]
euclid :: Integral a => a -> a -> a euclid 0 b = abs b euclid a 0 = abs a euclid a b = euclid b $ rem a b 

Extended

[edit | edit source]
eGCD :: Integer -> Integer -> (Integer,Integer,Integer) eGCD 0 b = (b, 0, 1) eGCD a b = let (g, s, t) = eGCD (b `mod` a) a  in (g, t - (b `div` a) * s, s)