summaryrefslogtreecommitdiff
path: root/amount.cc
diff options
context:
space:
mode:
authorJohn Wiegley <johnw@newartisans.com>2004-08-21 05:40:06 -0400
committerJohn Wiegley <johnw@newartisans.com>2004-08-21 05:40:06 -0400
commit86ac953379adc270ff1c9f5bc45256d29f0c41cd (patch)
tree97e3e74809a8fb2f1066188a01b83866be1b8563 /amount.cc
parent7dbd7bce59acf5e2121abba6491b67449455bb86 (diff)
downloadfork-ledger-86ac953379adc270ff1c9f5bc45256d29f0c41cd.tar.gz
fork-ledger-86ac953379adc270ff1c9f5bc45256d29f0c41cd.tar.bz2
fork-ledger-86ac953379adc270ff1c9f5bc45256d29f0c41cd.zip
tracked down a tricky memory leak in value.h
Diffstat (limited to 'amount.cc')
-rw-r--r--amount.cc118
1 files changed, 68 insertions, 50 deletions
diff --git a/amount.cc b/amount.cc
index b984d29d..43a36322 100644
--- a/amount.cc
+++ b/amount.cc
@@ -34,12 +34,16 @@ class amount_t::bigint_t {
bigint_t() : prec(0), ref(1), index(0) {
mpz_init(val);
#ifdef DEBUG_ENABLED
+ DEBUG_PRINT("ledger.amount.bigint-show",
+ "ctor " << this << " " << bigint_ctors);
bigint_ctors++;
#endif
}
bigint_t(mpz_t _val) : prec(0), ref(1), index(0) {
mpz_init_set(val, _val);
#ifdef DEBUG_ENABLED
+ DEBUG_PRINT("ledger.amount.bigint-show",
+ "ctor " << this << " " << bigint_ctors);
bigint_ctors++;
#endif
}
@@ -47,15 +51,19 @@ class amount_t::bigint_t {
: prec(other.prec), ref(1), index(0) {
mpz_init_set(val, other.val);
#ifdef DEBUG_ENABLED
+ DEBUG_PRINT("ledger.amount.bigint-show",
+ "ctor " << this << " " << bigint_ctors);
bigint_ctors++;
#endif
}
~bigint_t() {
assert(ref == 0);
- mpz_clear(val);
#ifdef DEBUG_ENABLED
+ DEBUG_PRINT("ledger.amount.bigint-show",
+ "dtor " << this << " " << bigint_dtors);
bigint_dtors++;
#endif
+ mpz_clear(val);
}
};
@@ -131,6 +139,10 @@ static void mpz_round(mpz_t out, mpz_t value, int value_prec, int round_prec)
}
}
+ // chop off the rounded bits
+ mpz_ui_pow_ui(divisor, 10, value_prec - round_prec);
+ mpz_tdiv_q(out, out, divisor);
+
mpz_clear(quotient);
mpz_clear(remainder);
}
@@ -185,6 +197,8 @@ amount_t::amount_t(const double value)
void amount_t::_release()
{
+ DEBUG_PRINT("ledger.amount.bigint-show",
+ "bigint " << quantity << " --ref " << (quantity->ref - 1));
if (--quantity->ref == 0)
delete quantity;
}
@@ -217,6 +231,8 @@ void amount_t::_copy(const amount_t& amt)
quantity = amt.quantity;
quantity->ref++;
+ DEBUG_PRINT("ledger.amount.bigint-show",
+ "bigint " << quantity << " ++ref " << quantity->ref);
}
commodity = amt.commodity;
}
@@ -322,58 +338,64 @@ void amount_t::_resize(unsigned int prec)
amount_t& amount_t::operator+=(const amount_t& amt)
{
- if (amt.quantity) {
- if (! quantity) {
- quantity = new bigint_t(*amt.quantity);
- commodity = amt.commodity;
- } else {
- _dup();
+ if (! amt.quantity)
+ return *this;
+
+ if (! quantity) {
+ quantity = new bigint_t(*amt.quantity);
+ commodity = amt.commodity;
+ return *this;
+ }
- if (commodity != amt.commodity)
- throw amount_error("Adding amounts with different commodities");
+ _dup();
- if (quantity->prec == amt.quantity->prec) {
- mpz_add(MPZ(quantity), MPZ(quantity), MPZ(amt.quantity));
- }
- else if (quantity->prec < amt.quantity->prec) {
- _resize(amt.quantity->prec);
- mpz_add(MPZ(quantity), MPZ(quantity), MPZ(amt.quantity));
- } else {
- amount_t temp = amt;
- temp._resize(quantity->prec);
- mpz_add(MPZ(quantity), MPZ(quantity), MPZ(temp.quantity));
- }
- }
+ if (commodity != amt.commodity)
+ throw amount_error("Adding amounts with different commodities");
+
+ if (quantity->prec == amt.quantity->prec) {
+ mpz_add(MPZ(quantity), MPZ(quantity), MPZ(amt.quantity));
}
+ else if (quantity->prec < amt.quantity->prec) {
+ _resize(amt.quantity->prec);
+ mpz_add(MPZ(quantity), MPZ(quantity), MPZ(amt.quantity));
+ } else {
+ amount_t temp = amt;
+ temp._resize(quantity->prec);
+ mpz_add(MPZ(quantity), MPZ(quantity), MPZ(temp.quantity));
+ }
+
return *this;
}
amount_t& amount_t::operator-=(const amount_t& amt)
{
- if (amt.quantity) {
- if (! quantity) {
- quantity = new bigint_t(*amt.quantity);
- mpz_neg(MPZ(quantity), MPZ(quantity));
- commodity = amt.commodity;
- } else {
- _dup();
+ if (! amt.quantity)
+ return *this;
- if (commodity != amt.commodity)
- throw amount_error("Subtracting amounts with different commodities");
+ if (! quantity) {
+ quantity = new bigint_t(*amt.quantity);
+ mpz_neg(MPZ(quantity), MPZ(quantity));
+ commodity = amt.commodity;
+ return *this;
+ }
- if (quantity->prec == amt.quantity->prec) {
- mpz_sub(MPZ(quantity), MPZ(quantity), MPZ(amt.quantity));
- }
- else if (quantity->prec < amt.quantity->prec) {
- _resize(amt.quantity->prec);
- mpz_sub(MPZ(quantity), MPZ(quantity), MPZ(amt.quantity));
- } else {
- amount_t temp = amt;
- temp._resize(quantity->prec);
- mpz_sub(MPZ(quantity), MPZ(quantity), MPZ(temp.quantity));
- }
- }
+ _dup();
+
+ if (commodity != amt.commodity)
+ throw amount_error("Subtracting amounts with different commodities");
+
+ if (quantity->prec == amt.quantity->prec) {
+ mpz_sub(MPZ(quantity), MPZ(quantity), MPZ(amt.quantity));
}
+ else if (quantity->prec < amt.quantity->prec) {
+ _resize(amt.quantity->prec);
+ mpz_sub(MPZ(quantity), MPZ(quantity), MPZ(amt.quantity));
+ } else {
+ amount_t temp = amt;
+ temp._resize(quantity->prec);
+ mpz_sub(MPZ(quantity), MPZ(quantity), MPZ(temp.quantity));
+ }
+
return *this;
}
@@ -598,11 +620,7 @@ amount_t amount_t::round(unsigned int prec) const
amount_t temp = *this;
temp._dup();
mpz_round(MPZ(temp.quantity), MPZ(temp.quantity), quantity->prec, prec);
-#if 0
- mpz_ui_pow_ui(divisor, 10, quantity->prec - prec);
- mpz_tdiv_q(MPZ(temp.quantity), MPZ(temp.quantity), divisor);
quantity->prec = prec;
-#endif
return temp;
}
}
@@ -626,10 +644,8 @@ std::ostream& operator<<(std::ostream& out, const amount_t& amt)
// outputting it. NOTE: `rquotient' is used here as a temp variable!
if (amt.commodity->precision < amt.quantity->prec) {
- mpz_round(rquotient, MPZ(amt.quantity),
- amt.quantity->prec, amt.commodity->precision);
- mpz_ui_pow_ui(divisor, 10, amt.quantity->prec - amt.commodity->precision);
- mpz_tdiv_q(rquotient, rquotient, divisor);
+ mpz_round(rquotient, MPZ(amt.quantity), amt.quantity->prec,
+ amt.commodity->precision);
mpz_ui_pow_ui(divisor, 10, amt.commodity->precision);
mpz_tdiv_qr(quotient, remainder, rquotient, divisor);
}
@@ -928,6 +944,8 @@ void amount_t::read_quantity(std::istream& in)
assert(index <= bigints.size());
quantity = bigints[index - 1];
quantity->ref++;
+ DEBUG_PRINT("ledger.amount.bigint-show",
+ "bigint " << quantity << " ++ref " << quantity->ref);
}
}