Skip to content

Commit 90840ce

Browse files
committed
Binary GCD
1 parent 4c378de commit 90840ce

File tree

1 file changed

+35
-0
lines changed

1 file changed

+35
-0
lines changed

src/algebra/euclid-algorithm.md

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,41 @@ int lcm (int a, int b) {
9595
}
9696
```
9797

98+
## Binary GCD
99+
100+
The Binary GCD algorithm is an optimization to the normal Eulidean algorithm.
101+
102+
The slow part of the normal algorithm are the modulo operations. Modulo operations, although we see them as $O(1)$, are a lot slower than simpler operations like addition, subtraction or bitwise operations.
103+
So it would be better to avoid those.
104+
105+
It turns out, that you can design a fast GCD algorithm that avoids modulo operations.
106+
It's based on a few properties:
107+
108+
- If both numbers are even, then we can factor out a two of both and compute the GCD of the remaining numbers: $\gcd(2a, 2b) = 2 \gcd(a, b)$.
109+
- If one of the numbers is even and the other one is odd, then we can remove the factor 2 from the even one: $\gcd(2a, b) = \gcd(a, b)$ if $b$ is odd.
110+
- If both numbers are odd, then subtracting one number of the other one will not change the GCD: $\gcd(a, b) = \gcd(b, a-b)$ (this can be proven in the same way as the correctness proof of the normal algorithm)
111+
112+
Using only these properties, and some fast bitwise functions from GCC, we can implement a fast version:
113+
114+
```cpp
115+
int gcd(int u, int v) {
116+
if (!u || !v)
117+
return u | v;
118+
unsigned shift = __builtin_ctz(u | v);
119+
u >>= __builtin_ctz(u);
120+
do {
121+
v >>= __builtin_ctz(v);
122+
if (u > v)
123+
swap(u, v);
124+
v -= u;
125+
} while (v);
126+
return u << shift;
127+
}
128+
```
129+
130+
Notice, that such an optimization is usually not necessary, and most programming languages already have a GCD function in their standard libraries.
131+
E.g. C++17 has such a function in the `numeric` header.
132+
98133
## Practice Problems
99134
100135
- [Codechef - GCD and LCM](https://www.codechef.com/problems/FLOW016)

0 commit comments

Comments
 (0)