|
|
@@ -82,10 +82,10 @@ namespace math { namespace detail {
|
|
|
for (size_t j = lbnd; j > 0; --j) {
|
|
|
// Max input 999,999,999
|
|
|
// Max output 999,999,998,000,000,001
|
|
|
- int64_t product = static_cast<int64_t>(value) * static_cast<int64_t>(lhs[j-1]);
|
|
|
+ int64_t product = int64_t(value) * lhs[j-1];
|
|
|
int64_t overflow = product / OVER_SEG;
|
|
|
- rhs[i+j-2] += static_cast<int32_t>(product - (overflow * OVER_SEG));
|
|
|
- rhs[i+j-1] += static_cast<int32_t>(overflow);
|
|
|
+ rhs[i+j-2] += int32_t(product - (overflow * OVER_SEG));
|
|
|
+ rhs[i+j-1] += int32_t(overflow);
|
|
|
}
|
|
|
rhs[i-1] -= value;
|
|
|
}
|
|
|
@@ -100,29 +100,37 @@ namespace math { namespace detail {
|
|
|
while (rhs.back() == 0) { rhs.pop_back(); }
|
|
|
}
|
|
|
|
|
|
- data_type shift10(data_type const & data, int32_t pow, size_t shift) {
|
|
|
+ int32_t powers[] = { 1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000 };
|
|
|
+
|
|
|
+ data_type shift10(data_type const & data, int32_t places) {
|
|
|
+ int32_t shift = places / SEG_DIGITS;
|
|
|
+ if (places < 0) { --shift; }
|
|
|
+ int64_t const pow = powers[places - (shift * SEG_DIGITS)];
|
|
|
size_t const bnd = data.size();
|
|
|
- data_type rval(bnd + shift + 1);
|
|
|
- for (size_t i = 0; i < bnd; ++i) {
|
|
|
- int64_t product = static_cast<int64_t>(data[i]) * static_cast<int64_t>(pow);
|
|
|
+ data_type rval(size_t((int32_t)bnd + shift) + 1);
|
|
|
+ for (size_t i = 0, o = size_t(std::max(0, shift));
|
|
|
+ i < bnd; ++i, ++o) {
|
|
|
+ int64_t product = int64_t(data[i]) * pow;
|
|
|
int64_t overflow = product / OVER_SEG;
|
|
|
- rval[i+shift] += static_cast<int32_t>(product - (overflow * OVER_SEG));
|
|
|
- rval[i+shift+1] += static_cast<int32_t>(overflow);
|
|
|
+ rval[o] += int32_t(product - (overflow * OVER_SEG));
|
|
|
+ rval[o+1] += int32_t(overflow);
|
|
|
+ }
|
|
|
+ if (shift < 0) {
|
|
|
+ // TODO rounding
|
|
|
+ rval.erase(rval.begin(), rval.begin()-shift);
|
|
|
}
|
|
|
if (rval.back() == 0 && rval.size() > 1) { rval.pop_back(); }
|
|
|
return rval;
|
|
|
}
|
|
|
|
|
|
size_t digits(int32_t val) {
|
|
|
- return val == 0 ? 1 : static_cast<size_t>(floor(log10(val))) + 1;
|
|
|
+ return val == 0 ? 1 : size_t(floor(log10(val))) + 1;
|
|
|
}
|
|
|
|
|
|
size_t digits(data_type const & data) {
|
|
|
return SEG_DIGITS * (data.size()-1) + digits(data.back());
|
|
|
}
|
|
|
|
|
|
- int32_t powers[] = { 1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000 };
|
|
|
-
|
|
|
data_type divide(data_type & remainder, data_type const & divisor) {
|
|
|
data_type accum{0};
|
|
|
auto const dig = digits(divisor);
|
|
|
@@ -130,7 +138,7 @@ namespace math { namespace detail {
|
|
|
auto const diff = std::max(1UL, digits(remainder) - dig) - 1;
|
|
|
auto const shift = diff / SEG_DIGITS;
|
|
|
auto const ipow = diff - (shift * SEG_DIGITS);
|
|
|
- data_type value{shift10(divisor, powers[ipow], 0)};
|
|
|
+ data_type value{shift10(divisor, int32_t(ipow))};
|
|
|
do {
|
|
|
subtract_nounderflow(remainder, value, shift);
|
|
|
add(accum, powers[ipow], shift);
|