Skip to content

Commit

Permalink
Add extended gcd (TheAlgorithms#307)
Browse files Browse the repository at this point in the history
Co-authored-by: Christian Clauss <[email protected]>
Co-authored-by: Andrii Siriak <[email protected]>
  • Loading branch information
3 people authored Sep 3, 2021
1 parent 2ce0de8 commit a50e4a6
Show file tree
Hide file tree
Showing 3 changed files with 82 additions and 0 deletions.
12 changes: 12 additions & 0 deletions math/gcd/extendedgcd.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package gcd

// ExtendedRecursive finds and returns gcd(a, b), x, y satisfying a*x + b*y = gcd(a, b).
func ExtendedRecursive(a, b int64) (int64, int64, int64) {
if b > 0 {
d, y, x := ExtendedRecursive(b, a%b)
y -= (a / b) * x
return d, x, y
}

return a, 1, 0
}
57 changes: 57 additions & 0 deletions math/gcd/extendedgcd_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
package gcd

import "testing"

type testExtendedFunction func(int64, int64) (int64, int64, int64)

var testCasesExtended = []struct {
name string
a int64
b int64
gcd int64
x int64
y int64
}{
{"gcd of 10 and 0", 10, 0, 10, 1, 0},
{"gcd of 98 and 56", 98, 56, 14, -1, 2},
{"gcd of 0 and 10", 0, 10, 10, 0, 1},
}

func TemplateTestExtendedGCD(t *testing.T, f testExtendedFunction) {
for _, tc := range testCasesExtended {
t.Run(tc.name, func(t *testing.T) {
actualGcd, actualX, actualY := f(tc.a, tc.b)
if actualGcd != tc.gcd {
t.Errorf("Expected GCD of %d and %d to be: %v, but got: %d", tc.a, tc.b, tc.gcd, actualGcd)
}
if actualX != tc.x {
t.Errorf("Expected x satisfying %d * x + %d * y = gcd to be: %v, but got: %d", tc.a, tc.b, tc.x, actualX)
}
if actualY != tc.y {
t.Errorf("Expected y satisfying %d * x + %d * y = gcd to be: %v, but got: %d", tc.a, tc.b, tc.y, actualY)
}
})
}
}

func TestExtendedGCDRecursive(t *testing.T) {
TemplateTestExtendedGCD(t, ExtendedRecursive)
}

func TestExtendedGCDIterative(t *testing.T) {
TemplateTestExtendedGCD(t, ExtendedIterative)
}

func TemplateBenchmarkExtendedGCD(b *testing.B, f testExtendedFunction) {
for i := 0; i < b.N; i++ {
f(98, 56)
}
}

func BenchmarkExtendedGCDRecursive(b *testing.B) {
TemplateBenchmarkExtendedGCD(b, ExtendedRecursive)
}

func BenchmarkExtendedGCDIterative(b *testing.B) {
TemplateBenchmarkExtendedGCD(b, ExtendedIterative)
}
13 changes: 13 additions & 0 deletions math/gcd/extendedgcditerative.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package gcd

// ExtendedIterative finds and returns gcd(a, b), x, y satisfying a*x + b*y = gcd(a, b).
func ExtendedIterative(a, b int64) (int64, int64, int64) {
var u, y, v, x int64 = 1, 1, 0, 0
for a > 0 {
var q int64 = b / a
x, u = u, x-q*u
y, v = v, y-q*v
b, a = a, b-q*a
}
return b, x, y
}

0 comments on commit a50e4a6

Please sign in to comment.