[core] greatest common divisor and tests

This commit is contained in:
ExMix 2014-08-13 14:19:13 +03:00 committed by Alex Zolotarev
parent 3f76c76d04
commit 3587e8ccc9
2 changed files with 55 additions and 0 deletions

View file

@ -131,3 +131,13 @@ UNIT_TEST(IsIntersect_Intervals)
TEST(my::IsIntersect(0, 100, -50, 0), ());
TEST(!my::IsIntersect(0, 100, -50, -20), ());
}
UNIT_TEST(GCD_Test)
{
TEST_EQUAL(my::GCD(6, 3), 3, ());
TEST_EQUAL(my::GCD(14, 7), 7, ());
TEST_EQUAL(my::GCD(100, 100), 100, ());
TEST_EQUAL(my::GCD(7, 3), 1, ());
TEST_EQUAL(my::GCD(8, 3), 1, ());
TEST_EQUAL(my::GCD(9, 3), 3, ());
}

View file

@ -139,4 +139,49 @@ inline uint32_t NextPowOf2(uint32_t v)
return v + 1;
}
// Greatest Common Divisor
inline uint32_t GCD(uint32_t a, uint32_t b)
{
uint32_t multiplier = 1;
uint32_t gcd = 1;
while (true)
{
if (a == 0 || b == 0)
{
gcd = max(a, b);
break;
}
if (a == 1 || b == 1)
{
gcd = 1;
break;
}
if ((a & 0x1) == 0 && (b & 0x1) == 0)
{
multiplier <<= 1;
a >>= 1;
b >>= 1;
continue;
}
if ((a & 0x1) != 0 && (b & 0x1) != 0)
{
uint32_t minV = min(a, b);
uint32_t maxV = max(a, b);
a = (maxV - minV) >> 1;
b = minV;
continue;
}
if ((a & 0x1) != 0)
swap(a, b);
a >>= 1;
}
return multiplier * gcd;
}
}