Merge "Expand big decimal with arithmetic operators" from Piotr
" This miniseries expands big_decimal interface with convenience operators (-=, +, -), provides test cases for it and makes one of the constructors explicit. Tests: unit(dev) " * 'expand_big_decimal_interface' of https://github.com/psarna/scylla: utils: make string-based big decimal constructor explicit tests: add more operators to big decimal tests utils: add operators to big_decimal
This commit is contained in:
@@ -35,13 +35,30 @@ void test_div(const char *r_cstr, const int64_t q, const char *expected_cstr) {
|
||||
BOOST_REQUIRE_EQUAL(res.scale(), expected.scale());
|
||||
}
|
||||
|
||||
void test_assignadd(const char *x_cstr, const char *y_cstr, const char *expected_cstr) {
|
||||
template<typename Op>
|
||||
void test_op(const char* x_cstr, const char* y_cstr, const char* expected_cstr, Op&& op) {
|
||||
big_decimal x{x_cstr};
|
||||
big_decimal y{y_cstr};
|
||||
big_decimal expected{expected_cstr};
|
||||
x += y;
|
||||
BOOST_REQUIRE_EQUAL(x.unscaled_value(), expected.unscaled_value());
|
||||
BOOST_REQUIRE_EQUAL(x.scale(), expected.scale());
|
||||
auto ret = op(x, y);
|
||||
BOOST_REQUIRE_EQUAL(ret.unscaled_value(), expected.unscaled_value());
|
||||
BOOST_REQUIRE_EQUAL(ret.scale(), expected.scale());
|
||||
}
|
||||
|
||||
void test_assignadd(const char *x_cstr, const char *y_cstr, const char *expected_cstr) {
|
||||
return test_op(x_cstr, y_cstr, expected_cstr, [](big_decimal& d1, big_decimal& d2) { return d1 += d2; });
|
||||
}
|
||||
|
||||
void test_add(const char *x_cstr, const char *y_cstr, const char *expected_cstr) {
|
||||
return test_op(x_cstr, y_cstr, expected_cstr, [](big_decimal& d1, big_decimal& d2) { return d1 + d2; });
|
||||
}
|
||||
|
||||
void test_assignsub(const char *x_cstr, const char *y_cstr, const char *expected_cstr) {
|
||||
return test_op(x_cstr, y_cstr, expected_cstr, [](big_decimal& d1, big_decimal& d2) { return d1 -= d2; });
|
||||
}
|
||||
|
||||
void test_sub(const char *x_cstr, const char *y_cstr, const char *expected_cstr) {
|
||||
return test_op(x_cstr, y_cstr, expected_cstr, [](big_decimal& d1, big_decimal& d2) { return d1 - d2; });
|
||||
}
|
||||
|
||||
} /* anonymous namespoce */
|
||||
@@ -128,3 +145,39 @@ BOOST_AUTO_TEST_CASE(test_big_decimal_assignadd) {
|
||||
test_assignadd("1.0", "1.000", "2.000");
|
||||
test_assignadd("-1.0", "-1.000", "-2.000");
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(test_big_decimal_add) {
|
||||
test_add("1", "4", "5");
|
||||
test_add("1.00", "4.00", "5.00");
|
||||
test_add("1.000", "4.000", "5.000");
|
||||
test_add("1", "-1", "0");
|
||||
test_add("1.00", "-1.00", "0.00");
|
||||
test_add("1.000", "-1.000", "0.000");
|
||||
test_add("0.0", "0.000", "0.000");
|
||||
test_add("1.0", "1.000", "2.000");
|
||||
test_add("-1.0", "-1.000", "-2.000");
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(test_big_decimal_assignsub) {
|
||||
test_assignsub("1", "4", "-3");
|
||||
test_assignsub("1.00", "4.00", "-3.00");
|
||||
test_assignsub("1.000", "4.000", "-3.000");
|
||||
test_assignsub("1", "-1", "2");
|
||||
test_assignsub("1.00", "-1.00", "2.00");
|
||||
test_assignsub("1.000", "-1.000", "2.000");
|
||||
test_assignsub("0.0", "0.000", "0.000");
|
||||
test_assignsub("1.0", "1.000", "0.000");
|
||||
test_assignsub("-1.0", "1.000", "-2.000");
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(test_big_decimal_sub) {
|
||||
test_sub("1", "4", "-3");
|
||||
test_sub("1.00", "4.00", "-3.00");
|
||||
test_sub("1.000", "4.000", "-3.000");
|
||||
test_sub("1", "-1", "2");
|
||||
test_sub("1.00", "-1.00", "2.00");
|
||||
test_sub("1.000", "-1.000", "2.000");
|
||||
test_sub("0.0", "0.000", "0.000");
|
||||
test_sub("1.0", "1.000", "0.000");
|
||||
test_sub("-1.0", "1.000", "-2.000");
|
||||
}
|
||||
|
||||
@@ -112,6 +112,32 @@ big_decimal& big_decimal::operator+=(const big_decimal& other)
|
||||
return *this;
|
||||
}
|
||||
|
||||
big_decimal& big_decimal::operator-=(const big_decimal& other) {
|
||||
if (_scale == other._scale) {
|
||||
_unscaled_value -= other._unscaled_value;
|
||||
} else {
|
||||
boost::multiprecision::cpp_int rescale(10);
|
||||
auto max_scale = std::max(_scale, other._scale);
|
||||
boost::multiprecision::cpp_int u = _unscaled_value * boost::multiprecision::pow(rescale, max_scale - _scale);
|
||||
boost::multiprecision::cpp_int v = other._unscaled_value * boost::multiprecision::pow(rescale, max_scale - other._scale);
|
||||
_unscaled_value = u - v;
|
||||
_scale = max_scale;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
big_decimal big_decimal::operator+(const big_decimal& other) const {
|
||||
big_decimal ret(*this);
|
||||
ret += other;
|
||||
return ret;
|
||||
}
|
||||
|
||||
big_decimal big_decimal::operator-(const big_decimal& other) const {
|
||||
big_decimal ret(*this);
|
||||
ret -= other;
|
||||
return ret;
|
||||
}
|
||||
|
||||
big_decimal big_decimal::div(const ::uint64_t y, const rounding_mode mode) const
|
||||
{
|
||||
if (mode != rounding_mode::HALF_EVEN) {
|
||||
|
||||
@@ -34,7 +34,7 @@ public:
|
||||
HALF_EVEN,
|
||||
};
|
||||
|
||||
big_decimal(sstring_view text);
|
||||
explicit big_decimal(sstring_view text);
|
||||
big_decimal() : big_decimal(0, 0) {}
|
||||
big_decimal(int32_t scale, boost::multiprecision::cpp_int unscaled_value)
|
||||
: _scale(scale), _unscaled_value(unscaled_value)
|
||||
@@ -48,6 +48,9 @@ public:
|
||||
int compare(const big_decimal& other) const;
|
||||
|
||||
big_decimal& operator+=(const big_decimal& other);
|
||||
big_decimal& operator-=(const big_decimal& other);
|
||||
big_decimal operator+(const big_decimal& other) const;
|
||||
big_decimal operator-(const big_decimal& other) const;
|
||||
big_decimal div(const ::uint64_t y, const rounding_mode mode) const;
|
||||
friend bool operator<(const big_decimal& x, const big_decimal& y) { return x.compare(y) < 0; }
|
||||
friend bool operator<=(const big_decimal& x, const big_decimal& y) { return x.compare(y) <= 0; }
|
||||
|
||||
Reference in New Issue
Block a user