abacus: bignum: optimize div_mod

This commit is contained in:
Bruno BELANYI 2021-08-23 19:12:35 +02:00
parent 1521d2b232
commit c675b15248

View file

@ -139,27 +139,28 @@ std::pair<digits_type, digits_type> do_div_mod(digits_type const& lhs,
throw std::invalid_argument("attempt to divide by zero"); throw std::invalid_argument("attempt to divide by zero");
} }
digits_type multiple = rhs;
digits_type rank;
rank.push_back(1);
while (!do_less_than(lhs, multiple)) {
multiple = do_addition(multiple, multiple);
rank = do_addition(rank, rank);
}
digits_type quotient; digits_type quotient;
digits_type remainder = lhs; digits_type remainder = lhs;
while (!do_less_than(remainder, rhs)) { while (!do_less_than(remainder, rhs)) {
// TODO: use `do_halve` to back down after calculate highest multiple while (do_less_than(remainder, multiple)) {
digits_type multiple = rhs; multiple = do_halve(multiple);
digits_type rank; rank = do_halve(rank);
rank.push_back(1);
digits_type prev_multiple = multiple;
digits_type prev_rank = rank;
while (!do_less_than(remainder, multiple)) {
prev_multiple = multiple;
prev_rank = rank;
multiple = do_addition(multiple, multiple);
rank = do_addition(rank, rank);
} }
quotient = do_addition(quotient, prev_rank); assert(!do_less_than(multiple, rhs));
remainder = do_substraction(remainder, prev_multiple);
quotient = do_addition(quotient, rank);
remainder = do_substraction(remainder, multiple);
} }
return std::make_pair(quotient, remainder); return std::make_pair(quotient, remainder);