summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCraig Earls <enderw88@gmail.com>2013-01-30 15:35:31 -0700
committerCraig Earls <enderw88@gmail.com>2013-01-30 15:35:31 -0700
commit0df13661686dfec66aa0d5a8dd88920e1e104fbc (patch)
treecbf9270fc8fe85d0ae67c1c1f3ab8d42296c232b
parent383c341d885e1a69fc63aca2ae7db4a2ff5ff1a8 (diff)
downloadfork-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).
-rw-r--r--doc/ledger3.texi4
-rw-r--r--src/amount.cc29
-rw-r--r--src/amount.h7
-rw-r--r--src/balance.h11
-rw-r--r--src/report.cc8
-rw-r--r--src/report.h1
-rw-r--r--src/value.cc21
-rw-r--r--src/value.h7
-rw-r--r--test/regress/25A099C9.test20
9 files changed, 83 insertions, 25 deletions
diff --git a/doc/ledger3.texi b/doc/ledger3.texi
index 377d740c..ee4c990b 100644
--- a/doc/ledger3.texi
+++ b/doc/ledger3.texi
@@ -7192,6 +7192,7 @@ Useful specifying a date in plain terms. For example, you could say
@item @strong{Function} @tab @strong{Abbrev.} @tab @strong{Description}
@item @code{amount_expr } @tab @code{} @tab
@item @code{abs } @tab @code{} @tab --> U
+@item @code{ceiling } @tab @code{} @tab Returns the next integer toward +infty
@item @code{code} @tab @code{} @tab returns the transaction code, the string between the parenthesis after the date.
@item @code{commodity } @tab @code{} @tab
@item @code{display_amount } @tab @code{} @tab --> t
@@ -7199,7 +7200,7 @@ Useful specifying a date in plain terms. For example, you could say
@item @code{date } @tab @code{} @tab
@item @code{format_date } @tab @code{} @tab
@item @code{format } @tab @code{} @tab
-@item @code{floor } @tab @code{} @tab
+@item @code{floor } @tab @code{} @tab Returns the next integer toward -infty
@item @code{get_at } @tab @code{} @tab
@item @code{is_seq } @tab @code{} @tab
@item @code{justify } @tab @code{} @tab
@@ -7215,6 +7216,7 @@ Useful specifying a date in plain terms. For example, you could say
@item @code{quoted } @tab @code{} @tab
@item @code{quantity } @tab @code{} @tab
@item @code{rounded } @tab @code{} @tab
+@item @code{roundto } @tab @code{} @tab Returns value rounded to n digits. Does not affect formatting.
@item @code{scrub } @tab @code{} @tab
@item @code{strip --> S } @tab @code{} @tab
@item @code{should_bold } @tab @code{} @tab
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();
diff --git a/test/regress/25A099C9.test b/test/regress/25A099C9.test
index fb362a4b..34c92c40 100644
--- a/test/regress/25A099C9.test
+++ b/test/regress/25A099C9.test
@@ -20,24 +20,24 @@ While parsing file "$sourcepath/src/amount.h", line 121:
Error: Unexpected whitespace at beginning of line
While parsing file "$sourcepath/src/amount.h", line 132:
Error: Unexpected whitespace at beginning of line
-While parsing file "$sourcepath/src/amount.h", line 711:
+While parsing file "$sourcepath/src/amount.h", line 718:
Error: Unexpected whitespace at beginning of line
-While parsing file "$sourcepath/src/amount.h", line 741:
+While parsing file "$sourcepath/src/amount.h", line 748:
Error: Unexpected whitespace at beginning of line
-While parsing file "$sourcepath/src/amount.h", line 749:
+While parsing file "$sourcepath/src/amount.h", line 756:
Error: Unexpected whitespace at beginning of line
-While parsing file "$sourcepath/src/amount.h", line 752:
+While parsing file "$sourcepath/src/amount.h", line 759:
Error: Invalid date/time: line amount_t amoun
-While parsing file "$sourcepath/src/amount.h", line 758:
+While parsing file "$sourcepath/src/amount.h", line 765:
Error: Invalid date/time: line string amount_
-While parsing file "$sourcepath/src/amount.h", line 764:
+While parsing file "$sourcepath/src/amount.h", line 771:
Error: Invalid date/time: line string amount_
-While parsing file "$sourcepath/src/amount.h", line 770:
+While parsing file "$sourcepath/src/amount.h", line 777:
Error: Invalid date/time: line string amount_
-While parsing file "$sourcepath/src/amount.h", line 776:
-Error: Invalid date/time: line std::ostream&
While parsing file "$sourcepath/src/amount.h", line 783:
+Error: Invalid date/time: line std::ostream&
+While parsing file "$sourcepath/src/amount.h", line 790:
Error: Invalid date/time: line std::istream&
-While parsing file "$sourcepath/src/amount.h", line 789:
+While parsing file "$sourcepath/src/amount.h", line 796:
Error: Unexpected whitespace at beginning of line
end test