From c730705a13e27d02a5b3173c9348ea178a6bc8e7 Mon Sep 17 00:00:00 2001 From: Bruno BELANYI Date: Mon, 23 Aug 2021 16:33:05 +0200 Subject: [PATCH] abacus: bignum: add log2 --- src/bignum/bignum.cc | 24 ++++++++++++++++++++++++ src/bignum/bignum.hh | 2 ++ tests/unit/bignum.cc | 21 +++++++++++++++++++++ 3 files changed, 47 insertions(+) diff --git a/src/bignum/bignum.cc b/src/bignum/bignum.cc index 0f78275..677191b 100644 --- a/src/bignum/bignum.cc +++ b/src/bignum/bignum.cc @@ -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 diff --git a/src/bignum/bignum.hh b/src/bignum/bignum.hh index c75e042..1c5529e 100644 --- a/src/bignum/bignum.hh +++ b/src/bignum/bignum.hh @@ -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); } diff --git a/tests/unit/bignum.cc b/tests/unit/bignum.cc index 8040ed0..61ae839 100644 --- a/tests/unit/bignum.cc +++ b/tests/unit/bignum.cc @@ -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); +}