|
@@ -13,8 +13,8 @@ namespace detail {
|
|
|
using data_type = biginteger::data_type;
|
|
using data_type = biginteger::data_type;
|
|
|
// 1 => GREATER, 0 => EQUAL, -1 => LESS
|
|
// 1 => GREATER, 0 => EQUAL, -1 => LESS
|
|
|
int compare(data_type const & rhs, data_type const & lhs);
|
|
int compare(data_type const & rhs, data_type const & lhs);
|
|
|
- data_type add(data_type const & rhs, data_type const & lhs);
|
|
|
|
|
- data_type subtract_nounderflow(data_type const & rhs, data_type const & lhs);
|
|
|
|
|
|
|
+ data_type add(data_type rhs, data_type const & lhs);
|
|
|
|
|
+ data_type subtract_nounderflow(data_type rhs, data_type const & lhs);
|
|
|
data_type multiply(data_type const & rhs, data_type const & lhs);
|
|
data_type multiply(data_type const & rhs, data_type const & lhs);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
@@ -121,62 +121,65 @@ namespace detail {
|
|
|
|
|
|
|
|
int compare(data_type const & rhs, data_type const & lhs) {
|
|
int compare(data_type const & rhs, data_type const & lhs) {
|
|
|
IMPL_COMPARE(.size());
|
|
IMPL_COMPARE(.size());
|
|
|
- for (data_type::size_type i = rhs.size(); i > 0; --i) {
|
|
|
|
|
|
|
+ for (size_t i = rhs.size(); i > 0; --i) {
|
|
|
IMPL_COMPARE([i-1]);
|
|
IMPL_COMPARE([i-1]);
|
|
|
}
|
|
}
|
|
|
return 0;
|
|
return 0;
|
|
|
}
|
|
}
|
|
|
#undef IMPL_COMPARE
|
|
#undef IMPL_COMPARE
|
|
|
|
|
|
|
|
- data_type add(data_type const & rhs, data_type const & lhs) {
|
|
|
|
|
- data_type::size_type const rbnd = rhs.size(), lbnd = lhs.size();
|
|
|
|
|
- data_type::size_type const ubnd = std::max(rbnd, lbnd);
|
|
|
|
|
- data_type rval(ubnd+1);
|
|
|
|
|
|
|
+ void add_into(data_type & rhs, data_type const & lhs) {
|
|
|
|
|
+ rhs.resize(std::max(rhs.size(), lhs.size())+1);
|
|
|
|
|
+ auto const lbnd = lhs.size(), ubnd = rhs.size() - 1;
|
|
|
// Add
|
|
// Add
|
|
|
- for (data_type::size_type i = 0; i < rbnd; ++i) {
|
|
|
|
|
- rval[i] += rhs[i];
|
|
|
|
|
- }
|
|
|
|
|
- for (data_type::size_type i = 0; i < lbnd; ++i) {
|
|
|
|
|
- rval[i] += lhs[i];
|
|
|
|
|
|
|
+ for (size_t i = 0; i < lbnd; ++i) {
|
|
|
|
|
+ rhs[i] += lhs[i];
|
|
|
}
|
|
}
|
|
|
// Carry
|
|
// Carry
|
|
|
- for (data_type::size_type i = 0; i < ubnd; ++i) {
|
|
|
|
|
- if (rval[i] > biginteger::MAX_SEG) {
|
|
|
|
|
- rval[i] -= biginteger::OVER_SEG;
|
|
|
|
|
- rval[i+1] += 1;
|
|
|
|
|
|
|
+ for (size_t i = 0; i < ubnd; ++i) {
|
|
|
|
|
+ if (rhs[i] > biginteger::MAX_SEG) {
|
|
|
|
|
+ rhs[i] -= biginteger::OVER_SEG;
|
|
|
|
|
+ rhs[i+1] += 1;
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
- if (rval[ubnd] == 0) { rval.pop_back(); }
|
|
|
|
|
- return rval;
|
|
|
|
|
|
|
+ if (rhs[ubnd] == 0) { rhs.pop_back(); }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ data_type add(data_type rhs, data_type const & lhs) {
|
|
|
|
|
+ add_into(rhs, lhs);
|
|
|
|
|
+ return rhs;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- data_type subtract_nounderflow(data_type const & rhs, data_type const & lhs) {
|
|
|
|
|
- data_type::size_type const rbnd = rhs.size(), lbnd = lhs.size();
|
|
|
|
|
- data_type rval{rhs};
|
|
|
|
|
|
|
+ void subtract_from(data_type & rhs, data_type const & lhs) {
|
|
|
|
|
+ size_t const rbnd = rhs.size(), lbnd = lhs.size();
|
|
|
// Subtract
|
|
// Subtract
|
|
|
- for (data_type::size_type i = 0; i < lbnd; ++i) {
|
|
|
|
|
- rval[i] -= lhs[i];
|
|
|
|
|
|
|
+ for (size_t i = 0; i < lbnd; ++i) {
|
|
|
|
|
+ rhs[i] -= lhs[i];
|
|
|
}
|
|
}
|
|
|
// Borrow
|
|
// Borrow
|
|
|
- for (data_type::size_type i = 0; i < rbnd; ++i) {
|
|
|
|
|
- if (rval[i] < 0) {
|
|
|
|
|
- rval[i] += biginteger::OVER_SEG;
|
|
|
|
|
- rval[i+1] -= 1;
|
|
|
|
|
|
|
+ for (size_t i = 0; i < rbnd; ++i) {
|
|
|
|
|
+ if (rhs[i] < 0) {
|
|
|
|
|
+ rhs[i] += biginteger::OVER_SEG;
|
|
|
|
|
+ rhs[i+1] -= 1;
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
- if (rval[rbnd-1] == 0 && rbnd > 1) { rval.pop_back(); }
|
|
|
|
|
- return rval;
|
|
|
|
|
|
|
+ if (rhs[rbnd-1] == 0 && rbnd > 1) { rhs.pop_back(); }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ data_type subtract_nounderflow(data_type rhs, data_type const & lhs) {
|
|
|
|
|
+ subtract_from(rhs, lhs);
|
|
|
|
|
+ return rhs;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
data_type multiply(data_type const & rhs, data_type const & lhs) {
|
|
data_type multiply(data_type const & rhs, data_type const & lhs) {
|
|
|
if (compare(rhs, {1}) == 0) { return lhs; }
|
|
if (compare(rhs, {1}) == 0) { return lhs; }
|
|
|
else if (compare(lhs, {1}) == 0) { return rhs; }
|
|
else if (compare(lhs, {1}) == 0) { return rhs; }
|
|
|
- data_type::size_type const rbnd = rhs.size(), lbnd = lhs.size();
|
|
|
|
|
- data_type::size_type const ubnd = rbnd + lbnd;
|
|
|
|
|
|
|
+ size_t const rbnd = rhs.size(), lbnd = lhs.size();
|
|
|
|
|
+ size_t const ubnd = rbnd + lbnd;
|
|
|
data_type rval(ubnd + 1);
|
|
data_type rval(ubnd + 1);
|
|
|
// Multiply
|
|
// Multiply
|
|
|
- for (data_type::size_type i = 0; i < rbnd; ++i) {
|
|
|
|
|
- for (data_type::size_type j = 0; j < lbnd; ++j) {
|
|
|
|
|
|
|
+ for (size_t i = 0; i < rbnd; ++i) {
|
|
|
|
|
+ for (size_t j = 0; j < lbnd; ++j) {
|
|
|
// Max input 999,999,999
|
|
// Max input 999,999,999
|
|
|
// Max output 999,999,998,000,000,001
|
|
// Max output 999,999,998,000,000,001
|
|
|
int64_t product = static_cast<int64_t>(rhs[i]) * static_cast<int64_t>(lhs[j]);
|
|
int64_t product = static_cast<int64_t>(rhs[i]) * static_cast<int64_t>(lhs[j]);
|
|
@@ -186,7 +189,7 @@ namespace detail {
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
// Carry
|
|
// Carry
|
|
|
- for (data_type::size_type i = 0; i < ubnd; ++i) {
|
|
|
|
|
|
|
+ for (size_t i = 0; i < ubnd; ++i) {
|
|
|
if (rval[i] > biginteger::MAX_SEG) {
|
|
if (rval[i] > biginteger::MAX_SEG) {
|
|
|
int32_t overflow = rval[i] / biginteger::OVER_SEG;
|
|
int32_t overflow = rval[i] / biginteger::OVER_SEG;
|
|
|
rval[i] -= (overflow * biginteger::OVER_SEG);
|
|
rval[i] -= (overflow * biginteger::OVER_SEG);
|