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 */ 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. */ 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