diff options
author | Craig Earls <enderw88@gmail.com> | 2013-01-30 15:35:31 -0700 |
---|---|---|
committer | Craig Earls <enderw88@gmail.com> | 2013-01-30 15:35:31 -0700 |
commit | 0df13661686dfec66aa0d5a8dd88920e1e104fbc (patch) | |
tree | cbf9270fc8fe85d0ae67c1c1f3ab8d42296c232b /src | |
parent | 383c341d885e1a69fc63aca2ae7db4a2ff5ff1a8 (diff) | |
download | fork-ledger-0df13661686dfec66aa0d5a8dd88920e1e104fbc.tar.gz fork-ledger-0df13661686dfec66aa0d5a8dd88920e1e104fbc.tar.bz2 fork-ledger-0df13661686dfec66aa0d5a8dd88920e1e104fbc.zip |
Bug 634 Added roundto function, optimized floor and ceiling
Fixes Bug634 by adding roundto(amount, places).
Diffstat (limited to 'src')
-rw-r--r-- | src/amount.cc | 29 | ||||
-rw-r--r-- | src/amount.h | 7 | ||||
-rw-r--r-- | src/balance.h | 11 | ||||
-rw-r--r-- | src/report.cc | 8 | ||||
-rw-r--r-- | src/report.h | 1 | ||||
-rw-r--r-- | src/value.cc | 21 | ||||
-rw-r--r-- | src/value.h | 7 |
7 files changed, 70 insertions, 14 deletions
diff --git a/src/amount.cc b/src/amount.cc index ee03827e..51e69290 100644 --- a/src/amount.cc +++ b/src/amount.cc @@ -30,6 +30,7 @@ */ #include <system.hh> +#include <math.h> #include "amount.h" #include "commodity.h" @@ -672,31 +673,31 @@ void amount_t::in_place_truncate() void amount_t::in_place_floor() { if (! quantity) - throw_(amount_error, _("Cannot floor an uninitialized amount")); + throw_(amount_error, _("Cannot compute floor on an uninitialized amount")); _dup(); - 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); + mpz_fdiv_q(temp, mpq_numref(MP(quantity)), mpq_denref(MP(quantity))); + mpq_set_z(MP(quantity), temp); } void amount_t::in_place_ceiling() { if (! quantity) - throw_(amount_error, _("Cannot ceiling an uninitialized amount")); + throw_(amount_error, _("Cannot compute ceiling on an uninitialized amount")); _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); + mpz_cdiv_q(temp, mpq_numref(MP(quantity)), mpq_denref(MP(quantity))); + mpq_set_z(MP(quantity), temp); +} + +void amount_t::in_place_roundto(int places) +{ + if (! quantity) + throw_(amount_error, _("Cannot round an uninitialized amount")); + double x=ceil(mpq_get_d(MP(quantity))*pow(10, places) - 0.49999999) / pow(10, places); + mpq_set_d(MP(quantity), x); } void amount_t::in_place_unround() diff --git a/src/amount.h b/src/amount.h index 1b7d2101..5fc2ad2e 100644 --- a/src/amount.h +++ b/src/amount.h @@ -346,6 +346,13 @@ public: } void in_place_round(); + amount_t roundto(int places) const { + amount_t temp(*this); + temp.in_place_round(); + return temp; + } + void in_place_roundto(int places); + /** Yields an amount which has lost all of its extra precision, beyond what the display precision of the commodity would have printed. */ amount_t truncated() const { diff --git a/src/balance.h b/src/balance.h index 9635742d..f822e353 100644 --- a/src/balance.h +++ b/src/balance.h @@ -325,6 +325,17 @@ public: pair.second.in_place_round(); } + balance_t roundto(int places) const { + balance_t temp(*this); + temp.in_place_roundto(places); + return temp; + } + + void in_place_roundto(int places) { + foreach (amounts_map::value_type& pair, amounts) + pair.second.in_place_roundto(places); + } + balance_t truncated() const { balance_t temp(*this); temp.in_place_truncate(); diff --git a/src/report.cc b/src/report.cc index 80993515..d90d22e4 100644 --- a/src/report.cc +++ b/src/report.cc @@ -691,6 +691,12 @@ value_t report_t::fn_round(call_scope_t& args) return args[0].rounded(); } +value_t report_t::fn_roundto(call_scope_t& args) +{ + if(args.has<int>(1)) + return args[0].roundto(args.get<int>(1)); +} + value_t report_t::fn_unround(call_scope_t& args) { return args[0].unrounded(); @@ -1435,6 +1441,8 @@ expr_t::ptr_op_t report_t::lookup(const symbol_t::kind_t kind, return WRAP_FUNCTOR(fn_red); else if (is_eq(p, "round")) return MAKE_FUNCTOR(report_t::fn_round); + else if (is_eq(p, "roundto")) + return MAKE_FUNCTOR(report_t::fn_roundto); break; case 's': diff --git a/src/report.h b/src/report.h index b0044f60..6533d2f1 100644 --- a/src/report.h +++ b/src/report.h @@ -176,6 +176,7 @@ public: 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_roundto(call_scope_t& scope); value_t fn_unround(call_scope_t& scope); value_t fn_abs(call_scope_t& scope); value_t fn_justify(call_scope_t& scope); diff --git a/src/value.cc b/src/value.cc index c57cff78..3df8f3c7 100644 --- a/src/value.cc +++ b/src/value.cc @@ -1612,6 +1612,27 @@ void value_t::in_place_round() throw_(value_error, _f("Cannot set rounding for %1%") % label()); } +void value_t::in_place_roundto(int places) +{ + DEBUG("amount.roundto", "=====> roundto places " << places); + switch (type()) { + case INTEGER: + return; + case AMOUNT: + as_amount_lval().in_place_roundto(places); + return; + case BALANCE: + as_balance_lval().in_place_roundto(places); + return; + case SEQUENCE: + foreach (value_t& value, as_sequence_lval()) + value.in_place_roundto(places); + return; + default: + break; + } +} + void value_t::in_place_truncate() { switch (type()) { diff --git a/src/value.h b/src/value.h index 249f3d7f..49d64ab6 100644 --- a/src/value.h +++ b/src/value.h @@ -443,6 +443,13 @@ public: } void in_place_round(); + value_t roundto(int places) const { + value_t temp(*this); + temp.in_place_roundto(places); + return temp; + } + void in_place_roundto(int places); + value_t truncated() const { value_t temp(*this); temp.in_place_truncate(); |