Compare commits
3 commits
31dcb91a26
...
c675b15248
Author | SHA1 | Date | |
---|---|---|---|
Bruno BELANYI | c675b15248 | ||
Bruno BELANYI | 1521d2b232 | ||
Bruno BELANYI | a99f60dcd4 |
|
@ -30,6 +30,35 @@ void trim_leading_zeros(digits_type& num) {
|
||||||
num.erase(it.base(), num.end());
|
num.erase(it.base(), num.end());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// More optimised than full-on div_mod
|
||||||
|
digits_type do_halve(digits_type num) {
|
||||||
|
assert(num.size() != 0);
|
||||||
|
|
||||||
|
int carry = 0;
|
||||||
|
for (auto i = num.rbegin(); i != num.rend(); ++i) {
|
||||||
|
auto const was_odd = (*i % 2) == 1;
|
||||||
|
*i /= 2;
|
||||||
|
*i += carry;
|
||||||
|
if (was_odd) {
|
||||||
|
carry = BASE / 2;
|
||||||
|
} else {
|
||||||
|
carry = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
trim_leading_zeros(num);
|
||||||
|
|
||||||
|
return num;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool is_odd(digits_type const& num) {
|
||||||
|
if (num.size() == 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (num.front() % 2) == 1;
|
||||||
|
}
|
||||||
|
|
||||||
digits_type do_addition(digits_type const& lhs, digits_type const& rhs) {
|
digits_type do_addition(digits_type const& lhs, digits_type const& rhs) {
|
||||||
int carry = 0;
|
int carry = 0;
|
||||||
digits_type res;
|
digits_type res;
|
||||||
|
@ -110,59 +139,33 @@ 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 quotient;
|
|
||||||
digits_type remainder = lhs;
|
|
||||||
|
|
||||||
while (!do_less_than(remainder, rhs)) {
|
|
||||||
// TODO: use `do_halve` to back down after calculate highest multiple
|
|
||||||
digits_type multiple = rhs;
|
digits_type multiple = rhs;
|
||||||
digits_type rank;
|
digits_type rank;
|
||||||
rank.push_back(1);
|
rank.push_back(1);
|
||||||
|
|
||||||
digits_type prev_multiple = multiple;
|
while (!do_less_than(lhs, multiple)) {
|
||||||
digits_type prev_rank = rank;
|
|
||||||
|
|
||||||
while (!do_less_than(remainder, multiple)) {
|
|
||||||
prev_multiple = multiple;
|
|
||||||
prev_rank = rank;
|
|
||||||
multiple = do_addition(multiple, multiple);
|
multiple = do_addition(multiple, multiple);
|
||||||
rank = do_addition(rank, rank);
|
rank = do_addition(rank, rank);
|
||||||
}
|
}
|
||||||
|
|
||||||
quotient = do_addition(quotient, prev_rank);
|
digits_type quotient;
|
||||||
remainder = do_substraction(remainder, prev_multiple);
|
digits_type remainder = lhs;
|
||||||
|
|
||||||
|
while (!do_less_than(remainder, rhs)) {
|
||||||
|
while (do_less_than(remainder, multiple)) {
|
||||||
|
multiple = do_halve(multiple);
|
||||||
|
rank = do_halve(rank);
|
||||||
|
}
|
||||||
|
|
||||||
|
assert(!do_less_than(multiple, rhs));
|
||||||
|
|
||||||
|
quotient = do_addition(quotient, rank);
|
||||||
|
remainder = do_substraction(remainder, multiple);
|
||||||
}
|
}
|
||||||
|
|
||||||
return std::make_pair(quotient, remainder);
|
return std::make_pair(quotient, remainder);
|
||||||
}
|
}
|
||||||
|
|
||||||
// More optimised than full-on div_mod
|
|
||||||
digits_type do_halve(digits_type num) {
|
|
||||||
assert(num.size() != 0);
|
|
||||||
|
|
||||||
int carry = 0;
|
|
||||||
for (auto i = num.rbegin(); i != num.rend(); ++i) {
|
|
||||||
auto const was_odd = (*i % 2) == 1;
|
|
||||||
*i /= 2;
|
|
||||||
*i += carry;
|
|
||||||
if (was_odd) {
|
|
||||||
carry = BASE / 2;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
trim_leading_zeros(num);
|
|
||||||
|
|
||||||
return num;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool is_odd(digits_type const& num) {
|
|
||||||
if (num.size() == 0) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return (num.front() % 2) == 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
digits_type do_pow(digits_type lhs, digits_type rhs) {
|
digits_type do_pow(digits_type lhs, digits_type rhs) {
|
||||||
assert(rhs.size() != 0);
|
assert(rhs.size() != 0);
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue