diff options
author | Craig Earls <enderw88@gmail.com> | 2012-10-25 22:28:26 -0700 |
---|---|---|
committer | Craig Earls <enderw88@gmail.com> | 2012-10-25 22:28:26 -0700 |
commit | b044a74bd34afdc27baf6241fe398690ff5e043a (patch) | |
tree | 6cf2168e51611a86e04d834b2a507322a8a8fe04 | |
parent | 4b261f99bc56853b3468a8a1bb5b4af39ed67af5 (diff) | |
download | fork-ledger-b044a74bd34afdc27baf6241fe398690ff5e043a.tar.gz fork-ledger-b044a74bd34afdc27baf6241fe398690ff5e043a.tar.bz2 fork-ledger-b044a74bd34afdc27baf6241fe398690ff5e043a.zip |
Bug 634 and 488, Corrected behavior of floor, and added ceiling
This is only a partial fix for 634, since rounding is not fixed.
-rw-r--r-- | src/amount.cc | 23 | ||||
-rw-r--r-- | src/amount.h | 9 | ||||
-rw-r--r-- | src/balance.h | 11 | ||||
-rw-r--r-- | src/report.cc | 7 | ||||
-rw-r--r-- | src/report.h | 1 | ||||
-rw-r--r-- | src/value.cc | 23 | ||||
-rw-r--r-- | src/value.h | 7 |
7 files changed, 78 insertions, 3 deletions
diff --git a/src/amount.cc b/src/amount.cc index 6ecb3558..4e658212 100644 --- a/src/amount.cc +++ b/src/amount.cc @@ -670,10 +670,27 @@ void amount_t::in_place_floor() _dup(); - std::ostringstream out; - stream_out_mpq(out, MP(quantity), precision_t(0), -1, GMP_RNDZ); + mpz_t quot; + mpz_init(quot); + mpz_fdiv_q(quot, mpq_numref(MP(quantity)), mpq_denref(MP(quantity))); + mpq_clear(MP(quantity)); + mpq_init(MP(quantity)); + mpq_set_num(MP(quantity), quot); +} + +void amount_t::in_place_ceiling() +{ + if (! quantity) + throw_(amount_error, _("Cannot ceiling an uninitialized amount")); - mpq_set_str(MP(quantity), out.str().c_str(), 10); + _dup(); + + mpz_t quot; + mpz_init(quot); + mpz_cdiv_q(quot, mpq_numref(MP(quantity)), mpq_denref(MP(quantity))); + mpq_clear(MP(quantity)); + mpq_init(MP(quantity)); + mpq_set_num(MP(quantity), quot); } void amount_t::in_place_unround() diff --git a/src/amount.h b/src/amount.h index 49027bb7..1b7d2101 100644 --- a/src/amount.h +++ b/src/amount.h @@ -364,6 +364,15 @@ public: } void in_place_floor(); + /** Yields an amount which has lost all of its extra precision, beyond what + the display precision of the commodity would have printed. */ + amount_t ceilinged() const { + amount_t temp(*this); + temp.in_place_ceiling(); + return temp; + } + void in_place_ceiling(); + /** Yields an amount whose display precision is never truncated, even though its commodity normally displays only rounded values. */ amount_t unrounded() const { diff --git a/src/balance.h b/src/balance.h index 230a4e2c..9635742d 100644 --- a/src/balance.h +++ b/src/balance.h @@ -345,6 +345,17 @@ public: pair.second.in_place_floor(); } + balance_t ceilinged() const { + balance_t temp(*this); + temp.in_place_ceiling(); + return temp; + } + void in_place_ceiling() { + foreach (amounts_map::value_type& pair, amounts) + pair.second.in_place_ceiling(); + } + + balance_t unrounded() const { balance_t temp(*this); temp.in_place_unround(); diff --git a/src/report.cc b/src/report.cc index 662386a4..dc5a0704 100644 --- a/src/report.cc +++ b/src/report.cc @@ -681,6 +681,11 @@ value_t report_t::fn_floor(call_scope_t& args) return args[0].floored(); } +value_t report_t::fn_ceiling(call_scope_t& args) +{ + return args[0].ceilinged(); +} + value_t report_t::fn_round(call_scope_t& args) { return args[0].rounded(); @@ -1335,6 +1340,8 @@ expr_t::ptr_op_t report_t::lookup(const symbol_t::kind_t kind, return WRAP_FUNCTOR(fn_cyan); else if (is_eq(p, "commodity")) return MAKE_FUNCTOR(report_t::fn_commodity); + else if (is_eq(p, "ceiling")) + return MAKE_FUNCTOR(report_t::fn_ceiling); break; case 'd': diff --git a/src/report.h b/src/report.h index 4a02843e..2eac61fe 100644 --- a/src/report.h +++ b/src/report.h @@ -174,6 +174,7 @@ public: value_t fn_unrounded(call_scope_t& scope); value_t fn_truncated(call_scope_t& scope); value_t fn_floor(call_scope_t& scope); + value_t fn_ceiling(call_scope_t& scope); value_t fn_round(call_scope_t& scope); value_t fn_unround(call_scope_t& scope); value_t fn_abs(call_scope_t& scope); diff --git a/src/value.cc b/src/value.cc index 1921d5a3..c57cff78 100644 --- a/src/value.cc +++ b/src/value.cc @@ -1658,6 +1658,29 @@ void value_t::in_place_floor() throw_(value_error, _f("Cannot floor %1%") % label()); } +void value_t::in_place_ceiling() +{ + switch (type()) { + case INTEGER: + return; + case AMOUNT: + as_amount_lval().in_place_ceiling(); + return; + case BALANCE: + as_balance_lval().in_place_ceiling(); + return; + case SEQUENCE: + foreach (value_t& value, as_sequence_lval()) + value.in_place_ceiling(); + return; + default: + break; + } + + add_error_context(_f("While ceiling %1%:") % *this); + throw_(value_error, _f("Cannot ceiling %1%") % label()); +} + void value_t::in_place_unround() { switch (type()) { diff --git a/src/value.h b/src/value.h index ee3d414d..249f3d7f 100644 --- a/src/value.h +++ b/src/value.h @@ -457,6 +457,13 @@ public: } void in_place_floor(); + value_t ceilinged() const { + value_t temp(*this); + temp.in_place_ceiling(); + return temp; + } + void in_place_ceiling(); + value_t unrounded() const { value_t temp(*this); temp.in_place_unround(); |