summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorCraig Earls <enderw88@gmail.com>2012-10-25 22:28:26 -0700
committerCraig Earls <enderw88@gmail.com>2012-10-25 22:28:26 -0700
commitb044a74bd34afdc27baf6241fe398690ff5e043a (patch)
tree6cf2168e51611a86e04d834b2a507322a8a8fe04 /src
parent4b261f99bc56853b3468a8a1bb5b4af39ed67af5 (diff)
downloadfork-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.
Diffstat (limited to 'src')
-rw-r--r--src/amount.cc23
-rw-r--r--src/amount.h9
-rw-r--r--src/balance.h11
-rw-r--r--src/report.cc7
-rw-r--r--src/report.h1
-rw-r--r--src/value.cc23
-rw-r--r--src/value.h7
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();