abacus: bignum: add log2

This commit is contained in:
Bruno BELANYI 2021-08-23 16:33:05 +02:00
parent 4b85d22923
commit c730705a13
3 changed files with 47 additions and 0 deletions
src/bignum
tests/unit

View file

@ -468,4 +468,28 @@ BigNum sqrt(BigNum const& num) {
return res;
}
BigNum log2(BigNum const& num) {
assert(num.is_canonicalized());
if (num.is_zero()) {
throw std::invalid_argument("attempt to take the log2 of zero");
} else if (num.is_negative()) {
throw std::invalid_argument(
"attempt to take the log2 of a negative number");
}
auto tmp = num;
auto res = BigNum(0);
auto one = BigNum(1);
while (tmp > one) {
tmp.digits_ = do_halve(tmp.digits_);
res += one;
}
assert(res.is_canonicalized());
return res;
}
} // namespace abacus::bignum

View file

@ -91,6 +91,8 @@ public:
friend BigNum sqrt(BigNum const& num);
friend BigNum log2(BigNum const& num);
friend bool operator==(BigNum const& lhs, BigNum const& rhs) {
return lhs.equal(rhs);
}

View file

@ -376,3 +376,24 @@ TEST(BigNum, sqrt) {
EXPECT_EQ(sqrt(ninety_nine), nine);
EXPECT_EQ(sqrt(hundred), ten);
}
TEST(BigNum, log2) {
auto const zero = BigNum(0);
auto const one = BigNum(1);
auto const two = BigNum(2);
auto const three = BigNum(3);
auto const four = BigNum(4);
auto const five = BigNum(5);
auto const seven = BigNum(7);
auto const eight = BigNum(8);
auto const nine = BigNum(9);
EXPECT_EQ(log2(one), zero);
EXPECT_EQ(log2(two), one);
EXPECT_EQ(log2(three), one);
EXPECT_EQ(log2(four), two);
EXPECT_EQ(log2(five), two);
EXPECT_EQ(log2(seven), two);
EXPECT_EQ(log2(eight), three);
EXPECT_EQ(log2(nine), three);
}