Bug 634 and 488, Corrected behavior of floor, and added ceiling

This is only a partial fix for 634, since rounding is not fixed.
This commit is contained in:
Craig Earls 2012-10-25 22:28:26 -07:00
parent 4b261f99bc
commit b044a74bd3
7 changed files with 78 additions and 3 deletions

View file

@ -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);
}
mpq_set_str(MP(quantity), out.str().c_str(), 10);
void amount_t::in_place_ceiling()
{
if (! quantity)
throw_(amount_error, _("Cannot ceiling 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);
}
void amount_t::in_place_unround()

View file

@ -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 {

View file

@ -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();

View file

@ -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':

View file

@ -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);

View file

@ -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()) {

View file

@ -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();