diff options
-rw-r--r-- | src/amount.cc | 48 | ||||
-rw-r--r-- | src/amount.h | 28 | ||||
-rw-r--r-- | src/commodity.h | 2 | ||||
-rw-r--r-- | src/py_amount.cc | 6 | ||||
-rw-r--r-- | tests/numerics/BasicAmount.cc | 8 | ||||
-rw-r--r-- | tests/numerics/CommodityAmount.cc | 4 | ||||
-rw-r--r-- | tests/python/numerics/CommodityAmount.py | 2 |
7 files changed, 73 insertions, 25 deletions
diff --git a/src/amount.cc b/src/amount.cc index cc76ed3e..7b8b1a91 100644 --- a/src/amount.cc +++ b/src/amount.cc @@ -84,7 +84,7 @@ class amount_t::bigint_t ~bigint_t(); }; -unsigned int sizeof_bigint_t() { +std::size_t sizeof_bigint_t() { return sizeof(amount_t::bigint_t); } @@ -216,7 +216,7 @@ void amount_t::_copy(const amount_t& amt) commodity_ = amt.commodity_; } -void amount_t::_resize(unsigned int prec) +void amount_t::_resize(precision_t prec) { assert(prec < 256); @@ -560,7 +560,7 @@ amount_t& amount_t::operator*=(const amount_t& amt) commodity_ = amt.commodity_; if (has_commodity() && ! (quantity->flags & BIGINT_KEEP_PREC)) { - unsigned int comm_prec = commodity().precision(); + precision_t comm_prec = commodity().precision(); if (quantity->prec > comm_prec + 6U) { mpz_round(MPZ(quantity), MPZ(quantity), quantity->prec, comm_prec + 6U); quantity->prec = comm_prec + 6U; @@ -612,7 +612,7 @@ amount_t& amount_t::operator/=(const amount_t& amt) // plus six places. if (has_commodity() && ! (quantity->flags & BIGINT_KEEP_PREC)) { - unsigned int comm_prec = commodity().precision(); + precision_t comm_prec = commodity().precision(); if (quantity->prec > comm_prec + 6U) { mpz_round(MPZ(quantity), MPZ(quantity), quantity->prec, comm_prec + 6U); quantity->prec = comm_prec + 6U; @@ -650,6 +650,44 @@ bool amount_t::zero() const return realzero(); } +long amount_t::to_long() const +{ + if (! quantity) + return 0; + + mpz_set(temp, MPZ(quantity)); + mpz_ui_pow_ui(divisor, 10, quantity->prec); + mpz_tdiv_q(temp, temp, divisor); + + return mpz_get_si(temp); +} + +double amount_t::to_double() const +{ + if (! quantity) + return 0.0; + + mpz_t remainder; + mpz_init(remainder); + + mpz_set(temp, MPZ(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); + + return lexical_cast<double>(num.str()); +} + amount_t amount_t::value(const moment_t& moment) const { if (quantity) { @@ -660,7 +698,7 @@ amount_t amount_t::value(const moment_t& moment) const return *this; } -amount_t amount_t::round(unsigned int prec) const +amount_t amount_t::round(precision_t prec) const { amount_t t = *this; diff --git a/src/amount.h b/src/amount.h index f90a5e4c..47fc913d 100644 --- a/src/amount.h +++ b/src/amount.h @@ -66,18 +66,23 @@ DECLARE_EXCEPTION(amount_error); * math, and also for uncommoditized math. In the commoditized case, * commodities keep track of how they are used, and will always * display back to the user after the same fashion. For - * uncommoditized numbers, no display truncation is ever done. - * Internally, precision is always kept to an excessive degree. + * uncommoditized numbers, no display truncation is ever done. In + * both cases, internal precision is always kept to an excessive + * degree. */ - class amount_t - : public ordered_field_operators<amount_t, - ordered_field_operators<amount_t, long, - ordered_field_operators<amount_t, unsigned long, - ordered_field_operators<amount_t, double> > > > +class amount_t + : public ordered_field_operators<amount_t, + ordered_field_operators<amount_t, long, + ordered_field_operators<amount_t, unsigned long, + ordered_field_operators<amount_t, double> > > > { public: class bigint_t; + // jww (2007-05-01): Change my uses of unsigned int to use this type + // for precision values. Or perhaps just std::size_t? + typedef uint_least16_t precision_t; + static void initialize(); static void shutdown(); @@ -92,7 +97,7 @@ protected: void _copy(const amount_t& amt); void _release(); void _dup(); - void _resize(unsigned int prec); + void _resize(precision_t prec); void _clear(); bigint_t * quantity; @@ -170,6 +175,9 @@ public: // test for truth, zero and non-zero operator bool() const { + return nonzero(); + } + bool nonzero() const { return ! zero(); } @@ -180,6 +188,8 @@ public: } // conversion methods + long to_long() const; + double to_double() const; string to_string() const; string to_fullstring() const; string quantity_string() const; @@ -220,7 +230,7 @@ public: optional<string> tag() const; // general methods - amount_t round(unsigned int prec) const; + amount_t round(precision_t prec) const; amount_t round() const; amount_t unround() const; amount_t value(const moment_t& moment) const; diff --git a/src/commodity.h b/src/commodity.h index 44754f0d..e3a89333 100644 --- a/src/commodity.h +++ b/src/commodity.h @@ -138,7 +138,7 @@ typedef std::pair<const string, commodity_t *> commodities_pair; typedef std::vector<commodity_t *> commodities_array; -class commodity_t +class commodity_t : public equality_comparable<commodity_t> { friend class annotated_commodity_t; diff --git a/src/py_amount.cc b/src/py_amount.cc index 86dac640..89960fdf 100644 --- a/src/py_amount.cc +++ b/src/py_amount.cc @@ -147,9 +147,9 @@ void export_amount() .def(! self) - .def(self_ns::int_(self)) - .def(self_ns::float_(self)) - + .def("__int__", &amount_t::to_long) + .def("__float__", &amount_t::to_double) + .def("__nonzero__", &amount_t::nonzero) .def("__abs__", &amount_t::abs) .def("__str__", &amount_t::to_string) .def("__repr__", &amount_t::to_fullstring) diff --git a/tests/numerics/BasicAmount.cc b/tests/numerics/BasicAmount.cc index 626c3ba8..bcc5c2b5 100644 --- a/tests/numerics/BasicAmount.cc +++ b/tests/numerics/BasicAmount.cc @@ -415,8 +415,8 @@ void BasicAmountTestCase::testIntegerConversion() amount_t x1(123456L); assertEqual(true, bool(x1)); - assertEqual(123456L, long(x1)); - assertEqual(123456.0, double(x1)); + assertEqual(123456L, x1.to_long()); + assertEqual(123456.0, x1.to_double()); assertEqual(string("123456"), x1.to_string()); assertEqual(string("123456"), x1.quantity_string()); @@ -428,8 +428,8 @@ void BasicAmountTestCase::testFractionalConversion() amount_t x1(1234.56); assertEqual(true, bool(x1)); - assertEqual(1234L, long(x1)); - assertEqual(1234.56, double(x1)); + assertEqual(1234L, x1.to_long()); + assertEqual(1234.56, x1.to_double()); assertEqual(string("1234.56"), x1.to_string()); assertEqual(string("1234.56"), x1.quantity_string()); diff --git a/tests/numerics/CommodityAmount.cc b/tests/numerics/CommodityAmount.cc index ffedbdac..e443d6a1 100644 --- a/tests/numerics/CommodityAmount.cc +++ b/tests/numerics/CommodityAmount.cc @@ -465,8 +465,8 @@ void CommodityAmountTestCase::testConversion() amount_t x1("$1234.56"); assertEqual(true, bool(x1)); - assertEqual(1234L, long(x1)); - assertEqual(1234.56, double(x1)); + assertEqual(1234L, x1.to_long()); + assertEqual(1234.56, x1.to_double()); assertEqual(string("$1234.56"), x1.to_string()); assertEqual(string("1234.56"), x1.quantity_string()); diff --git a/tests/python/numerics/CommodityAmount.py b/tests/python/numerics/CommodityAmount.py index 80f58b21..5c177044 100644 --- a/tests/python/numerics/CommodityAmount.py +++ b/tests/python/numerics/CommodityAmount.py @@ -177,7 +177,7 @@ class CommodityAmountTestCase(unittest.TestCase): x9 = amount("123.45€") x10 = amount("-123.45€") - self.assertTrue(x0.null()) + self.assertTrue(x0.is_null()) self.assertTrue(x0.zero()) self.assertTrue(x0.realzero()) self.assertTrue(x0.sign() == 0) |