18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only 28c2ecf20Sopenharmony_ci#include <linux/kernel.h> 38c2ecf20Sopenharmony_ci#include <linux/gcd.h> 48c2ecf20Sopenharmony_ci#include <linux/export.h> 58c2ecf20Sopenharmony_ci 68c2ecf20Sopenharmony_ci/* 78c2ecf20Sopenharmony_ci * This implements the binary GCD algorithm. (Often attributed to Stein, 88c2ecf20Sopenharmony_ci * but as Knuth has noted, appears in a first-century Chinese math text.) 98c2ecf20Sopenharmony_ci * 108c2ecf20Sopenharmony_ci * This is faster than the division-based algorithm even on x86, which 118c2ecf20Sopenharmony_ci * has decent hardware division. 128c2ecf20Sopenharmony_ci */ 138c2ecf20Sopenharmony_ci 148c2ecf20Sopenharmony_ci#if !defined(CONFIG_CPU_NO_EFFICIENT_FFS) 158c2ecf20Sopenharmony_ci 168c2ecf20Sopenharmony_ci/* If __ffs is available, the even/odd algorithm benchmarks slower. */ 178c2ecf20Sopenharmony_ci 188c2ecf20Sopenharmony_ci/** 198c2ecf20Sopenharmony_ci * gcd - calculate and return the greatest common divisor of 2 unsigned longs 208c2ecf20Sopenharmony_ci * @a: first value 218c2ecf20Sopenharmony_ci * @b: second value 228c2ecf20Sopenharmony_ci */ 238c2ecf20Sopenharmony_ciunsigned long gcd(unsigned long a, unsigned long b) 248c2ecf20Sopenharmony_ci{ 258c2ecf20Sopenharmony_ci unsigned long r = a | b; 268c2ecf20Sopenharmony_ci 278c2ecf20Sopenharmony_ci if (!a || !b) 288c2ecf20Sopenharmony_ci return r; 298c2ecf20Sopenharmony_ci 308c2ecf20Sopenharmony_ci b >>= __ffs(b); 318c2ecf20Sopenharmony_ci if (b == 1) 328c2ecf20Sopenharmony_ci return r & -r; 338c2ecf20Sopenharmony_ci 348c2ecf20Sopenharmony_ci for (;;) { 358c2ecf20Sopenharmony_ci a >>= __ffs(a); 368c2ecf20Sopenharmony_ci if (a == 1) 378c2ecf20Sopenharmony_ci return r & -r; 388c2ecf20Sopenharmony_ci if (a == b) 398c2ecf20Sopenharmony_ci return a << __ffs(r); 408c2ecf20Sopenharmony_ci 418c2ecf20Sopenharmony_ci if (a < b) 428c2ecf20Sopenharmony_ci swap(a, b); 438c2ecf20Sopenharmony_ci a -= b; 448c2ecf20Sopenharmony_ci } 458c2ecf20Sopenharmony_ci} 468c2ecf20Sopenharmony_ci 478c2ecf20Sopenharmony_ci#else 488c2ecf20Sopenharmony_ci 498c2ecf20Sopenharmony_ci/* If normalization is done by loops, the even/odd algorithm is a win. */ 508c2ecf20Sopenharmony_ciunsigned long gcd(unsigned long a, unsigned long b) 518c2ecf20Sopenharmony_ci{ 528c2ecf20Sopenharmony_ci unsigned long r = a | b; 538c2ecf20Sopenharmony_ci 548c2ecf20Sopenharmony_ci if (!a || !b) 558c2ecf20Sopenharmony_ci return r; 568c2ecf20Sopenharmony_ci 578c2ecf20Sopenharmony_ci /* Isolate lsbit of r */ 588c2ecf20Sopenharmony_ci r &= -r; 598c2ecf20Sopenharmony_ci 608c2ecf20Sopenharmony_ci while (!(b & r)) 618c2ecf20Sopenharmony_ci b >>= 1; 628c2ecf20Sopenharmony_ci if (b == r) 638c2ecf20Sopenharmony_ci return r; 648c2ecf20Sopenharmony_ci 658c2ecf20Sopenharmony_ci for (;;) { 668c2ecf20Sopenharmony_ci while (!(a & r)) 678c2ecf20Sopenharmony_ci a >>= 1; 688c2ecf20Sopenharmony_ci if (a == r) 698c2ecf20Sopenharmony_ci return r; 708c2ecf20Sopenharmony_ci if (a == b) 718c2ecf20Sopenharmony_ci return a; 728c2ecf20Sopenharmony_ci 738c2ecf20Sopenharmony_ci if (a < b) 748c2ecf20Sopenharmony_ci swap(a, b); 758c2ecf20Sopenharmony_ci a -= b; 768c2ecf20Sopenharmony_ci a >>= 1; 778c2ecf20Sopenharmony_ci if (a & r) 788c2ecf20Sopenharmony_ci a += b; 798c2ecf20Sopenharmony_ci a >>= 1; 808c2ecf20Sopenharmony_ci } 818c2ecf20Sopenharmony_ci} 828c2ecf20Sopenharmony_ci 838c2ecf20Sopenharmony_ci#endif 848c2ecf20Sopenharmony_ci 858c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(gcd); 86