1*457c8996SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only
22c64e9cbSAndy Shevchenko #include <linux/kernel.h>
32c64e9cbSAndy Shevchenko #include <linux/gcd.h>
42c64e9cbSAndy Shevchenko #include <linux/export.h>
52c64e9cbSAndy Shevchenko
62c64e9cbSAndy Shevchenko /*
72c64e9cbSAndy Shevchenko * This implements the binary GCD algorithm. (Often attributed to Stein,
82c64e9cbSAndy Shevchenko * but as Knuth has noted, appears in a first-century Chinese math text.)
92c64e9cbSAndy Shevchenko *
102c64e9cbSAndy Shevchenko * This is faster than the division-based algorithm even on x86, which
112c64e9cbSAndy Shevchenko * has decent hardware division.
122c64e9cbSAndy Shevchenko */
132c64e9cbSAndy Shevchenko
142c64e9cbSAndy Shevchenko #if !defined(CONFIG_CPU_NO_EFFICIENT_FFS)
152c64e9cbSAndy Shevchenko
162c64e9cbSAndy Shevchenko /* If __ffs is available, the even/odd algorithm benchmarks slower. */
172c64e9cbSAndy Shevchenko
182c64e9cbSAndy Shevchenko /**
192c64e9cbSAndy Shevchenko * gcd - calculate and return the greatest common divisor of 2 unsigned longs
202c64e9cbSAndy Shevchenko * @a: first value
212c64e9cbSAndy Shevchenko * @b: second value
222c64e9cbSAndy Shevchenko */
gcd(unsigned long a,unsigned long b)232c64e9cbSAndy Shevchenko unsigned long gcd(unsigned long a, unsigned long b)
242c64e9cbSAndy Shevchenko {
252c64e9cbSAndy Shevchenko unsigned long r = a | b;
262c64e9cbSAndy Shevchenko
272c64e9cbSAndy Shevchenko if (!a || !b)
282c64e9cbSAndy Shevchenko return r;
292c64e9cbSAndy Shevchenko
302c64e9cbSAndy Shevchenko b >>= __ffs(b);
312c64e9cbSAndy Shevchenko if (b == 1)
322c64e9cbSAndy Shevchenko return r & -r;
332c64e9cbSAndy Shevchenko
342c64e9cbSAndy Shevchenko for (;;) {
352c64e9cbSAndy Shevchenko a >>= __ffs(a);
362c64e9cbSAndy Shevchenko if (a == 1)
372c64e9cbSAndy Shevchenko return r & -r;
382c64e9cbSAndy Shevchenko if (a == b)
392c64e9cbSAndy Shevchenko return a << __ffs(r);
402c64e9cbSAndy Shevchenko
412c64e9cbSAndy Shevchenko if (a < b)
422c64e9cbSAndy Shevchenko swap(a, b);
432c64e9cbSAndy Shevchenko a -= b;
442c64e9cbSAndy Shevchenko }
452c64e9cbSAndy Shevchenko }
462c64e9cbSAndy Shevchenko
472c64e9cbSAndy Shevchenko #else
482c64e9cbSAndy Shevchenko
492c64e9cbSAndy Shevchenko /* If normalization is done by loops, the even/odd algorithm is a win. */
gcd(unsigned long a,unsigned long b)502c64e9cbSAndy Shevchenko unsigned long gcd(unsigned long a, unsigned long b)
512c64e9cbSAndy Shevchenko {
522c64e9cbSAndy Shevchenko unsigned long r = a | b;
532c64e9cbSAndy Shevchenko
542c64e9cbSAndy Shevchenko if (!a || !b)
552c64e9cbSAndy Shevchenko return r;
562c64e9cbSAndy Shevchenko
572c64e9cbSAndy Shevchenko /* Isolate lsbit of r */
582c64e9cbSAndy Shevchenko r &= -r;
592c64e9cbSAndy Shevchenko
602c64e9cbSAndy Shevchenko while (!(b & r))
612c64e9cbSAndy Shevchenko b >>= 1;
622c64e9cbSAndy Shevchenko if (b == r)
632c64e9cbSAndy Shevchenko return r;
642c64e9cbSAndy Shevchenko
652c64e9cbSAndy Shevchenko for (;;) {
662c64e9cbSAndy Shevchenko while (!(a & r))
672c64e9cbSAndy Shevchenko a >>= 1;
682c64e9cbSAndy Shevchenko if (a == r)
692c64e9cbSAndy Shevchenko return r;
702c64e9cbSAndy Shevchenko if (a == b)
712c64e9cbSAndy Shevchenko return a;
722c64e9cbSAndy Shevchenko
732c64e9cbSAndy Shevchenko if (a < b)
742c64e9cbSAndy Shevchenko swap(a, b);
752c64e9cbSAndy Shevchenko a -= b;
762c64e9cbSAndy Shevchenko a >>= 1;
772c64e9cbSAndy Shevchenko if (a & r)
782c64e9cbSAndy Shevchenko a += b;
792c64e9cbSAndy Shevchenko a >>= 1;
802c64e9cbSAndy Shevchenko }
812c64e9cbSAndy Shevchenko }
822c64e9cbSAndy Shevchenko
832c64e9cbSAndy Shevchenko #endif
842c64e9cbSAndy Shevchenko
852c64e9cbSAndy Shevchenko EXPORT_SYMBOL_GPL(gcd);
86