abacus: bignum: add multiplication
This commit is contained in:
parent
eb47889eef
commit
4a4b9f361c
|
@ -69,6 +69,23 @@ digits_type do_substraction(digits_type const& lhs, digits_type const& rhs) {
|
||||||
return complement;
|
return complement;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
digits_type do_multiplication(digits_type const& lhs, digits_type const& rhs) {
|
||||||
|
digits_type res(lhs.size() + rhs.size());
|
||||||
|
|
||||||
|
for (std::size_t i = 0; i < lhs.size(); ++i) {
|
||||||
|
int carry = 0;
|
||||||
|
for (std::size_t j = 0; j < rhs.size(); ++j) {
|
||||||
|
int multiplication = lhs[i] * rhs[j];
|
||||||
|
res[i + j] += multiplication + carry;
|
||||||
|
carry = res[i + j] / 10;
|
||||||
|
res[i + j] %= 10;
|
||||||
|
}
|
||||||
|
res[i + rhs.size()] += carry;
|
||||||
|
}
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
BigNum::BigNum(std::int64_t number) {
|
BigNum::BigNum(std::int64_t number) {
|
||||||
|
@ -188,6 +205,21 @@ void BigNum::substract(BigNum const& rhs) {
|
||||||
assert(is_canonicalized());
|
assert(is_canonicalized());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void BigNum::multiply(BigNum const& rhs) {
|
||||||
|
assert(is_canonicalized());
|
||||||
|
assert(rhs.is_canonicalized());
|
||||||
|
|
||||||
|
if (sign_ == 0 || rhs.sign_ == 0) {
|
||||||
|
*this = BigNum();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
digits_ = do_multiplication(digits_, rhs.digits_);
|
||||||
|
sign_ *= rhs.sign_;
|
||||||
|
|
||||||
|
canonicalize();
|
||||||
|
}
|
||||||
|
|
||||||
bool BigNum::equal(BigNum const& rhs) const {
|
bool BigNum::equal(BigNum const& rhs) const {
|
||||||
assert(is_canonicalized());
|
assert(is_canonicalized());
|
||||||
assert(rhs.is_canonicalized());
|
assert(rhs.is_canonicalized());
|
||||||
|
|
|
@ -51,6 +51,17 @@ public:
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
friend BigNum& operator*=(BigNum& lhs, BigNum const& rhs) {
|
||||||
|
lhs.multiply(rhs);
|
||||||
|
return lhs;
|
||||||
|
}
|
||||||
|
|
||||||
|
friend BigNum operator*(BigNum const& lhs, BigNum const& rhs) {
|
||||||
|
auto ret = lhs;
|
||||||
|
ret *= rhs;
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
friend bool operator==(BigNum const& lhs, BigNum const& rhs) {
|
friend bool operator==(BigNum const& lhs, BigNum const& rhs) {
|
||||||
return lhs.equal(rhs);
|
return lhs.equal(rhs);
|
||||||
}
|
}
|
||||||
|
@ -82,6 +93,7 @@ private:
|
||||||
void flip_sign();
|
void flip_sign();
|
||||||
void add(BigNum const& rhs);
|
void add(BigNum const& rhs);
|
||||||
void substract(BigNum const& rhs);
|
void substract(BigNum const& rhs);
|
||||||
|
void multiply(BigNum const& rhs);
|
||||||
|
|
||||||
bool equal(BigNum const& rhs) const;
|
bool equal(BigNum const& rhs) const;
|
||||||
bool less_than(BigNum const& rhs) const;
|
bool less_than(BigNum const& rhs) const;
|
||||||
|
|
|
@ -156,3 +156,44 @@ TEST(BigNum, substraction_flips_sign) {
|
||||||
EXPECT_EQ(one - two, minus_one);
|
EXPECT_EQ(one - two, minus_one);
|
||||||
EXPECT_EQ(minus_one - minus_two, one);
|
EXPECT_EQ(minus_one - minus_two, one);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST(BigNum, multiplication_zero) {
|
||||||
|
auto const zero = BigNum(0);
|
||||||
|
auto const one = BigNum(1);
|
||||||
|
auto const minus_one = BigNum(-1);
|
||||||
|
|
||||||
|
EXPECT_EQ(zero * zero, zero);
|
||||||
|
EXPECT_EQ(zero * one, zero);
|
||||||
|
EXPECT_EQ(one * zero, zero);
|
||||||
|
EXPECT_EQ(zero * minus_one, zero);
|
||||||
|
EXPECT_EQ(minus_one * zero, zero);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(BigNum, multiplication_positive) {
|
||||||
|
auto const one = BigNum(1);
|
||||||
|
auto const two = BigNum(2);
|
||||||
|
auto const four = BigNum(4);
|
||||||
|
|
||||||
|
EXPECT_EQ(one * one, one);
|
||||||
|
EXPECT_EQ(two * one, two);
|
||||||
|
EXPECT_EQ(one * two, two);
|
||||||
|
EXPECT_EQ(two * two, four);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(BigNum, multiplication_mixed_signs) {
|
||||||
|
auto const minus_one = BigNum(-1);
|
||||||
|
auto const one = BigNum(1);
|
||||||
|
auto const minus_two = BigNum(-2);
|
||||||
|
auto const two = BigNum(2);
|
||||||
|
auto const minus_four = BigNum(-4);
|
||||||
|
auto const four = BigNum(4);
|
||||||
|
|
||||||
|
EXPECT_EQ(one * minus_one, minus_one);
|
||||||
|
EXPECT_EQ(minus_one * one, minus_one);
|
||||||
|
EXPECT_EQ(minus_one * minus_one, one);
|
||||||
|
EXPECT_EQ(two * minus_one, minus_two);
|
||||||
|
EXPECT_EQ(minus_one * two, minus_two);
|
||||||
|
EXPECT_EQ(two * minus_two, minus_four);
|
||||||
|
EXPECT_EQ(minus_two * two, minus_four);
|
||||||
|
EXPECT_EQ(minus_two * minus_two, four);
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue