diff options
author | John Wiegley <johnw@newartisans.com> | 2006-03-04 17:13:45 +0000 |
---|---|---|
committer | John Wiegley <johnw@newartisans.com> | 2008-04-13 02:41:29 -0400 |
commit | 7acc1306d985fb532ee429121fac0e1692285503 (patch) | |
tree | 6ff877c57daf4fdeb048147dad6f17811cdeca41 /value.cc | |
parent | 11498f48070a9e96826afb316c684fed8c59397b (diff) | |
download | fork-ledger-7acc1306d985fb532ee429121fac0e1692285503.tar.gz fork-ledger-7acc1306d985fb532ee429121fac0e1692285503.tar.bz2 fork-ledger-7acc1306d985fb532ee429121fac0e1692285503.zip |
*** empty log message ***
Diffstat (limited to 'value.cc')
-rw-r--r-- | value.cc | 777 |
1 files changed, 535 insertions, 242 deletions
@@ -1,4 +1,5 @@ #include "value.h" +#include "debug.h" namespace ledger { @@ -19,6 +20,34 @@ void value_t::destroy() } } +void value_t::simplify() +{ + if (realzero()) { + DEBUG_PRINT("amounts.values.simplify", "Zeroing type " << type); + *this = 0L; + return; + } + + if (type == BALANCE_PAIR && + (! ((balance_pair_t *) data)->cost || + ((balance_pair_t *) data)->cost->realzero())) { + DEBUG_PRINT("amounts.values.simplify", "Reducing balance pair to balance"); + cast(BALANCE); + } + + if (type == BALANCE && + ((balance_t *) data)->amounts.size() == 1) { + DEBUG_PRINT("amounts.values.simplify", "Reducing balance to amount"); + cast(AMOUNT); + } + + if (type == AMOUNT && + ! ((amount_t *) data)->commodity()) { + DEBUG_PRINT("amounts.values.simplify", "Reducing amount to integer"); + cast(INTEGER); + } +} + value_t& value_t::operator=(const value_t& value) { if (this == &value) @@ -57,253 +86,493 @@ value_t& value_t::operator=(const value_t& value) return *this; } -#define DEF_VALUE_ADDSUB_OP(OP) \ -value_t& value_t::operator OP(const value_t& value) \ -{ \ - switch (type) { \ - case BOOLEAN: \ - case INTEGER: \ - cast(INTEGER); \ - switch (value.type) { \ - case BOOLEAN: \ - *((long *) data) OP (*((bool *) value.data) ? 1L : 0L); \ - break; \ - case INTEGER: \ - *((long *) data) OP *((long *) value.data); \ - break; \ - case AMOUNT: \ - cast(AMOUNT); \ - *((amount_t *) data) OP *((amount_t *) value.data); \ - break; \ - case BALANCE: \ - cast(BALANCE); \ - *((balance_t *) data) OP *((balance_t *) value.data); \ - break; \ - case BALANCE_PAIR: \ - cast(BALANCE_PAIR); \ - *((balance_pair_t *) data) OP *((balance_pair_t *) value.data); \ - break; \ - default: \ - assert(0); \ - break; \ - } \ - break; \ - \ - case AMOUNT: \ - switch (value.type) { \ - case BOOLEAN: \ - if (*((bool *) value.data) && \ - ((amount_t *) data)->commodity()) { \ - cast(BALANCE); \ - return *this OP value; \ - } \ - *((amount_t *) data) OP (*((bool *) value.data) ? 1L : 0L); \ - break; \ - \ - case INTEGER: \ - if (*((long *) value.data) && \ - ((amount_t *) data)->commodity()) { \ - cast(BALANCE); \ - return *this OP value; \ - } \ - *((amount_t *) data) OP *((long *) value.data); \ - break; \ - \ - case AMOUNT: \ - if (((amount_t *) data)->commodity() != \ - ((amount_t *) value.data)->commodity()) { \ - cast(BALANCE); \ - return *this OP value; \ - } \ - *((amount_t *) data) OP *((amount_t *) value.data); \ - break; \ - \ - case BALANCE: \ - cast(BALANCE); \ - *((balance_t *) data) OP *((balance_t *) value.data); \ - break; \ - \ - case BALANCE_PAIR: \ - cast(BALANCE_PAIR); \ - *((balance_pair_t *) data) OP *((balance_pair_t *) value.data); \ - break; \ - \ - default: \ - assert(0); \ - break; \ - } \ - break; \ - \ - case BALANCE: \ - switch (value.type) { \ - case BOOLEAN: \ - *((balance_t *) data) OP (*((bool *) value.data) ? 1L : 0L); \ - break; \ - case INTEGER: \ - *((balance_t *) data) OP *((long *) value.data); \ - break; \ - case AMOUNT: \ - *((balance_t *) data) OP *((amount_t *) value.data); \ - break; \ - case BALANCE: \ - *((balance_t *) data) OP *((balance_t *) value.data); \ - break; \ - case BALANCE_PAIR: \ - cast(BALANCE_PAIR); \ - *((balance_pair_t *) data) OP *((balance_pair_t *) value.data); \ - break; \ - default: \ - assert(0); \ - break; \ - } \ - break; \ - \ - case BALANCE_PAIR: \ - switch (value.type) { \ - case BOOLEAN: \ - *((balance_pair_t *) data) OP (*((bool *) value.data) ? 1L : 0L); \ - break; \ - case INTEGER: \ - *((balance_pair_t *) data) OP *((long *) value.data); \ - break; \ - case AMOUNT: \ - *((balance_pair_t *) data) OP *((amount_t *) value.data); \ - break; \ - case BALANCE: \ - *((balance_pair_t *) data) OP *((balance_t *) value.data); \ - break; \ - case BALANCE_PAIR: \ - *((balance_pair_t *) data) OP *((balance_pair_t *) value.data); \ - break; \ - default: \ - assert(0); \ - break; \ - } \ - break; \ - \ - default: \ - assert(0); \ - break; \ - } \ - return *this; \ +value_t& value_t::operator+=(const value_t& value) +{ + switch (type) { + case BOOLEAN: + case INTEGER: + cast(INTEGER); + switch (value.type) { + case BOOLEAN: + *((long *) data) += (*((bool *) value.data) ? 1L : 0L); + break; + case INTEGER: + *((long *) data) += *((long *) value.data); + break; + case AMOUNT: + cast(AMOUNT); + *((amount_t *) data) += *((amount_t *) value.data); + break; + case BALANCE: + cast(BALANCE); + *((balance_t *) data) += *((balance_t *) value.data); + break; + case BALANCE_PAIR: + cast(BALANCE_PAIR); + *((balance_pair_t *) data) += *((balance_pair_t *) value.data); + break; + default: + assert(0); + break; + } + break; + + case AMOUNT: + switch (value.type) { + case BOOLEAN: + if (*((bool *) value.data) && + ((amount_t *) data)->commodity()) { + cast(BALANCE); + return *this += value; + } + *((amount_t *) data) += (*((bool *) value.data) ? 1L : 0L); + break; + + case INTEGER: + if (*((long *) value.data) && + ((amount_t *) data)->commodity()) { + cast(BALANCE); + return *this += value; + } + *((amount_t *) data) += *((long *) value.data); + break; + + case AMOUNT: + if (((amount_t *) data)->commodity() != + ((amount_t *) value.data)->commodity()) { + cast(BALANCE); + return *this += value; + } + *((amount_t *) data) += *((amount_t *) value.data); + break; + + case BALANCE: + cast(BALANCE); + *((balance_t *) data) += *((balance_t *) value.data); + break; + + case BALANCE_PAIR: + cast(BALANCE_PAIR); + *((balance_pair_t *) data) += *((balance_pair_t *) value.data); + break; + + default: + assert(0); + break; + } + break; + + case BALANCE: + switch (value.type) { + case BOOLEAN: + *((balance_t *) data) += (*((bool *) value.data) ? 1L : 0L); + break; + case INTEGER: + *((balance_t *) data) += *((long *) value.data); + break; + case AMOUNT: + *((balance_t *) data) += *((amount_t *) value.data); + break; + case BALANCE: + *((balance_t *) data) += *((balance_t *) value.data); + break; + case BALANCE_PAIR: + cast(BALANCE_PAIR); + *((balance_pair_t *) data) += *((balance_pair_t *) value.data); + break; + default: + assert(0); + break; + } + break; + + case BALANCE_PAIR: + switch (value.type) { + case BOOLEAN: + *((balance_pair_t *) data) += (*((bool *) value.data) ? 1L : 0L); + break; + case INTEGER: + *((balance_pair_t *) data) += *((long *) value.data); + break; + case AMOUNT: + *((balance_pair_t *) data) += *((amount_t *) value.data); + break; + case BALANCE: + *((balance_pair_t *) data) += *((balance_t *) value.data); + break; + case BALANCE_PAIR: + *((balance_pair_t *) data) += *((balance_pair_t *) value.data); + break; + default: + assert(0); + break; + } + break; + + default: + assert(0); + break; + } + return *this; } -DEF_VALUE_ADDSUB_OP(+=) -DEF_VALUE_ADDSUB_OP(-=) +value_t& value_t::operator-=(const value_t& value) +{ + switch (type) { + case BOOLEAN: + case INTEGER: + cast(INTEGER); + switch (value.type) { + case BOOLEAN: + *((long *) data) -= (*((bool *) value.data) ? 1L : 0L); + break; + case INTEGER: + *((long *) data) -= *((long *) value.data); + break; + case AMOUNT: + cast(AMOUNT); + *((amount_t *) data) -= *((amount_t *) value.data); + break; + case BALANCE: + cast(BALANCE); + *((balance_t *) data) -= *((balance_t *) value.data); + break; + case BALANCE_PAIR: + cast(BALANCE_PAIR); + *((balance_pair_t *) data) -= *((balance_pair_t *) value.data); + break; + default: + assert(0); + break; + } + break; -#define DEF_VALUE_MULDIV_OP(OP) \ -value_t& value_t::operator OP(const value_t& value) \ -{ \ - switch (type) { \ - case BOOLEAN: \ - case INTEGER: \ - cast(INTEGER); \ - switch (value.type) { \ - case BOOLEAN: \ - *((long *) data) OP (*((bool *) value.data) ? 1L : 0L); \ - break; \ - case INTEGER: \ - *((long *) data) OP *((long *) value.data); \ - break; \ - case AMOUNT: \ - cast(AMOUNT); \ - *((amount_t *) data) OP *((amount_t *) value.data); \ - break; \ - case BALANCE: \ - cast(BALANCE); \ - *((balance_t *) data) OP *((balance_t *) value.data); \ - break; \ - case BALANCE_PAIR: \ - cast(BALANCE_PAIR); \ - *((balance_pair_t *) data) OP *((balance_pair_t *) value.data); \ - break; \ - default: \ - assert(0); \ - break; \ - } \ - break; \ - \ - case AMOUNT: \ - switch (value.type) { \ - case BOOLEAN: \ - *((amount_t *) data) OP (*((bool *) value.data) ? 1L : 0L); \ - break; \ - case INTEGER: \ - *((amount_t *) data) OP *((long *) value.data); \ - break; \ - case AMOUNT: \ - *((amount_t *) data) OP *((amount_t *) value.data); \ - break; \ - case BALANCE: \ - cast(BALANCE); \ - *((balance_t *) data) OP *((balance_t *) value.data); \ - break; \ - case BALANCE_PAIR: \ - cast(BALANCE_PAIR); \ - *((balance_pair_t *) data) OP *((balance_pair_t *) value.data); \ - break; \ - default: \ - assert(0); \ - break; \ - } \ - break; \ - \ - case BALANCE: \ - switch (value.type) { \ - case BOOLEAN: \ - *((balance_t *) data) OP (*((bool *) value.data) ? 1L : 0L); \ - break; \ - case INTEGER: \ - *((balance_t *) data) OP *((long *) value.data); \ - break; \ - case AMOUNT: \ - *((balance_t *) data) OP *((amount_t *) value.data); \ - break; \ - case BALANCE: \ - *((balance_t *) data) OP *((balance_t *) value.data); \ - break; \ - case BALANCE_PAIR: \ - cast(BALANCE_PAIR); \ - *((balance_pair_t *) data) OP *((balance_pair_t *) value.data); \ - break; \ - default: \ - assert(0); \ - break; \ - } \ - break; \ - \ - case BALANCE_PAIR: \ - switch (value.type) { \ - case BOOLEAN: \ - *((balance_pair_t *) data) OP (*((bool *) value.data) ? 1L : 0L); \ - break; \ - case INTEGER: \ - *((balance_pair_t *) data) OP *((long *) value.data); \ - break; \ - case AMOUNT: \ - *((balance_pair_t *) data) OP *((amount_t *) value.data); \ - break; \ - case BALANCE: \ - *((balance_pair_t *) data) OP *((balance_t *) value.data); \ - break; \ - case BALANCE_PAIR: \ - *((balance_pair_t *) data) OP *((balance_pair_t *) value.data); \ - break; \ - default: \ - assert(0); \ - break; \ - } \ - break; \ - \ - default: \ - assert(0); \ - break; \ - } \ - return *this; \ + case AMOUNT: + switch (value.type) { + case BOOLEAN: + if (*((bool *) value.data) && + ((amount_t *) data)->commodity()) { + cast(BALANCE); + return *this -= value; + } + *((amount_t *) data) -= (*((bool *) value.data) ? 1L : 0L); + break; + + case INTEGER: + if (*((long *) value.data) && + ((amount_t *) data)->commodity()) { + cast(BALANCE); + return *this -= value; + } + *((amount_t *) data) -= *((long *) value.data); + break; + + case AMOUNT: + if (((amount_t *) data)->commodity() != + ((amount_t *) value.data)->commodity()) { + cast(BALANCE); + return *this -= value; + } + *((amount_t *) data) -= *((amount_t *) value.data); + break; + + case BALANCE: + cast(BALANCE); + *((balance_t *) data) -= *((balance_t *) value.data); + break; + + case BALANCE_PAIR: + cast(BALANCE_PAIR); + *((balance_pair_t *) data) -= *((balance_pair_t *) value.data); + break; + + default: + assert(0); + break; + } + break; + + case BALANCE: + switch (value.type) { + case BOOLEAN: + *((balance_t *) data) -= (*((bool *) value.data) ? 1L : 0L); + break; + case INTEGER: + *((balance_t *) data) -= *((long *) value.data); + break; + case AMOUNT: + *((balance_t *) data) -= *((amount_t *) value.data); + break; + case BALANCE: + *((balance_t *) data) -= *((balance_t *) value.data); + break; + case BALANCE_PAIR: + cast(BALANCE_PAIR); + *((balance_pair_t *) data) -= *((balance_pair_t *) value.data); + break; + default: + assert(0); + break; + } + break; + + case BALANCE_PAIR: + switch (value.type) { + case BOOLEAN: + *((balance_pair_t *) data) -= (*((bool *) value.data) ? 1L : 0L); + break; + case INTEGER: + *((balance_pair_t *) data) -= *((long *) value.data); + break; + case AMOUNT: + *((balance_pair_t *) data) -= *((amount_t *) value.data); + break; + case BALANCE: + *((balance_pair_t *) data) -= *((balance_t *) value.data); + break; + case BALANCE_PAIR: + *((balance_pair_t *) data) -= *((balance_pair_t *) value.data); + break; + default: + assert(0); + break; + } + break; + + default: + assert(0); + break; + } + + simplify(); + + return *this; } -DEF_VALUE_MULDIV_OP(*=) -DEF_VALUE_MULDIV_OP(/=) +value_t& value_t::operator*=(const value_t& value) +{ + if (value.realzero()) { + *this = 0L; + return *this; + } + + switch (type) { + case BOOLEAN: + case INTEGER: + cast(INTEGER); + switch (value.type) { + case BOOLEAN: + *((long *) data) *= (*((bool *) value.data) ? 1L : 0L); + break; + case INTEGER: + *((long *) data) *= *((long *) value.data); + break; + case AMOUNT: + cast(AMOUNT); + *((amount_t *) data) *= *((amount_t *) value.data); + break; + case BALANCE: + cast(BALANCE); + *((balance_t *) data) *= *((balance_t *) value.data); + break; + case BALANCE_PAIR: + cast(BALANCE_PAIR); + *((balance_pair_t *) data) *= *((balance_pair_t *) value.data); + break; + default: + assert(0); + break; + } + break; + + case AMOUNT: + switch (value.type) { + case BOOLEAN: + *((amount_t *) data) *= (*((bool *) value.data) ? 1L : 0L); + break; + case INTEGER: + *((amount_t *) data) *= *((long *) value.data); + break; + case AMOUNT: + *((amount_t *) data) *= *((amount_t *) value.data); + break; + case BALANCE: + cast(BALANCE); + *((balance_t *) data) *= *((balance_t *) value.data); + break; + case BALANCE_PAIR: + cast(BALANCE_PAIR); + *((balance_pair_t *) data) *= *((balance_pair_t *) value.data); + break; + default: + assert(0); + break; + } + break; + + case BALANCE: + switch (value.type) { + case BOOLEAN: + *((balance_t *) data) *= (*((bool *) value.data) ? 1L : 0L); + break; + case INTEGER: + *((balance_t *) data) *= *((long *) value.data); + break; + case AMOUNT: + *((balance_t *) data) *= *((amount_t *) value.data); + break; + case BALANCE: + *((balance_t *) data) *= *((balance_t *) value.data); + break; + case BALANCE_PAIR: + cast(BALANCE_PAIR); + *((balance_pair_t *) data) *= *((balance_pair_t *) value.data); + break; + default: + assert(0); + break; + } + break; + + case BALANCE_PAIR: + switch (value.type) { + case BOOLEAN: + *((balance_pair_t *) data) *= (*((bool *) value.data) ? 1L : 0L); + break; + case INTEGER: + *((balance_pair_t *) data) *= *((long *) value.data); + break; + case AMOUNT: + *((balance_pair_t *) data) *= *((amount_t *) value.data); + break; + case BALANCE: + *((balance_pair_t *) data) *= *((balance_t *) value.data); + break; + case BALANCE_PAIR: + *((balance_pair_t *) data) *= *((balance_pair_t *) value.data); + break; + default: + assert(0); + break; + } + break; + + default: + assert(0); + break; + } + return *this; +} + +value_t& value_t::operator/=(const value_t& value) +{ + switch (type) { + case BOOLEAN: + case INTEGER: + cast(INTEGER); + switch (value.type) { + case BOOLEAN: + *((long *) data) /= (*((bool *) value.data) ? 1L : 0L); + break; + case INTEGER: + *((long *) data) /= *((long *) value.data); + break; + case AMOUNT: + cast(AMOUNT); + *((amount_t *) data) /= *((amount_t *) value.data); + break; + case BALANCE: + cast(BALANCE); + *((balance_t *) data) /= *((balance_t *) value.data); + break; + case BALANCE_PAIR: + cast(BALANCE_PAIR); + *((balance_pair_t *) data) /= *((balance_pair_t *) value.data); + break; + default: + assert(0); + break; + } + break; + + case AMOUNT: + switch (value.type) { + case BOOLEAN: + *((amount_t *) data) /= (*((bool *) value.data) ? 1L : 0L); + break; + case INTEGER: + *((amount_t *) data) /= *((long *) value.data); + break; + case AMOUNT: + *((amount_t *) data) /= *((amount_t *) value.data); + break; + case BALANCE: + cast(BALANCE); + *((balance_t *) data) /= *((balance_t *) value.data); + break; + case BALANCE_PAIR: + cast(BALANCE_PAIR); + *((balance_pair_t *) data) /= *((balance_pair_t *) value.data); + break; + default: + assert(0); + break; + } + break; + + case BALANCE: + switch (value.type) { + case BOOLEAN: + *((balance_t *) data) /= (*((bool *) value.data) ? 1L : 0L); + break; + case INTEGER: + *((balance_t *) data) /= *((long *) value.data); + break; + case AMOUNT: + *((balance_t *) data) /= *((amount_t *) value.data); + break; + case BALANCE: + *((balance_t *) data) /= *((balance_t *) value.data); + break; + case BALANCE_PAIR: + cast(BALANCE_PAIR); + *((balance_pair_t *) data) /= *((balance_pair_t *) value.data); + break; + default: + assert(0); + break; + } + break; + + case BALANCE_PAIR: + switch (value.type) { + case BOOLEAN: + *((balance_pair_t *) data) /= (*((bool *) value.data) ? 1L : 0L); + break; + case INTEGER: + *((balance_pair_t *) data) /= *((long *) value.data); + break; + case AMOUNT: + *((balance_pair_t *) data) /= *((amount_t *) value.data); + break; + case BALANCE: + *((balance_pair_t *) data) /= *((balance_t *) value.data); + break; + case BALANCE_PAIR: + *((balance_pair_t *) data) /= *((balance_pair_t *) value.data); + break; + default: + assert(0); + break; + } + break; + + default: + assert(0); + break; + } + return *this; +} #define DEF_VALUE_CMP_OP(OP) \ bool value_t::operator OP(const value_t& value) \ @@ -747,6 +1016,30 @@ value_t value_t::price() const return value_t(); } +value_t value_t::date() const +{ + switch (type) { + case BOOLEAN: + case INTEGER: + return *this; + + case AMOUNT: + return ((amount_t *) data)->date(); + + case BALANCE: + return (long)((balance_t *) data)->date(); + + case BALANCE_PAIR: + return (long)((balance_pair_t *) data)->quantity.date(); + + default: + assert(0); + break; + } + assert(0); + return value_t(); +} + value_t value_t::reduce(const bool keep_price, const bool keep_date, const bool keep_tag) const { |