summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/amount.cc48
-rw-r--r--src/amount.h28
-rw-r--r--src/commodity.h2
-rw-r--r--src/py_amount.cc6
-rw-r--r--tests/numerics/BasicAmount.cc8
-rw-r--r--tests/numerics/CommodityAmount.cc4
-rw-r--r--tests/python/numerics/CommodityAmount.py2
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)