diff options
author | John Wiegley <johnw@newartisans.com> | 2007-04-17 07:33:36 +0000 |
---|---|---|
committer | John Wiegley <johnw@newartisans.com> | 2008-04-13 03:35:36 -0400 |
commit | 0f2cad4cab7ef99e1ad33be34ea813213da7288d (patch) | |
tree | 0dbd64dfdb1022d811d2dfdc5f3693f5faafafb8 /amount.cc | |
parent | 2e3082e734362fb934ff8f308fe9fd9f85c35032 (diff) | |
download | fork-ledger-0f2cad4cab7ef99e1ad33be34ea813213da7288d.tar.gz fork-ledger-0f2cad4cab7ef99e1ad33be34ea813213da7288d.tar.bz2 fork-ledger-0f2cad4cab7ef99e1ad33be34ea813213da7288d.zip |
Got most of the commodity tests working, save multiplication and division.
Diffstat (limited to 'amount.cc')
-rw-r--r-- | amount.cc | 132 |
1 files changed, 69 insertions, 63 deletions
@@ -505,6 +505,12 @@ void amount_t::_clear() amount_t& amount_t::operator+=(const amount_t& amt) { + if (commodity() != amt.commodity()) + throw new amount_error + (std::string("Adding amounts with different commodities: ") + + (has_commodity() ? commodity_->qualified_symbol : "NONE") + " != " + + (amt.has_commodity() ? amt.commodity_->qualified_symbol : "NONE")); + if (! amt.quantity) return *this; @@ -515,12 +521,6 @@ amount_t& amount_t::operator+=(const amount_t& amt) _dup(); - if (commodity() != amt.commodity()) - throw new amount_error - (std::string("Adding amounts with different commodities: ") + - commodity_->qualified_symbol + " != " + - amt.commodity_->qualified_symbol); - if (quantity->prec == amt.quantity->prec) { mpz_add(MPZ(quantity), MPZ(quantity), MPZ(amt.quantity)); } @@ -539,6 +539,12 @@ amount_t& amount_t::operator+=(const amount_t& amt) amount_t& amount_t::operator-=(const amount_t& amt) { + if (commodity() != amt.commodity()) + throw new amount_error + (std::string("Subtracting amounts with different commodities: ") + + (has_commodity() ? commodity_->qualified_symbol : "NONE") + " != " + + (amt.has_commodity() ? amt.commodity_->qualified_symbol : "NONE")); + if (! amt.quantity) return *this; @@ -551,12 +557,6 @@ amount_t& amount_t::operator-=(const amount_t& amt) _dup(); - if (commodity() != amt.commodity()) - throw new amount_error - (std::string("Subtracting amounts with different commodities: ") + - commodity_->qualified_symbol + " != " + - amt.commodity_->qualified_symbol); - if (quantity->prec == amt.quantity->prec) { mpz_sub(MPZ(quantity), MPZ(quantity), MPZ(amt.quantity)); } @@ -580,12 +580,19 @@ amount_t& amount_t::operator*=(const amount_t& amt) else if (! quantity) return *this; + if (has_commodity() && amt.has_commodity() && + commodity() != amt.commodity()) + throw new amount_error + (std::string("Multiplying amounts with different commodities: ") + + (has_commodity() ? commodity_->qualified_symbol : "NONE") + " != " + + (amt.has_commodity() ? amt.commodity_->qualified_symbol : "NONE")); + _dup(); mpz_mul(MPZ(quantity), MPZ(quantity), MPZ(amt.quantity)); quantity->prec += amt.quantity->prec; - if (has_commodity()) { + if (has_commodity() && ! (quantity->flags & BIGINT_KEEP_PREC)) { unsigned int comm_prec = commodity().precision(); if (quantity->prec > comm_prec + 6U) { mpz_round(MPZ(quantity), MPZ(quantity), quantity->prec, comm_prec + 6U); @@ -603,6 +610,13 @@ amount_t& amount_t::operator/=(const amount_t& amt) else if (! quantity) return *this; + if (has_commodity() && amt.has_commodity() && + commodity() != amt.commodity()) + throw new amount_error + (std::string("Dividing amounts with different commodities: ") + + (has_commodity() ? commodity_->qualified_symbol : "NONE") + " != " + + (amt.has_commodity() ? amt.commodity_->qualified_symbol : "NONE")); + _dup(); // Increase the value's precision, to capture fractional parts after @@ -612,7 +626,7 @@ amount_t& amount_t::operator/=(const amount_t& amt) mpz_tdiv_q(MPZ(quantity), MPZ(quantity), MPZ(amt.quantity)); quantity->prec += quantity->prec + 6U; - if (has_commodity()) { + if (has_commodity() && ! (quantity->flags & BIGINT_KEEP_PREC)) { unsigned int comm_prec = commodity().precision(); if (quantity->prec > comm_prec + 6U) { mpz_round(MPZ(quantity), MPZ(quantity), quantity->prec, comm_prec + 6U); @@ -877,16 +891,11 @@ void amount_t::print_quantity(std::ostream& out) const void amount_t::print(std::ostream& _out, bool omit_commodity) const { - if (! quantity) { - _out << "0"; - return; - } - amount_t base(*this); if (! amount_t::keep_base && commodity().larger()) { amount_t last(*this); while (last.commodity().larger()) { - last /= *last.commodity().larger(); + last /= last.commodity().larger()->number(); last.commodity_ = last.commodity().larger()->commodity_; if (::abs(last) < 1) break; @@ -910,49 +919,46 @@ void amount_t::print(std::ostream& _out, bool omit_commodity) const // outputting it. NOTE: `rquotient' is used here as a temp variable! commodity_t& comm(base.commodity()); - unsigned char precision; - - if (! comm || base.quantity->flags & BIGINT_KEEP_PREC) { - mpz_ui_pow_ui(divisor, 10, base.quantity->prec); - mpz_tdiv_qr(quotient, remainder, MPZ(base.quantity), divisor); - precision = base.quantity->prec; - } - else if (comm.precision() < base.quantity->prec) { - mpz_round(rquotient, MPZ(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, MPZ(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, MPZ(base.quantity), divisor); - precision = base.quantity->prec; - } - else { - mpz_set(quotient, MPZ(base.quantity)); - mpz_set_ui(remainder, 0); - precision = 0; - } + unsigned char precision = 0; - if (mpz_sgn(quotient) < 0 || mpz_sgn(remainder) < 0) { - negative = true; + if (quantity) { + if (! comm || base.quantity->flags & BIGINT_KEEP_PREC) { + mpz_ui_pow_ui(divisor, 10, base.quantity->prec); + mpz_tdiv_qr(quotient, remainder, MPZ(base.quantity), divisor); + precision = base.quantity->prec; + } + else if (comm.precision() < base.quantity->prec) { + mpz_round(rquotient, MPZ(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, MPZ(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, MPZ(base.quantity), divisor); + precision = base.quantity->prec; + } + else { + mpz_set(quotient, MPZ(base.quantity)); + mpz_set_ui(remainder, 0); + precision = 0; + } - mpz_abs(quotient, quotient); - mpz_abs(remainder, remainder); - } - mpz_set(rquotient, remainder); + if (mpz_sgn(quotient) < 0 || mpz_sgn(remainder) < 0) { + negative = true; - if (mpz_sgn(quotient) == 0 && mpz_sgn(rquotient) == 0) { - _out << "0"; - return; + mpz_abs(quotient, quotient); + mpz_abs(remainder, remainder); + } + mpz_set(rquotient, remainder); } if (! omit_commodity && ! (comm.flags() & COMMODITY_STYLE_SUFFIXED)) { @@ -1337,7 +1343,7 @@ void amount_t::parse(std::istream& in, unsigned char flags) void amount_t::reduce() { while (commodity_ && commodity().smaller()) { - *this *= *commodity().smaller(); + *this *= commodity().smaller()->number(); commodity_ = commodity().smaller()->commodity_; } } @@ -1350,7 +1356,7 @@ void parse_conversion(const std::string& larger_str, larger.parse(larger_str.c_str(), AMOUNT_PARSE_NO_REDUCE); smaller.parse(smaller_str.c_str(), AMOUNT_PARSE_NO_REDUCE); - larger *= smaller; + larger *= smaller.number(); if (larger.commodity()) { larger.commodity().set_smaller(smaller); @@ -1614,7 +1620,7 @@ amount_t amount_t::price() const { if (commodity_ && commodity_->annotated) { amount_t t(((annotated_commodity_t *)commodity_)->price); - t *= *this; + t *= number(); DEBUG_PRINT("amounts.commodities", "Returning price of " << *this << " = " << t); return t; |