abacus: bignum: add multiplication

This commit is contained in:
Bruno BELANYI 2021-08-20 22:19:20 +02:00
parent eb47889eef
commit 4a4b9f361c
3 changed files with 85 additions and 0 deletions

View file

@ -69,6 +69,23 @@ digits_type do_substraction(digits_type const& lhs, digits_type const& rhs) {
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
BigNum::BigNum(std::int64_t number) {
@ -188,6 +205,21 @@ void BigNum::substract(BigNum const& rhs) {
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 {
assert(is_canonicalized());
assert(rhs.is_canonicalized());

View file

@ -51,6 +51,17 @@ public:
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) {
return lhs.equal(rhs);
}
@ -82,6 +93,7 @@ private:
void flip_sign();
void add(BigNum const& rhs);
void substract(BigNum const& rhs);
void multiply(BigNum const& rhs);
bool equal(BigNum const& rhs) const;
bool less_than(BigNum const& rhs) const;