summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--python/py_amount.cc73
-rw-r--r--python/py_value.cc7
-rw-r--r--src/amount.cc584
-rw-r--r--src/amount.h53
-rw-r--r--src/balance.h29
-rw-r--r--src/commodity.cc4
-rw-r--r--src/entry.cc2
-rw-r--r--src/filters.cc12
-rw-r--r--src/gnucash.cc6
-rw-r--r--src/value.cc38
-rw-r--r--src/value.h8
-rw-r--r--test/unit/t_amount.cc219
-rw-r--r--test/unit/t_amount.h5
-rw-r--r--test/unit/t_commodity.cc13
14 files changed, 159 insertions, 894 deletions
diff --git a/python/py_amount.cc b/python/py_amount.cc
index b57687f2..2528f779 100644
--- a/python/py_amount.cc
+++ b/python/py_amount.cc
@@ -41,29 +41,6 @@ namespace ledger {
using namespace boost::python;
-#ifdef INTEGER_MATH
-amount_t py_round_0(const amount_t& amount) {
- return amount.round();
-}
-amount_t py_round_1(const amount_t& amount, amount_t::precision_t prec) {
- return amount.round(prec);
-}
-#endif
-
-double py_to_double_0(amount_t& amount) {
- return amount.to_double();
-}
-double py_to_double_1(amount_t& amount, bool no_check) {
- return amount.to_double(no_check);
-}
-
-long py_to_long_0(amount_t& amount) {
- return amount.to_long();
-}
-long py_to_long_1(amount_t& amount, bool no_check) {
- return amount.to_long(no_check);
-}
-
boost::optional<amount_t> py_value_0(const amount_t& amount) {
return amount.value();
}
@@ -169,7 +146,9 @@ void export_amount()
make_getter(&amount_t::stream_fullstrings),
make_setter(&amount_t::stream_fullstrings))
+#if 0
.def(init<double>())
+#endif
.def(init<long>())
.def(init<std::string>())
@@ -185,80 +164,108 @@ internal precision.")
.def(self == self)
.def(self == long())
.def(long() == self)
+#if 0
.def(self == double())
.def(double() == self)
+#endif
.def(self != self)
.def(self != long())
.def(long() != self)
+#if 0
.def(self != double())
.def(double() != self)
+#endif
.def(! self)
.def(self < self)
.def(self < long())
.def(long() < self)
+#if 0
.def(self < double())
.def(double() < self)
+#endif
.def(self <= self)
.def(self <= long())
.def(long() <= self)
+#if 0
.def(self <= double())
.def(double() <= self)
+#endif
.def(self > self)
.def(self > long())
.def(long() > self)
+#if 0
.def(self > double())
.def(double() > self)
+#endif
.def(self >= self)
.def(self >= long())
.def(long() >= self)
+#if 0
.def(self >= double())
.def(double() >= self)
+#endif
.def(self += self)
.def(self += long())
+#if 0
.def(self += double())
+#endif
.def(self + self)
.def(self + long())
.def(long() + self)
+#if 0
.def(self + double())
.def(double() + self)
+#endif
.def(self -= self)
.def(self -= long())
+#if 0
.def(self -= double())
+#endif
.def(self - self)
.def(self - long())
.def(long() - self)
+#if 0
.def(self - double())
.def(double() - self)
+#endif
.def(self *= self)
.def(self *= long())
+#if 0
.def(self *= double())
+#endif
.def(self * self)
.def(self * long())
.def(long() * self)
+#if 0
.def(self * double())
.def(double() * self)
+#endif
.def(self /= self)
.def(self /= long())
+#if 0
.def(self /= double())
+#endif
.def(self / self)
.def(self / long())
.def(long() / self)
+#if 0
.def(self / double())
.def(double() / self)
+#endif
.def("precision", &amount_t::precision)
@@ -270,11 +277,8 @@ internal precision.")
.def("abs", &amount_t::abs)
.def("__abs__", &amount_t::abs)
-#ifdef INTEGER_MATH
- .def("round", py_round_0)
- .def("round", py_round_1)
-#endif
- .def("unround", &amount_t::unround)
+ .def("rounded", &amount_t::rounded)
+ .def("unrounded", &amount_t::unrounded)
.def("reduce", &amount_t::reduce)
.def("in_place_reduce", &amount_t::in_place_reduce,
@@ -295,18 +299,15 @@ internal precision.")
.def("is_realzero", &amount_t::is_realzero)
.def("is_null", &amount_t::is_null)
- .def("to_double", py_to_double_0)
- .def("to_double", py_to_double_1)
- .def("__float__", py_to_double_0)
- .def("to_long", py_to_long_0)
- .def("to_long", py_to_long_1)
- .def("__int__", py_to_long_0)
+ .def("to_double", &amount_t::to_double)
+ .def("__float__", &amount_t::to_double)
+ .def("to_long", &amount_t::to_long)
+ .def("__int__", &amount_t::to_long)
.def("to_string", &amount_t::to_string)
.def("__str__", &amount_t::to_string)
.def("to_fullstring", &amount_t::to_fullstring)
.def("__repr__", &amount_t::to_fullstring)
- .def("fits_in_double", &amount_t::fits_in_double)
.def("fits_in_long", &amount_t::fits_in_long)
.def("quantity_string", &amount_t::quantity_string)
@@ -359,7 +360,9 @@ internal precision.")
register_optional_to_python<amount_t>();
+#if 0
implicitly_convertible<double, amount_t>();
+#endif
implicitly_convertible<long, amount_t>();
implicitly_convertible<string, amount_t>();
diff --git a/python/py_value.cc b/python/py_value.cc
index 48cd0feb..4556c31e 100644
--- a/python/py_value.cc
+++ b/python/py_value.cc
@@ -195,11 +195,8 @@ void export_value()
.def("abs", &value_t::abs)
.def("__abs__", &value_t::abs)
-#ifdef INTEGER_MATH
- .def("round", &value_t::round)
- .def("in_place_round", &value_t::in_place_round)
-#endif
- .def("unround", &value_t::unround)
+ .def("rounded", &value_t::rounded)
+ .def("unrounded", &value_t::unrounded)
.def("reduce", &value_t::reduce)
.def("in_place_reduce", &value_t::in_place_reduce)
diff --git a/src/amount.cc b/src/amount.cc
index bc7d5a6a..ae61495c 100644
--- a/src/amount.cc
+++ b/src/amount.cc
@@ -47,26 +47,18 @@ bool amount_t::stream_fullstrings = false;
#if !defined(THREADSAFE)
// These global temporaries are pre-initialized for the sake of
// efficiency, and are reused over and over again.
-static mpz_t temp;
+static mpz_t temp;
+static mpq_t tempq;
static mpfr_t tempf;
-#ifdef INTEGER_MATH
-static mpz_t divisor;
-#else
-static mpq_t tempq;
static mpfr_t tempfb;
#endif
-#endif
struct amount_t::bigint_t : public supports_flags<>
{
#define BIGINT_BULK_ALLOC 0x01
#define BIGINT_KEEP_PREC 0x02
-#ifdef INTEGER_MATH
- mpz_t val;
-#else
mpq_t val;
-#endif
precision_t prec;
uint_least16_t ref;
uint_fast32_t index;
@@ -75,31 +67,19 @@ struct amount_t::bigint_t : public supports_flags<>
bigint_t() : prec(0), ref(1), index(0) {
TRACE_CTOR(bigint_t, "");
-#ifdef INTEGER_MATH
- mpz_init(val);
-#else
mpq_init(val);
-#endif
}
bigint_t(const bigint_t& other)
: supports_flags<>(other.flags() & ~BIGINT_BULK_ALLOC),
prec(other.prec), ref(1), index(0) {
TRACE_CTOR(bigint_t, "copy");
-#ifdef INTEGER_MATH
- mpz_init_set(val, other.val);
-#else
mpq_init(val);
mpq_set(val, other.val);
-#endif
}
~bigint_t() {
TRACE_DTOR(bigint_t);
assert(ref == 0);
-#ifdef INTEGER_MATH
- mpz_clear(val);
-#else
mpq_clear(val);
-#endif
}
bool valid() const {
@@ -125,15 +105,11 @@ amount_t * one = NULL;
void amount_t::initialize()
{
mpz_init(temp);
- mpfr_init(tempf);
-#ifdef INTEGER_MATH
- mpz_init(divisor);
-#else
mpq_init(tempq);
+ mpfr_init(tempf);
mpfr_init(tempfb);
-#endif
- one = new amount_t(amount_t(1L).unround());
+ one = new amount_t(amount_t(1L).unrounded());
if (! current_pool)
current_pool = new commodity_pool_t;
@@ -153,13 +129,9 @@ void amount_t::initialize()
void amount_t::shutdown()
{
mpz_clear(temp);
- mpfr_clear(tempf);
-#ifdef INTEGER_MATH
- mpz_clear(divisor);
-#else
mpq_clear(tempq);
+ mpfr_clear(tempf);
mpfr_clear(tempfb);
-#endif
checked_delete(one);
@@ -206,28 +178,6 @@ void amount_t::_dup()
assert(valid());
}
-#ifdef INTEGER_MATH
-
-void amount_t::_resize(precision_t prec)
-{
- assert(prec < 256);
-
- if (! quantity || prec == quantity->prec)
- return;
-
- _dup();
-
- assert(prec > quantity->prec);
- mpz_ui_pow_ui(divisor, 10, prec - quantity->prec);
- mpz_mul(MP(quantity), MP(quantity), divisor);
-
- quantity->prec = prec;
-
- assert(valid());
-}
-
-#endif // INTEGER_MATH
-
void amount_t::_clear()
{
if (quantity) {
@@ -262,12 +212,7 @@ amount_t::amount_t(const double val) : commodity_(NULL)
{
TRACE_CTOR(amount_t, "const double");
quantity = new bigint_t;
-#ifdef INTEGER_MATH
- mpfr_set_d(tempf, val, GMP_RNDN);
- mpfr_get_z(MP(quantity), tempf);
-#else
mpq_set_d(MP(quantity), val);
-#endif
quantity->prec = extend_by_digits; // an approximation
}
@@ -275,22 +220,14 @@ amount_t::amount_t(const unsigned long val) : commodity_(NULL)
{
TRACE_CTOR(amount_t, "const unsigned long");
quantity = new bigint_t;
-#ifdef INTEGER_MATH
- mpz_set_ui(MP(quantity), val);
-#else
mpq_set_ui(MP(quantity), val, 1);
-#endif
}
amount_t::amount_t(const long val) : commodity_(NULL)
{
TRACE_CTOR(amount_t, "const long");
quantity = new bigint_t;
-#ifdef INTEGER_MATH
- mpz_set_si(MP(quantity), val);
-#else
mpq_set_si(MP(quantity), val, 1);
-#endif
}
@@ -325,23 +262,7 @@ int amount_t::compare(const amount_t& amt) const
"Cannot compare amounts with different commodities: " <<
commodity().symbol() << " and " << amt.commodity().symbol());
-#ifdef INTEGER_MATH
- if (quantity->prec == amt.quantity->prec) {
- return mpz_cmp(MP(quantity), MP(amt.quantity));
- }
- else if (quantity->prec < amt.quantity->prec) {
- amount_t t(*this);
- t._resize(amt.quantity->prec);
- return mpz_cmp(MP(t.quantity), MP(amt.quantity));
- }
- else {
- amount_t t = amt;
- t._resize(quantity->prec);
- return mpz_cmp(MP(quantity), MP(t.quantity));
- }
-#else
return mpq_cmp(MP(quantity), MP(amt.quantity));
-#endif
}
@@ -367,25 +288,10 @@ amount_t& amount_t::operator+=(const amount_t& amt)
_dup();
-#ifdef INTEGER_MATH
- if (quantity->prec == amt.quantity->prec) {
- mpz_add(MP(quantity), MP(quantity), MP(amt.quantity));
- }
- else if (quantity->prec < amt.quantity->prec) {
- _resize(amt.quantity->prec);
- mpz_add(MP(quantity), MP(quantity), MP(amt.quantity));
- }
- else {
- amount_t t = amt;
- t._resize(quantity->prec);
- mpz_add(MP(quantity), MP(quantity), MP(t.quantity));
- }
-#else
mpq_add(MP(quantity), MP(quantity), MP(amt.quantity));
if (quantity->prec < amt.quantity->prec)
quantity->prec = amt.quantity->prec;
-#endif
return *this;
}
@@ -412,81 +318,14 @@ amount_t& amount_t::operator-=(const amount_t& amt)
_dup();
-#ifdef INTEGER_MATH
- if (quantity->prec == amt.quantity->prec) {
- mpz_sub(MP(quantity), MP(quantity), MP(amt.quantity));
- }
- else if (quantity->prec < amt.quantity->prec) {
- _resize(amt.quantity->prec);
- mpz_sub(MP(quantity), MP(quantity), MP(amt.quantity));
- }
- else {
- amount_t t = amt;
- t._resize(quantity->prec);
- mpz_sub(MP(quantity), MP(quantity), MP(t.quantity));
- }
-#else
mpq_sub(MP(quantity), MP(quantity), MP(amt.quantity));
if (quantity->prec < amt.quantity->prec)
quantity->prec = amt.quantity->prec;
-#endif
return *this;
}
-#ifdef INTEGER_MATH
-
-namespace {
- void mpz_round(mpz_t out, mpz_t value, int value_prec, int round_prec)
- {
- // Round `value', with an encoding precision of `value_prec', to a
- // rounded value with precision `round_prec'. Result is stored in
- // `out'.
-
- assert(value_prec > round_prec);
-
- mpz_t quotient;
- mpz_t remainder;
-
- mpz_init(quotient);
- mpz_init(remainder);
-
- mpz_ui_pow_ui(divisor, 10, value_prec - round_prec);
- mpz_tdiv_qr(quotient, remainder, value, divisor);
- mpz_divexact_ui(divisor, divisor, 10);
- mpz_mul_ui(divisor, divisor, 5);
-
- if (mpz_sgn(remainder) < 0) {
- mpz_neg(divisor, divisor);
- if (mpz_cmp(remainder, divisor) < 0) {
- mpz_ui_pow_ui(divisor, 10, value_prec - round_prec);
- mpz_add(remainder, divisor, remainder);
- mpz_ui_sub(remainder, 0, remainder);
- mpz_add(out, value, remainder);
- } else {
- mpz_sub(out, value, remainder);
- }
- } else {
- if (mpz_cmp(remainder, divisor) >= 0) {
- mpz_ui_pow_ui(divisor, 10, value_prec - round_prec);
- mpz_sub(remainder, divisor, remainder);
- mpz_add(out, value, remainder);
- } else {
- mpz_sub(out, value, remainder);
- }
- }
- mpz_clear(quotient);
- mpz_clear(remainder);
-
- // chop off the rounded bits
- mpz_ui_pow_ui(divisor, 10, value_prec - round_prec);
- mpz_tdiv_q(out, out, divisor);
- }
-}
-
-#endif // INTEGER_MATH
-
amount_t& amount_t::operator*=(const amount_t& amt)
{
assert(amt.valid());
@@ -502,11 +341,7 @@ amount_t& amount_t::operator*=(const amount_t& amt)
_dup();
-#ifdef INTEGER_MATH
- mpz_mul(MP(quantity), MP(quantity), MP(amt.quantity));
-#else
mpq_mul(MP(quantity), MP(quantity), MP(amt.quantity));
-#endif
quantity->prec += amt.quantity->prec;
if (! has_commodity())
@@ -514,13 +349,8 @@ amount_t& amount_t::operator*=(const amount_t& amt)
if (has_commodity() && ! keep_precision()) {
precision_t comm_prec = commodity().precision();
- if (quantity->prec > comm_prec + extend_by_digits) {
-#ifdef INTEGER_MATH
- mpz_round(MP(quantity), MP(quantity), quantity->prec,
- comm_prec + extend_by_digits);
-#endif // INTEGER_MATH
+ if (quantity->prec > comm_prec + extend_by_digits)
quantity->prec = comm_prec + extend_by_digits;
- }
}
return *this;
@@ -547,19 +377,8 @@ amount_t& amount_t::operator/=(const amount_t& amt)
// Increase the value's precision, to capture fractional parts after
// the divide. Round up in the last position.
-#ifdef INTEGER_MATH
- mpz_ui_pow_ui(divisor, 10, (2 * amt.quantity->prec) + quantity->prec +
- extend_by_digits + 1U);
- mpz_mul(MP(quantity), MP(quantity), divisor);
- mpz_tdiv_q(MP(quantity), MP(quantity), MP(amt.quantity));
- quantity->prec += amt.quantity->prec + quantity->prec + extend_by_digits + 1U;
-
- mpz_round(MP(quantity), MP(quantity), quantity->prec, quantity->prec - 1);
- quantity->prec -= 1;
-#else
mpq_div(MP(quantity), MP(quantity), MP(amt.quantity));
quantity->prec += amt.quantity->prec + quantity->prec + extend_by_digits;
-#endif
if (! has_commodity())
commodity_ = amt.commodity_;
@@ -571,13 +390,8 @@ amount_t& amount_t::operator/=(const amount_t& amt)
if (has_commodity() && ! keep_precision()) {
precision_t comm_prec = commodity().precision();
- if (quantity->prec > comm_prec + extend_by_digits) {
-#ifdef INTEGER_MATH
- mpz_round(MP(quantity), MP(quantity), quantity->prec,
- comm_prec + extend_by_digits);
-#endif // INTEGER_MATH
+ if (quantity->prec > comm_prec + extend_by_digits)
quantity->prec = comm_prec + extend_by_digits;
- }
}
return *this;
@@ -634,59 +448,28 @@ amount_t& amount_t::in_place_negate()
{
if (quantity) {
_dup();
-#ifdef INTEGER_MATH
- mpz_neg(MP(quantity), MP(quantity));
-#else
mpq_neg(MP(quantity), MP(quantity));
-#endif
} else {
throw_(amount_error, "Cannot negate an uninitialized amount");
}
return *this;
}
-#ifdef INTEGER_MATH
-
-amount_t& amount_t::in_place_round()
-{
- if (! quantity)
- throw_(amount_error, "Cannot round an uninitialized amount");
-
- if (has_commodity())
- in_place_round(commodity().precision());
-
- return *this;
-}
-
-amount_t& amount_t::in_place_round(precision_t prec)
+amount_t amount_t::rounded() const
{
if (! quantity)
- throw_(amount_error, "Cannot round an uninitialized amount");
-
- if (quantity && quantity->prec <= prec) {
- if (keep_precision()) {
- _dup();
- set_keep_precision(false);
- }
+ throw_(amount_error, "Cannot set rounding for an uninitialized amount");
+ else if (! keep_precision())
return *this;
- }
-
- DEBUG("amount.round", "Rounding " << *this << " to precision " << prec);
-
- _dup();
- mpz_round(MP(quantity), MP(quantity), quantity->prec, prec);
-
- quantity->prec = prec;
- set_keep_precision(false);
- DEBUG("amount.round", " result = " << *this);
+ amount_t t(*this);
+ t._dup();
+ t.set_keep_precision(false);
- return *this;
+ return t;
}
-#endif // INTEGER_MATH
-
-amount_t amount_t::unround() const
+amount_t amount_t::unrounded() const
{
if (! quantity)
throw_(amount_error, "Cannot unround an uninitialized amount");
@@ -732,11 +515,7 @@ optional<amount_t> amount_t::value(const optional<datetime_t>& moment,
if (quantity) {
optional<price_point_t> point(commodity().find_price(in_terms_of, moment));
if (point)
-#ifdef INTEGER_MATH
- return (point->price * number()).round();
-#else
- return point->price * number();
-#endif
+ return (point->price * number()).rounded();
} else {
throw_(amount_error, "Cannot determine value of an uninitialized amount");
}
@@ -749,15 +528,9 @@ int amount_t::sign() const
if (! quantity)
throw_(amount_error, "Cannot determine sign of an uninitialized amount");
-#ifdef INTEGER_MATH
- return mpz_sgn(MP(quantity));
-#else
return mpq_sgn(MP(quantity));
-#endif
}
-#ifndef INTEGER_MATH
-
namespace {
void stream_out_mpq(std::ostream& out, mpq_t quant,
amount_t::precision_t prec,
@@ -826,8 +599,6 @@ namespace {
}
}
-#endif // INTEGER_MATH
-
bool amount_t::is_zero() const
{
if (! quantity)
@@ -837,9 +608,6 @@ bool amount_t::is_zero() const
if (keep_precision() || quantity->prec <= commodity().precision()) {
return is_realzero();
} else {
-#ifdef INTEGER_MATH
- return round(commodity().precision()).sign() == 0;
-#else
std::ostringstream out;
stream_out_mpq(out, MP(quantity), commodity().precision());
@@ -847,80 +615,34 @@ bool amount_t::is_zero() const
if (*p != '0' && *p != '.')
return false;
return true;
-#endif
}
}
return is_realzero();
}
-double amount_t::to_double(bool no_check) const
+double amount_t::to_double() const
{
if (! quantity)
throw_(amount_error, "Cannot convert an uninitialized amount to a double");
-#ifdef INTEGER_MATH
- mpz_t remainder;
- mpz_init(remainder);
-
- mpz_set(temp, MP(quantity));
- mpz_ui_pow_ui(divisor, 10, quantity->prec);
- mpz_tdiv_qr(temp, remainder, temp, divisor);
-
- char * quotient_s = mpz_get_str(NULL, 10, temp);
- char * remainder_s = mpz_get_str(NULL, 10, remainder);
-
- std::ostringstream num;
- num << quotient_s << '.' << remainder_s;
-
- std::free(quotient_s);
- std::free(remainder_s);
-
- mpz_clear(remainder);
-
- double value = lexical_cast<double>(num.str());
-#else
mpfr_set_q(tempf, MP(quantity), GMP_RNDN);
- double value = mpfr_get_d(tempf, GMP_RNDN);
-#endif
-
- if (! no_check && *this != value)
- throw_(amount_error, "Conversion of amount to_double loses precision");
-
- return value;
+ return mpfr_get_d(tempf, GMP_RNDN);
}
-long amount_t::to_long(bool no_check) const
+long amount_t::to_long() const
{
if (! quantity)
throw_(amount_error, "Cannot convert an uninitialized amount to a long");
-#ifdef INTEGER_MATH
- mpz_set(temp, MP(quantity));
- mpz_ui_pow_ui(divisor, 10, quantity->prec);
- mpz_tdiv_q(temp, temp, divisor);
- long value = mpz_get_si(temp);
-#else
mpfr_set_q(tempf, MP(quantity), GMP_RNDN);
- long value = mpfr_get_si(tempf, GMP_RNDN);
-#endif
-
- if (! no_check && *this != value)
- throw_(amount_error, "Conversion of amount to_long loses precision");
-
- return value;
-}
-
-bool amount_t::fits_in_double() const
-{
- double value = to_double(true);
- return *this == amount_t(value);
+ return mpfr_get_si(tempf, GMP_RNDN);
}
bool amount_t::fits_in_long() const
{
- long value = to_long(true);
- return *this == amount_t(value);
+ mpfr_set_q(tempf, MP(quantity), GMP_RNDN);
+ return mpfr_fits_slong_p(tempf, GMP_RNDN);
}
@@ -1170,9 +892,6 @@ bool amount_t::parse(std::istream& in, const parse_flags_t& flags)
}
*t = '\0';
-#ifdef INTEGER_MATH
- mpz_set_str(MP(quantity), buf.get(), 10);
-#else
mpq_set_str(MP(quantity), buf.get(), 10);
mpz_ui_pow_ui(temp, 10, quantity->prec);
mpq_set_z(tempq, temp);
@@ -1183,13 +902,8 @@ bool amount_t::parse(std::istream& in, const parse_flags_t& flags)
DEBUG("amount.parse", "Rational parsed = " << buf);
std::free(buf);
}
-#endif
} else {
-#ifdef INTEGER_MATH
- mpz_set_str(MP(quantity), quant.c_str(), 10);
-#else
mpq_set_str(MP(quantity), quant.c_str(), 10);
-#endif
}
if (negative)
@@ -1243,156 +957,6 @@ void amount_t::print(std::ostream& _out, bool omit_commodity,
commodity_t& comm(base.commodity());
precision_t precision = 0;
-#ifdef INTEGER_MATH
-
- mpz_t quotient;
- mpz_t rquotient;
- mpz_t remainder;
-
- mpz_init(quotient);
- mpz_init(rquotient);
- mpz_init(remainder);
-
- bool negative = false;
-
- // Ensure the value is rounded to the commodity's precision before
- // outputting it. NOTE: `rquotient' is used here as a temp variable!
-
- if (quantity) {
- if (! comm || full_precision || base.keep_precision()) {
- mpz_ui_pow_ui(divisor, 10, base.quantity->prec);
- mpz_tdiv_qr(quotient, remainder, MP(base.quantity), divisor);
- precision = base.quantity->prec;
- }
- else if (comm.precision() < base.quantity->prec) {
- mpz_round(rquotient, MP(base.quantity), base.quantity->prec,
- comm.precision());
- mpz_ui_pow_ui(divisor, 10, comm.precision());
- mpz_tdiv_qr(quotient, remainder, rquotient, divisor);
- precision = comm.precision();
- }
- else if (comm.precision() > base.quantity->prec) {
- mpz_ui_pow_ui(divisor, 10, comm.precision() - base.quantity->prec);
- mpz_mul(rquotient, MP(base.quantity), divisor);
- mpz_ui_pow_ui(divisor, 10, comm.precision());
- mpz_tdiv_qr(quotient, remainder, rquotient, divisor);
- precision = comm.precision();
- }
- else if (base.quantity->prec) {
- mpz_ui_pow_ui(divisor, 10, base.quantity->prec);
- mpz_tdiv_qr(quotient, remainder, MP(base.quantity), divisor);
- precision = base.quantity->prec;
- }
- else {
- mpz_set(quotient, MP(base.quantity));
- mpz_set_ui(remainder, 0);
- precision = 0;
- }
-
- if (mpz_sgn(quotient) < 0 || mpz_sgn(remainder) < 0) {
- negative = true;
-
- mpz_abs(quotient, quotient);
- mpz_abs(remainder, remainder);
- }
- mpz_set(rquotient, remainder);
- }
-
- if (! omit_commodity && ! comm.has_flags(COMMODITY_STYLE_SUFFIXED)) {
- comm.print(out);
- if (comm.has_flags(COMMODITY_STYLE_SEPARATED))
- out << " ";
- }
-
- if (negative)
- out << "-";
-
- if (! quantity || mpz_sgn(quotient) == 0) {
- out << '0';
- }
- else if (omit_commodity || ! comm.has_flags(COMMODITY_STYLE_THOUSANDS)) {
- char * p = mpz_get_str(NULL, 10, quotient);
- out << p;
- std::free(p);
- }
- else {
- std::list<string> strs;
- char buf[4];
-
- for (int powers = 0; true; powers += 3) {
- if (powers > 0) {
- mpz_ui_pow_ui(divisor, 10, powers);
- mpz_tdiv_q(temp, quotient, divisor);
- if (mpz_sgn(temp) == 0)
- break;
- mpz_tdiv_r_ui(temp, temp, 1000);
- } else {
- mpz_tdiv_r_ui(temp, quotient, 1000);
- }
- mpz_get_str(buf, 10, temp);
- strs.push_back(buf);
- }
-
- bool printed = false;
-
- for (std::list<string>::reverse_iterator i = strs.rbegin();
- i != strs.rend();
- i++) {
- if (printed) {
- out << (comm.has_flags(COMMODITY_STYLE_EUROPEAN) ? '.' : ',');
- out.width(3);
- out.fill('0');
- }
- out << *i;
-
- printed = true;
- }
- }
-
- if (quantity && precision) {
- std::ostringstream final;
- final.width(precision);
- final.fill('0');
- char * p = mpz_get_str(NULL, 10, rquotient);
- final << p;
- std::free(p);
-
- const string& str(final.str());
- int i, len = str.length();
- const char * q = str.c_str();
- for (i = len; i > 0; i--)
- if (q[i - 1] != '0')
- break;
-
- string ender;
- if (i == len)
- ender = str;
- else if (i < comm.precision())
- ender = string(str, 0, comm.precision());
- else
- ender = string(str, 0, i);
-
- if (! ender.empty()) {
- if (omit_commodity)
- out << '.';
- else
- out << (comm.has_flags(COMMODITY_STYLE_EUROPEAN) ? ',' : '.');
- out << ender;
- }
- }
-
- if (! omit_commodity && comm.has_flags(COMMODITY_STYLE_SUFFIXED)) {
- if (comm.has_flags(COMMODITY_STYLE_SEPARATED))
- out << " ";
- comm.print(out);
- }
-
- mpz_clear(quotient);
- mpz_clear(rquotient);
- mpz_clear(remainder);
-
-#else // INTEGER_MATH
-
if (! omit_commodity && ! comm.has_flags(COMMODITY_STYLE_SUFFIXED)) {
comm.print(out);
if (comm.has_flags(COMMODITY_STYLE_SEPARATED))
@@ -1408,8 +972,6 @@ void amount_t::print(std::ostream& _out, bool omit_commodity,
comm.print(out);
}
-#endif // INTEGER_MATH
-
// If there are any annotations associated with this commodity,
// output them now.
@@ -1451,43 +1013,27 @@ void amount_t::read(std::istream& in)
if (byte < 3) {
quantity = new bigint_t;
-#ifndef INTEGER_MATH
- mpz_t numerator;
- mpz_t denominator;
-#endif
-
unsigned short len;
in.read(reinterpret_cast<char *>(&len), sizeof(len));
assert(len < 4096);
static char buf[4096];
in.read(buf, len);
-#ifdef INTEGER_MATH
- mpz_import(MP(quantity), len / sizeof(short), 1, sizeof(short),
- 0, 0, buf);
-#else
- mpz_init(numerator);
- mpz_import(numerator, len / sizeof(short), 1, sizeof(short),
+
+ mpz_import(temp, len / sizeof(short), 1, sizeof(short),
0, 0, buf);
+ mpq_set_num(MP(quantity), temp);
in.read(reinterpret_cast<char *>(&len), sizeof(len));
assert(len < 4096);
in.read(buf, len);
- mpz_init(denominator);
- mpz_import(denominator, len / sizeof(short), 1, sizeof(short),
+ mpz_import(temp, len / sizeof(short), 1, sizeof(short),
0, 0, buf);
-
- mpq_set_num(MP(quantity), numerator);
- mpq_set_den(MP(quantity), denominator);
-#endif
+ mpq_set_den(MP(quantity), temp);
char negative;
in.read(&negative, sizeof(negative));
if (negative)
-#ifdef INTEGER_MATH
- mpz_neg(MP(quantity), MP(quantity));
-#else
mpq_neg(MP(quantity), MP(quantity));
-#endif
in.read(reinterpret_cast<char *>(&quantity->prec), sizeof(quantity->prec));
@@ -1531,40 +1077,28 @@ void amount_t::read(const char *& data,
quantity = new bigint_t;
}
-#ifndef INTEGER_MATH
- mpz_t numerator;
- mpz_t denominator;
-#endif
-
unsigned short len =
*reinterpret_cast<unsigned short *>(const_cast<char *>(data));
data += sizeof(unsigned short);
-#ifdef INTEGER_MATH
- mpz_import(MP(quantity), len / sizeof(short), 1, sizeof(short),
- 0, 0, data);
-#else
- mpz_init(numerator);
- mpz_import(numerator, len / sizeof(short), 1, sizeof(short),
+ mpz_init(temp);
+ mpz_import(temp, len / sizeof(short), 1, sizeof(short),
0, 0, data);
+ data += len;
+
+ mpq_set_num(MP(quantity), temp);
len = *reinterpret_cast<unsigned short *>(const_cast<char *>(data));
data += sizeof(unsigned short);
- mpz_init(denominator);
- mpz_import(denominator, len / sizeof(short), 1, sizeof(short),
+ mpz_init(temp);
+ mpz_import(temp, len / sizeof(short), 1, sizeof(short),
0, 0, data);
-
- mpq_set_num(MP(quantity), numerator);
- mpq_set_den(MP(quantity), denominator);
-#endif
data += len;
+ mpq_set_den(MP(quantity), temp);
+
char negative = *data++;
if (negative)
-#ifdef INTEGER_MATH
- mpz_neg(MP(quantity), MP(quantity));
-#else
mpq_neg(MP(quantity), MP(quantity));
-#endif
quantity->prec = *reinterpret_cast<precision_t *>(const_cast<char *>(data));
data += sizeof(precision_t);
@@ -1585,6 +1119,20 @@ void amount_t::read(const char *& data,
}
}
+namespace {
+ void write_bytes(std::ostream& out,
+ const char * buf,
+ const std::size_t size)
+ {
+ unsigned short len = size * sizeof(short);
+ out.write(reinterpret_cast<char *>(&len), sizeof(len));
+ if (len) {
+ assert(len < 4096);
+ out.write(buf, len);
+ }
+ }
+}
+
void amount_t::write(std::ostream& out, std::size_t index) const
{
using namespace ledger::binary;
@@ -1614,32 +1162,16 @@ void amount_t::write(std::ostream& out, std::size_t index) const
std::size_t size;
static char buf[4096];
-#ifdef INTEGER_MATH
- mpz_export(buf, &size, 1, sizeof(short), 0, 0, MP(quantity));
-#else
- mpz_t numerator;
- mpz_t denominator;
-
- mpz_init(numerator);
- mpq_get_num(numerator, MP(quantity));
- mpz_export(buf, &size, 1, sizeof(short), 0, 0, numerator);
-
- mpz_init(denominator);
- mpq_get_den(denominator, MP(quantity));
- mpz_export(buf, &size, 1, sizeof(short), 0, 0, denominator);
-#endif
- unsigned short len = size * sizeof(short);
- out.write(reinterpret_cast<char *>(&len), sizeof(len));
- if (len) {
- assert(len < 4096);
- out.write(buf, len);
- }
-#ifdef INTEGER_MATH
- byte = mpz_sgn(MP(quantity)) < 0 ? 1 : 0;
-#else
+ mpq_get_num(temp, MP(quantity));
+ mpz_export(buf, &size, 1, sizeof(short), 0, 0, temp);
+ write_bytes(out, buf, size);
+
+ mpq_get_den(temp, MP(quantity));
+ mpz_export(buf, &size, 1, sizeof(short), 0, 0, temp);
+ write_bytes(out, buf, size);
+
byte = mpq_sgn(MP(quantity)) < 0 ? 1 : 0;
-#endif
out.write(&byte, sizeof(byte));
out.write(reinterpret_cast<char *>(&quantity->prec), sizeof(quantity->prec));
diff --git a/src/amount.h b/src/amount.h
index d15a0205..7e4f832c 100644
--- a/src/amount.h
+++ b/src/amount.h
@@ -57,11 +57,6 @@
namespace ledger {
-// If defined, amount.cc uses GMP integers rather than rationals.
-// Ledger 3.0 uses rationals, but 2.6 and before used integers, so this
-// provides a quick way of testing against past numerical behavior.
-//#define INTEGER_MATH 1
-
class commodity_t;
class annotation_t;
class commodity_pool_t;
@@ -147,9 +142,6 @@ public:
protected:
void _copy(const amount_t& amt);
void _dup();
-#ifdef INTEGER_MATH
- void _resize(precision_t prec);
-#endif
void _clear();
void _release();
@@ -354,33 +346,16 @@ public:
return *this;
}
-#ifdef INTEGER_MATH
-
- /** An amount's internal value to the given precision, or to the
- commodity's current display precision if no precision value is
- given. This method changes the internal value of the amount, if
- it's internal precision was greater than the rounding precision.
- */
- amount_t round() const {
- amount_t temp(*this);
- temp.in_place_round();
- return temp;
- }
- amount_t& in_place_round();
-
- amount_t round(precision_t prec) const {
- amount_t temp(*this);
- temp.in_place_round(prec);
- return temp;
- }
- amount_t& in_place_round(precision_t prec);
-
-#endif // INTEGER_MATH
+ /** Yields an amount whose display precision when output is truncated
+ to the display precision of its commodity. This is normally the
+ default state of an amount, but if one has become unrounded, this
+ sets the "keep precision" state back to false.
+ @see set_keep_precision */
+ amount_t rounded() const;
/** Yields an amount whose display precision is never truncated, even
- though its commodity normally displays only rounded values.
- */
- amount_t unround() const;
+ though its commodity normally displays only rounded values. */
+ amount_t unrounded() const;
/** reduces a value to its most basic commodity form, for amounts that
utilize "scaling commodities". For example, an amount of \c 1h
@@ -487,9 +462,6 @@ public:
optional boolean argument is true (the default), an exception is
thrown if the conversion would lose information.
- fits_in_double() returns true if to_double() would not lose
- precision.
-
fits_in_long() returns true if to_long() would not lose
precision.
@@ -506,15 +478,14 @@ public:
been stripped and the full, internal precision of the amount
would be displayed.
*/
- double to_double(bool no_check = false) const;
- long to_long(bool no_check = false) const;
+ double to_double() const;
+ long to_long() const;
+ bool fits_in_long() const;
+
string to_string() const;
string to_fullstring() const;
string quantity_string() const;
- bool fits_in_double() const;
- bool fits_in_long() const;
-
/*@}*/
/** @name Commodity methods
diff --git a/src/balance.h b/src/balance.h
index eec86576..d1e4301b 100644
--- a/src/balance.h
+++ b/src/balance.h
@@ -311,38 +311,17 @@ public:
return temp;
}
-#ifdef INTEGER_MATH
-
- balance_t round() const {
+ balance_t rounded() const {
balance_t temp;
foreach (const amounts_map::value_type& pair, amounts)
- temp += pair.second.round();
+ temp += pair.second.rounded();
return temp;
}
- balance_t& in_place_round() {
- foreach (amounts_map::value_type& pair, amounts)
- pair.second.in_place_round();
- return *this;
- }
-
- balance_t round(amount_t::precision_t prec) const {
- balance_t temp;
- foreach (const amounts_map::value_type& pair, amounts)
- temp += pair.second.round(prec);
- return temp;
- }
- balance_t& in_place_round(amount_t::precision_t prec) {
- foreach (amounts_map::value_type& pair, amounts)
- pair.second.in_place_round(prec);
- return *this;
- }
-
-#endif // INTEGER_MATH
- balance_t unround() const {
+ balance_t unrounded() const {
balance_t temp;
foreach (const amounts_map::value_type& pair, amounts)
- temp += pair.second.unround();
+ temp += pair.second.unrounded();
return temp;
}
diff --git a/src/commodity.cc b/src/commodity.cc
index 0a751941..1157f3e7 100644
--- a/src/commodity.cc
+++ b/src/commodity.cc
@@ -657,15 +657,13 @@ void annotation_t::parse(std::istream& in)
temp.parse(buf, amount_t::PARSE_NO_MIGRATE);
temp.in_place_reduce();
-#ifdef INTEGER_MATH
// Since this price will maintain its own precision, make sure
// it is at least as large as the base commodity, since the user
// may have only specified {$1} or something similar.
if (temp.has_commodity() &&
temp.precision() > temp.commodity().precision())
- temp = temp.round(); // no need to retain individual precision
-#endif
+ temp = temp.rounded(); // no need to retain individual precision
price = temp;
}
diff --git a/src/entry.cc b/src/entry.cc
index 9749b1df..d1aa1234 100644
--- a/src/entry.cc
+++ b/src/entry.cc
@@ -231,7 +231,7 @@ bool entry_base_t::finalize()
add_error_context(entry_context(*this));
#endif
add_error_context("Unbalanced remainder is: ");
- add_error_context(value_context(balance.unround()));
+ add_error_context(value_context(balance.unrounded()));
throw_(balance_error, "Entry does not balance");
}
diff --git a/src/filters.cc b/src/filters.cc
index 47dec09b..4b8c7162 100644
--- a/src/filters.cc
+++ b/src/filters.cc
@@ -367,11 +367,7 @@ void changed_value_xacts::output_diff(const date_t& date)
value_t cur_bal;
last_xact->xdata().date = date;
-#ifdef INTEGER_MATH
- cur_bal = total_expr.calc(*last_xact).round();
-#else
- cur_bal = total_expr.calc(*last_xact);
-#endif
+ cur_bal = total_expr.calc(*last_xact).rounded();
if (value_t diff = cur_bal - last_balance) {
entry_temps.push_back(entry_t());
@@ -394,11 +390,7 @@ void changed_value_xacts::operator()(xact_t& xact)
item_handler<xact_t>::operator()(xact);
-#ifdef INTEGER_MATH
- last_balance = total_expr.calc(xact).round();
-#else
- last_balance = total_expr.calc(xact);
-#endif
+ last_balance = total_expr.calc(xact).rounded();
last_xact = &xact;
}
diff --git a/src/gnucash.cc b/src/gnucash.cc
index 91217699..29528013 100644
--- a/src/gnucash.cc
+++ b/src/gnucash.cc
@@ -187,11 +187,7 @@ static void endElement(void *, const char *name)
if (default_commodity) {
curr_quant.set_commodity(*default_commodity);
-#ifdef INTEGER_MATH
- value = curr_quant.round();
-#else
- value = curr_quant;
-#endif
+ value = curr_quant.rounded();
if (curr_value.commodity() == *default_commodity)
curr_value = value;
diff --git a/src/value.cc b/src/value.cc
index b63b8d76..b5ee6602 100644
--- a/src/value.cc
+++ b/src/value.cc
@@ -1400,56 +1400,28 @@ value_t value_t::abs() const
return NULL_VALUE;
}
-#ifdef INTEGER_MATH
-
-value_t value_t::round() const
+value_t value_t::rounded() const
{
switch (type()) {
case INTEGER:
return *this;
case AMOUNT:
- return as_amount().round();
- case BALANCE:
- return as_balance().round();
- case BALANCE_PAIR:
- return as_balance_pair().round();
+ return as_amount().rounded();
default:
break;
}
- throw_(value_error, "Cannot round " << label());
+ throw_(value_error, "Cannot set rounding for " << label());
return NULL_VALUE;
}
-void value_t::in_place_round()
-{
- switch (type()) {
- case INTEGER:
- break;
- case AMOUNT:
- as_amount_lval().in_place_round();
- break;
- case BALANCE:
- as_balance_lval().in_place_round();
- break;
- case BALANCE_PAIR:
- as_balance_pair_lval().in_place_round();
- break;
- default:
- throw_(value_error, "Cannot round " << label());
- break;
- }
-}
-
-#endif // INTEGER_MATH
-
-value_t value_t::unround() const
+value_t value_t::unrounded() const
{
switch (type()) {
case INTEGER:
return *this;
case AMOUNT:
- return as_amount().unround();
+ return as_amount().unrounded();
default:
break;
}
diff --git a/src/value.h b/src/value.h
index bb04508e..069a3c46 100644
--- a/src/value.h
+++ b/src/value.h
@@ -404,11 +404,9 @@ public:
}
value_t abs() const;
-#ifdef INTEGER_MATH
- value_t round() const;
- void in_place_round();
-#endif
- value_t unround() const;
+
+ value_t rounded() const;
+ value_t unrounded() const;
value_t reduce() const {
value_t temp(*this);
diff --git a/test/unit/t_amount.cc b/test/unit/t_amount.cc
index 3b199f5b..577a4aaf 100644
--- a/test/unit/t_amount.cc
+++ b/test/unit/t_amount.cc
@@ -213,6 +213,7 @@ void AmountTestCase::testCommodityConstructors()
}
#ifndef NOT_FOR_PYTHON
+
void AmountTestCase::testAssignment()
{
amount_t x0;
@@ -318,6 +319,7 @@ void AmountTestCase::testCommodityAssignment()
assertValid(x9);
assertValid(x10);
}
+
#endif // NOT_FOR_PYTHON
void AmountTestCase::testEquality()
@@ -423,8 +425,10 @@ void AmountTestCase::testComparisons()
assertTrue(100L > x1);
assertTrue(x1 < 100UL);
assertTrue(100UL > x1);
+#ifndef NOT_FOR_PYTHON
assertTrue(x1 < 100.0);
assertTrue(100.0 > x1);
+#endif // NOT_FOR_PYTHON
assertValid(x0);
assertValid(x1);
@@ -538,7 +542,9 @@ void AmountTestCase::testCommodityAddition()
assertThrow(x1 + x4, amount_error);
assertThrow(x1 + x5, amount_error);
assertThrow(x1 + x6, amount_error);
+#ifndef NOT_FOR_PYTHON
assertThrow(x1 + 123.45, amount_error);
+#endif // NOT_FOR_PYTHON
assertThrow(x1 + 123L, amount_error);
assertEqual(amount_t("DM 246.90"), x3 + x3);
@@ -652,7 +658,9 @@ void AmountTestCase::testCommoditySubtraction()
assertThrow(x1 - x4, amount_error);
assertThrow(x1 - x5, amount_error);
assertThrow(x1 - x6, amount_error);
+#ifndef NOT_FOR_PYTHON
assertThrow(x1 - 123.45, amount_error);
+#endif // NOT_FOR_PYTHON
assertThrow(x1 - 123L, amount_error);
assertEqual(amount_t("DM 0.00"), x3 - x3);
@@ -857,11 +865,7 @@ void AmountTestCase::testIntegerDivision()
x1 /= amount_t(456L);
assertEqual(string("0.269737"), x1.to_string());
x1 /= 456L;
-#ifdef INTEGER_MATH
- assertEqual(string("0.00059152850877193"), x1.to_string());
-#else
assertEqual(string("0.000591528162511542"), x1.to_string());
-#endif
amount_t x4("123456789123456789123456789");
amount_t y4("56");
@@ -901,13 +905,9 @@ void AmountTestCase::testFractionalDivision()
x1 /= amount_t("456.456");
assertEqual(string("0.269736842105263"), x1.to_string());
x1 /= amount_t("456.456");
-#ifdef INTEGER_MATH
- assertEqual(string("0.000590937225286255411255411255411255411"), x1.to_string());
-#else
assertEqual(string("0.000590937225286255757169884601508201951"), x1.to_string());
-#endif
x1 /= 456L;
- assertEqual(string("0.000001295914967733016252753094858358016252192982456140350877192982456140350877192982"), x1.to_string());
+ assertEqual(string("0.000001295914967733017011337466214297678193292890066687335298289595263924317558590360"), x1.to_string());
amount_t x4("1234567891234567.89123456789");
amount_t y4("56.789");
@@ -934,18 +934,18 @@ void AmountTestCase::testCommodityDivision()
assertThrow(x1 / 0L, amount_error);
assertEqual(amount_t("$0.00"), 0L / x1);
assertEqual(x1, x1 / 1L);
- assertEqual(string("$0.00812216"), (1L / x1).to_string());
+ assertEqual(string("$0.00812216"), (1L / x1).to_fullstring());
assertEqual(- x1, x1 / -1L);
- assertEqual(string("$-0.00812216"), (-1L / x1).to_string());
- assertEqual(string("$0.26973382"), (x1 / y1).to_string());
+ assertEqual(string("$-0.00812216"), (-1L / x1).to_fullstring());
+ assertEqual(string("$0.26973382"), (x1 / y1).to_fullstring());
assertEqual(string("$0.27"), (x1 / y1).to_string());
- assertEqual(string("$3.70735867"), (y1 / x1).to_string());
+ assertEqual(string("$3.70735867"), (y1 / x1).to_fullstring());
assertEqual(string("$3.71"), (y1 / x1).to_string());
// Internal amounts retain their precision, even when being
// converted to strings
- assertEqual(string("$0.99727201"), (x1 / x2).to_string());
- assertEqual(string("$1.00273545321637426901"), (x2 / x1).to_string());
+ assertEqual(string("$0.99727201"), (x1 / x2).to_fullstring());
+ assertEqual(string("$1.00273545321637426901"), (x2 / x1).to_fullstring());
assertEqual(string("$1.00"), (x1 / x2).to_string());
assertEqual(string("$1.00273545321637426901"), (x2 / x1).to_string());
@@ -959,10 +959,10 @@ void AmountTestCase::testCommodityDivision()
x1 /= amount_t("123.12");
assertEqual(string("$1.00"), x1.to_string());
x1 /= amount_t("123.12");
- assertEqual(string("$0.00812216"), x1.to_string());
+ assertEqual(string("$0.00812216"), x1.to_fullstring());
assertEqual(string("$0.01"), x1.to_string());
x1 /= 123L;
- assertEqual(string("$0.00006603"), x1.to_string());
+ assertEqual(string("$0.00006603"), x1.to_fullstring());
assertEqual(string("$0.00"), x1.to_string());
amount_t x6(internalAmount("$237235987235987.98723987235978"));
@@ -970,9 +970,9 @@ void AmountTestCase::testCommodityDivision()
assertEqual(amount_t("$1"), x7 / x7);
assertEqual(string("$0.0019216115121765559608381226612019501046413574469262"),
- (x6 / x7).to_string());
+ (x6 / x7).to_fullstring());
assertEqual(string("$520.39654928343335571379527154924040947271699678158689736256"),
- (x7 / x6).to_string());
+ (x7 / x6).to_fullstring());
assertValid(x1);
assertValid(x2);
@@ -1098,177 +1098,6 @@ void AmountTestCase::testCommodityAbs()
assertValid(x2);
}
-#ifndef NOT_FOR_PYTHON
-#ifdef INTEGER_MATH
-
-void AmountTestCase::testFractionalRound()
-{
- amount_t x0;
- amount_t x1("1234.567890");
-
- assertThrow(x0.precision(), amount_error);
- assertThrow(x0.round(), amount_error);
- assertThrow(x0.round(2), amount_error);
- assertThrow(x0.unround(), amount_error);
- assertEqual(amount_t::precision_t(6), x1.precision());
-
- amount_t x1b(x1.unround());
-
- assertEqual(x1b.precision(), x1b.unround().precision());
-
- amount_t y7(x1.round(7));
- amount_t y6(x1.round(6));
- amount_t y5(x1.round(5));
- amount_t y4(x1.round(4));
- amount_t y3(x1.round(3));
- amount_t y2(x1.round(2));
- amount_t y1(x1.round(1));
- amount_t y0(x1.round(0));
-
- assertEqual(amount_t::precision_t(6), y7.precision());
- assertEqual(amount_t::precision_t(6), y6.precision());
- assertEqual(amount_t::precision_t(5), y5.precision());
- assertEqual(amount_t::precision_t(4), y4.precision());
- assertEqual(amount_t::precision_t(3), y3.precision());
- assertEqual(amount_t::precision_t(2), y2.precision());
- assertEqual(amount_t::precision_t(1), y1.precision());
- assertEqual(amount_t::precision_t(0), y0.precision());
-
- assertEqual(amount_t("1234.56789"), y7);
- assertEqual(amount_t("1234.56789"), y6);
- assertEqual(amount_t("1234.56789"), y5);
- assertEqual(amount_t("1234.5679"), y4);
- assertEqual(amount_t("1234.568"), y3);
- assertEqual(amount_t("1234.57"), y2);
- assertEqual(amount_t("1234.6"), y1);
- assertEqual(amount_t("1235"), y0);
-
- amount_t x2("9876.543210");
-
- assertEqual(amount_t("9876.543210"), x2.round(6));
- assertEqual(amount_t("9876.54321"), x2.round(5));
- assertEqual(amount_t("9876.5432"), x2.round(4));
- assertEqual(amount_t("9876.543"), x2.round(3));
- assertEqual(amount_t("9876.54"), x2.round(2));
- assertEqual(amount_t("9876.5"), x2.round(1));
- assertEqual(amount_t("9877"), x2.round(0));
-
- amount_t x3("-1234.567890");
-
- assertEqual(amount_t("-1234.56789"), x3.round(6));
- assertEqual(amount_t("-1234.56789"), x3.round(5));
- assertEqual(amount_t("-1234.5679"), x3.round(4));
- assertEqual(amount_t("-1234.568"), x3.round(3));
- assertEqual(amount_t("-1234.57"), x3.round(2));
- assertEqual(amount_t("-1234.6"), x3.round(1));
- assertEqual(amount_t("-1235"), x3.round(0));
-
- amount_t x4("-9876.543210");
-
- assertEqual(amount_t("-9876.543210"), x4.round(6));
- assertEqual(amount_t("-9876.54321"), x4.round(5));
- assertEqual(amount_t("-9876.5432"), x4.round(4));
- assertEqual(amount_t("-9876.543"), x4.round(3));
- assertEqual(amount_t("-9876.54"), x4.round(2));
- assertEqual(amount_t("-9876.5"), x4.round(1));
- assertEqual(amount_t("-9877"), x4.round(0));
-
- amount_t x5("0.0000000000000000000000000000000000001");
-
- assertEqual(amount_t("0.0000000000000000000000000000000000001"),
- x5.round(37));
- assertEqual(amount_t(0L), x5.round(36));
-
- assertValid(x1);
- assertValid(x2);
- assertValid(x3);
- assertValid(x4);
- assertValid(x5);
-}
-
-void AmountTestCase::testCommodityRound()
-{
- amount_t x1(internalAmount("$1234.567890"));
-
- assertEqual(internalAmount("$1234.56789"), x1.round(6));
- assertEqual(internalAmount("$1234.56789"), x1.round(5));
- assertEqual(internalAmount("$1234.5679"), x1.round(4));
- assertEqual(internalAmount("$1234.568"), x1.round(3));
- assertEqual(amount_t("$1234.57"), x1.round(2));
- assertEqual(amount_t("$1234.6"), x1.round(1));
- assertEqual(amount_t("$1235"), x1.round(0));
-
- amount_t x2(internalAmount("$9876.543210"));
-
- assertEqual(internalAmount("$9876.543210"), x2.round(6));
- assertEqual(internalAmount("$9876.54321"), x2.round(5));
- assertEqual(internalAmount("$9876.5432"), x2.round(4));
- assertEqual(internalAmount("$9876.543"), x2.round(3));
- assertEqual(amount_t("$9876.54"), x2.round(2));
- assertEqual(amount_t("$9876.5"), x2.round(1));
- assertEqual(amount_t("$9877"), x2.round(0));
-
- amount_t x3(internalAmount("$-1234.567890"));
-
- assertEqual(internalAmount("$-1234.56789"), x3.round(6));
- assertEqual(internalAmount("$-1234.56789"), x3.round(5));
- assertEqual(internalAmount("$-1234.5679"), x3.round(4));
- assertEqual(internalAmount("$-1234.568"), x3.round(3));
- assertEqual(amount_t("$-1234.57"), x3.round(2));
- assertEqual(amount_t("$-1234.6"), x3.round(1));
- assertEqual(amount_t("$-1235"), x3.round(0));
-
- amount_t x4(internalAmount("$-9876.543210"));
-
- assertEqual(internalAmount("$-9876.543210"), x4.round(6));
- assertEqual(internalAmount("$-9876.54321"), x4.round(5));
- assertEqual(internalAmount("$-9876.5432"), x4.round(4));
- assertEqual(internalAmount("$-9876.543"), x4.round(3));
- assertEqual(amount_t("$-9876.54"), x4.round(2));
- assertEqual(amount_t("$-9876.5"), x4.round(1));
- assertEqual(amount_t("$-9877"), x4.round(0));
-
- amount_t x5("$123.45");
-
- x5 *= amount_t("100.12");
-
- assertEqual(internalAmount("$12359.814"), x5);
- assertEqual(string("$12359.81"), x5.to_string());
- assertEqual(string("$12359.814"), x5.to_fullstring());
- assertEqual(string("$12359.814"), x5.unround().to_string());
-
- assertValid(x1);
- assertValid(x2);
- assertValid(x3);
- assertValid(x4);
- assertValid(x5);
-}
-
-void AmountTestCase::testCommodityDisplayRound()
-{
- amount_t x1("$0.85");
- amount_t x2("$0.1");
-
- x1 *= amount_t("0.19");
-
- assertNotEqual(amount_t("$0.16"), x1);
- assertEqual(internalAmount("$0.1615"), x1);
- assertEqual(string("$0.16"), x1.to_string());
-
- assertEqual(amount_t("$0.10"), x2);
- assertNotEqual(internalAmount("$0.101"), x2);
- assertEqual(string("$0.10"), x2.to_string());
-
- x1 *= 7L;
-
- assertNotEqual(amount_t("$1.13"), x1);
- assertEqual(internalAmount("$1.1305"), x1);
- assertEqual(string("$1.13"), x1.to_string());
-}
-
-#endif // INTEGER_MATH
-#endif
-
void AmountTestCase::testReduction()
{
amount_t x0;
@@ -1411,10 +1240,7 @@ void AmountTestCase::testFractionalConversion()
amount_t x1("1234.56");
amount_t x2("1234.5683787634678348734");
- assertThrow(x1.to_long(), amount_error); // loses precision
- assertThrow(x2.to_double(), amount_error); // loses precision
- assertFalse(x2.fits_in_double());
- assertEqual(1234L, x1.to_long(true));
+ assertEqual(1235L, x1.to_long());
assertEqual(1234.56, x1.to_double());
assertEqual(string("1234.56"), x1.to_string());
assertEqual(string("1234.56"), x1.quantity_string());
@@ -1426,8 +1252,7 @@ void AmountTestCase::testCommodityConversion()
{
amount_t x1("$1234.56");
- assertThrow(x1.to_long(), amount_error); // loses precision
- assertEqual(1234L, x1.to_long(true));
+ assertEqual(1235L, x1.to_long());
assertEqual(1234.56, x1.to_double());
assertEqual(string("$1234.56"), x1.to_string());
assertEqual(string("1234.56"), x1.quantity_string());
@@ -1436,6 +1261,7 @@ void AmountTestCase::testCommodityConversion()
}
#ifndef NOT_FOR_PYTHON
+
void AmountTestCase::testPrinting()
{
amount_t x0;
@@ -1579,4 +1405,5 @@ void AmountTestCase::testXmlSerialization()
assertEqual(std::string("<amount>\n <commodity flags=\"PT\">\n <symbol>$</symbol>\n </commodity>\n <quantity>8192.34</quantity>\n</amount>\n"), storage.str());
}
+
#endif // NOT_FOR_PYTHON
diff --git a/test/unit/t_amount.h b/test/unit/t_amount.h
index 92bbe9b8..a3727c61 100644
--- a/test/unit/t_amount.h
+++ b/test/unit/t_amount.h
@@ -32,11 +32,6 @@ class AmountTestCase : public CPPUNIT_NS::TestCase
CPPUNIT_TEST(testCommodityNegation);
CPPUNIT_TEST(testAbs);
CPPUNIT_TEST(testCommodityAbs);
-#ifdef INTEGER_MATH
- CPPUNIT_TEST(testFractionalRound);
- CPPUNIT_TEST(testCommodityRound);
- CPPUNIT_TEST(testCommodityDisplayRound);
-#endif
CPPUNIT_TEST(testReduction);
CPPUNIT_TEST(testSign);
CPPUNIT_TEST(testCommoditySign);
diff --git a/test/unit/t_commodity.cc b/test/unit/t_commodity.cc
index 81538e76..9818c863 100644
--- a/test/unit/t_commodity.cc
+++ b/test/unit/t_commodity.cc
@@ -75,22 +75,27 @@ void CommodityTestCase::testPriceHistory()
amt = x1.value(current_time);
assertTrue(amt);
- assertEqual(amount_t("$2124.12"), *amt);
+ assertEqual(string("$2124.12"), amt->to_string());
+#ifdef INTEGER_MATH
+ assertEqual(string("$2124.12"), amt->to_fullstring());
+#else
+ assertEqual(string("$2124.1220"), amt->to_fullstring());
+#endif
amt = x1.value(current_time, euro);
assertTrue(amt);
- assertEqual(amount_t("EUR 1366.87"), *amt);
+ assertEqual(string("EUR 1366.87"), amt->rounded().to_string());
// Add a newer Euro pricing
aapl.add_price(jan17_07, amount_t("EUR 23.00"));
amt = x1.value(current_time, euro);
assertTrue(amt);
- assertEqual(amount_t("EUR 2302.30"), *amt);
+ assertEqual(string("EUR 2302.30"), amt->to_string());
amt = x1.value(current_time, cad);
assertTrue(amt);
- assertEqual(amount_t("CAD 3223.22"), *amt);
+ assertEqual(string("CAD 3223.22"), amt->to_string());
#endif // NOT_FOR_PYTHON
assertValid(x1);