|
|
@@ -156,7 +156,6 @@ static bool is_one(bigdecimal::data_type const & data, int32_t scale) {
|
|
|
|
|
|
bigdecimal & math::operator*=(bigdecimal & rhs, bigdecimal const & lhs) {
|
|
|
int32_t const new_scale = rhs.scale_ + lhs.scale_;
|
|
|
- size_t const offset = mul_scale(rhs.scale_) + mul_scale(lhs.scale_) - mul_scale(new_scale);
|
|
|
bool is_neg = rhs.is_negative != lhs.is_negative;
|
|
|
if (rhs == bigdecimal::ZERO || lhs == bigdecimal::ZERO) {
|
|
|
rhs = bigdecimal::ZERO;
|
|
|
@@ -166,11 +165,11 @@ bigdecimal & math::operator*=(bigdecimal & rhs, bigdecimal const & lhs) {
|
|
|
rhs = lhs;
|
|
|
rhs.is_negative = is_neg;
|
|
|
} else {
|
|
|
- detail::multiply(rhs.data, lhs.data, offset);
|
|
|
- int32_t const steps = add_scale(rhs.scale_), nsteps = add_scale(new_scale);
|
|
|
- int32_t const off1 = (steps <= 0 ? 0 : 1), off2 = (steps < 0 ? 0 : 1);
|
|
|
- if (steps - off1 > nsteps) {
|
|
|
- rhs.data.erase(rhs.data.begin(), rhs.data.begin() + steps - nsteps - off1);
|
|
|
+ detail::multiply(rhs.data, lhs.data);
|
|
|
+ int32_t const steps = add_scale(rhs.scale_) + add_scale(lhs.scale_), nsteps = add_scale(new_scale);
|
|
|
+ int32_t const off2 = (steps < 0 ? 0 : 1);
|
|
|
+ if (steps > nsteps) {
|
|
|
+ rhs.data.erase(rhs.data.begin(), rhs.data.begin() + steps - nsteps);
|
|
|
} else if (steps + off2 < nsteps) {
|
|
|
rhs.data.insert(rhs.data.begin(), size_t(nsteps-steps-off2), 0);
|
|
|
}
|
|
|
@@ -224,23 +223,25 @@ bool math::operator==(bigdecimal const & lhs, bigdecimal const & rhs) {
|
|
|
bigdecimal const bigdecimal::ZERO{0}, bigdecimal::ONE{1}, bigdecimal::NEGATIVE_ONE{-1};
|
|
|
|
|
|
std::string bigdecimal::to_string() const {
|
|
|
- std::vector<char> output(biginteger::SEG_DIGITS * data.size() + 1, '\0');
|
|
|
- std::ptrdiff_t idx = 0;
|
|
|
- if (is_negative) { output[0] = '-'; ++idx; }
|
|
|
- idx += sprintf(output.data() + idx, "%d", data[data.size()-1]);
|
|
|
- size_t i = data.size()-1;
|
|
|
- for (; i > size_t(std::max(0, add_scale(scale_))); --i, idx+=SEG_DIGITS) {
|
|
|
- sprintf(output.data() + idx, "%0.*d", SEG_DIGITS, data[i-1]);
|
|
|
+ size_t const decimal_split = size_t(std::max(0, add_scale(scale_)));
|
|
|
+ int32_t const hidden = std::max(0, SEG_DIGITS * (-scale_/SEG_DIGITS));
|
|
|
+ size_t const chars = SEG_DIGITS * data.size() + size_t(hidden);
|
|
|
+ std::vector<char> output(chars + 3, '\0');
|
|
|
+ char * ptr = output.data();
|
|
|
+ if (is_negative) { *ptr++ = '-'; }
|
|
|
+ ptr += sprintf(ptr, "%d", data.back());
|
|
|
+ for (size_t i = data.size()-1; i > decimal_split; --i) {
|
|
|
+ ptr += sprintf(ptr, "%0.*d", SEG_DIGITS, data[i-1]);
|
|
|
}
|
|
|
- if (scale_ > 0) { // TODO: scale > size?
|
|
|
- sprintf(output.data() + idx++, ".");
|
|
|
- for (; i > 1; --i, idx+=SEG_DIGITS) {
|
|
|
- sprintf(output.data() + idx, "%0.*d", SEG_DIGITS, data[i-1]);
|
|
|
+ if (scale_ > 0) {
|
|
|
+ *ptr++ = '.';
|
|
|
+ for (size_t i = decimal_split; i > 1; --i) {
|
|
|
+ ptr += sprintf(ptr, "%0.*d", SEG_DIGITS, data[i-1]);
|
|
|
}
|
|
|
int32_t const val = scale_ % SEG_DIGITS;
|
|
|
- sprintf(output.data() + idx, "%0.*d", val, data[0]/detail::powers[SEG_DIGITS-val]);
|
|
|
- } else if (scale_ < 0) {
|
|
|
- output.insert(output.begin() + idx, size_t(-SEG_DIGITS*add_scale(scale_)), '0');
|
|
|
+ sprintf(ptr, "%0.*d", val, data[0]/detail::powers[SEG_DIGITS-val]);
|
|
|
+ } else {
|
|
|
+ sprintf(ptr, "%0.*d", hidden, 0);
|
|
|
}
|
|
|
return output.data();
|
|
|
}
|