[libcxx-commits] [libcxx] [libc++] Implement std::gcd using the binary version (PR #77747)
via libcxx-commits
libcxx-commits at lists.llvm.org
Wed Apr 24 14:37:54 PDT 2024
================
@@ -50,9 +52,25 @@ struct __ct_abs<_Result, _Source, false> {
};
template <class _Tp>
-_LIBCPP_CONSTEXPR _LIBCPP_HIDDEN _Tp __gcd(_Tp __m, _Tp __n) {
+_LIBCPP_CONSTEXPR _LIBCPP_HIDDEN _Tp __gcd(_Tp __a, _Tp __b) {
static_assert((!is_signed<_Tp>::value), "");
- return __n == 0 ? __m : std::__gcd<_Tp>(__n, __m % __n);
+ if (__a == 0)
+ return __b;
+ if (__b == 0)
+ return __a;
+
+ int __az = std::__countr_zero(__a);
+ int __bz = std::__countr_zero(__b);
+ int __shift = std::min(__az, __bz);
+ __b >>= __bz;
+ while (__a != 0) {
+ __a >>= __az;
+ _Tp __absdiff = __a > __b ? __a - __b : __b - __a;
+ __b = std::min(__a, __b);
+ __a = __absdiff;
+ __az = std::__countr_zero(__absdiff);
+ }
+ return __b << __shift;
----------------
AdvenamTacet wrote:
I would be happy, if that information is included:
```
If power of two divides both numbers, we can push it out.
- gcd( 2^x * a, 2^x * b) = 2^x * gcd(a, b)
If and only if exactly one number is even, we can divide that number by that power.
- if a, b are odd, then gcd(2^x * a, b) = gcd(a, b)
And standard gcd algorithm where instead of modulo, minus is used.
```
https://github.com/llvm/llvm-project/pull/77747
More information about the libcxx-commits
mailing list