speed improvements; my "bal" script is cut to a third

This commit is contained in:
John Wiegley 2004-08-17 22:18:38 -04:00
parent 18ec7d0539
commit 55d58940ce
6 changed files with 1206 additions and 83 deletions

View file

@ -254,16 +254,25 @@ amount_t& amount_t::negate()
return *this;
}
// comparisons to zero
// integer comparisons
template <typename T>
static inline void parse_num(amount_t& amt, T num) {
std::string str;
{ std::ostringstream strstr(str);
strstr << num;
}
{ std::istringstream strstr(str);
amt.parse(strstr);
}
}
bool amount_t::operator<(const int num) const
{
if (num == 0) {
return quantity ? mpz_sgn(MPZ(quantity)) < 0 : false;
} else {
std::string str;
std::ostringstream strstr(str);
strstr << num;
amount_t amt(strstr.str());
amount_t amt;
parse_num(amt, num);
return *this < amt;
}
}
@ -273,10 +282,8 @@ bool amount_t::operator<=(const int num) const
if (num == 0) {
return quantity ? mpz_sgn(MPZ(quantity)) <= 0 : true;
} else {
std::string str;
std::ostringstream strstr(str);
strstr << num;
amount_t amt(strstr.str());
amount_t amt;
parse_num(amt, num);
return *this <= amt;
}
}
@ -286,10 +293,8 @@ bool amount_t::operator>(const int num) const
if (num == 0) {
return quantity ? mpz_sgn(MPZ(quantity)) > 0 : false;
} else {
std::string str;
std::ostringstream strstr(str);
strstr << num;
amount_t amt(strstr.str());
amount_t amt;
parse_num(amt, num);
return *this > amt;
}
}
@ -299,14 +304,67 @@ bool amount_t::operator>=(const int num) const
if (num == 0) {
return quantity ? mpz_sgn(MPZ(quantity)) >= 0 : true;
} else {
std::string str;
std::ostringstream strstr(str);
strstr << num;
amount_t amt(strstr.str());
amount_t amt;
parse_num(amt, num);
return *this >= amt;
}
}
bool amount_t::operator<(const unsigned int num) const
{
if (num == 0) {
return quantity ? mpz_sgn(MPZ(quantity)) < 0 : false;
} else {
amount_t amt;
parse_num(amt, num);
return *this < amt;
}
}
bool amount_t::operator<=(const unsigned int num) const
{
if (num == 0) {
return quantity ? mpz_sgn(MPZ(quantity)) <= 0 : true;
} else {
amount_t amt;
parse_num(amt, num);
return *this <= amt;
}
}
bool amount_t::operator>(const unsigned int num) const
{
if (num == 0) {
return quantity ? mpz_sgn(MPZ(quantity)) > 0 : false;
} else {
amount_t amt;
parse_num(amt, num);
return *this > amt;
}
}
bool amount_t::operator>=(const unsigned int num) const
{
if (num == 0) {
return quantity ? mpz_sgn(MPZ(quantity)) >= 0 : true;
} else {
amount_t amt;
parse_num(amt, num);
return *this >= amt;
}
}
bool amount_t::operator==(const unsigned int num) const
{
if (num == 0) {
return quantity ? mpz_sgn(MPZ(quantity)) == 0 : true;
} else {
amount_t amt;
parse_num(amt, num);
return *this == amt;
}
}
// comparisons between amounts
bool amount_t::operator<(const amount_t& amt) const
{

View file

@ -41,15 +41,10 @@ class amount_t
commodity = amt.commodity;
}
amount_t(const std::string& value) {
_init();
std::istringstream str(value);
str >> *this;
parse(value);
}
amount_t(const char * value) {
_init();
std::string valstr(value);
std::istringstream str(valstr);
str >> *this;
parse(value);
}
amount_t(const bool value);
amount_t(const int value);
@ -122,12 +117,21 @@ class amount_t
// test for non-zero (use ! for zero)
operator bool() const;
// comparisons to zero
// integer comparisons
bool operator<(const int num) const;
bool operator<=(const int num) const;
bool operator>(const int num) const;
bool operator>=(const int num) const;
bool operator<(const unsigned int num) const;
bool operator<=(const unsigned int num) const;
bool operator>(const unsigned int num) const;
bool operator>=(const unsigned int num) const;
bool operator==(const unsigned int num) const;
bool operator!=(const unsigned int num) const {
return ! (*this == num);
}
// comparisons between amounts
bool operator<(const amount_t& amt) const;
bool operator<=(const amount_t& amt) const;
@ -142,6 +146,11 @@ class amount_t
amount_t value(const std::time_t moment) const;
void abs() {
if (*this < 0)
negate();
}
operator std::string() const;
void parse(std::istream& in);

View file

@ -243,6 +243,12 @@ class balance_t
bool operator<=(const amount_t& amt) const {
return amount(amt.commodity) <= amt;
}
bool operator<(const unsigned int val) const {
return amount() < val;
}
bool operator<=(const unsigned int val) const {
return amount() <= val;
}
bool operator>(const balance_t& bal) const {
for (amounts_map::const_iterator i = bal.amounts.begin();
@ -283,6 +289,12 @@ class balance_t
bool operator>=(const amount_t& amt) const {
return amount(amt.commodity) >= amt;
}
bool operator>(const unsigned int val) const {
return amount() > val;
}
bool operator>=(const unsigned int val) const {
return amount() >= val;
}
bool operator==(const balance_t& bal) const {
amounts_map::const_iterator i, j;
@ -298,12 +310,18 @@ class balance_t
bool operator==(const amount_t& amt) const {
return amounts.size() == 1 && (*amounts.begin()).second == amt;
}
bool operator==(const unsigned int val) const {
return amount() == val;
}
bool operator!=(const balance_t& bal) const {
return ! (*this == bal);
}
bool operator!=(const amount_t& amt) const {
return ! (*this == amt);
}
bool operator!=(const unsigned int val) const {
return ! (*this == val);
}
// unary negation
balance_t& negate() {
@ -322,7 +340,10 @@ class balance_t
return negated();
}
// test for non-zero (use ! for zero)
// conversion operators
operator amount_t() const {
return amount();
}
operator bool() const {
for (amounts_map::const_iterator i = amounts.begin();
i != amounts.end();
@ -338,14 +359,18 @@ class balance_t
void write(std::ostream& out,
const int first_width,
const int latter_width = -1) const;
void abs() {
for (amounts_map::iterator i = amounts.begin();
i != amounts.end();
i++)
(*i).second.abs();
}
};
inline balance_t abs(const balance_t& bal) {
balance_t temp;
for (amounts_map::const_iterator i = bal.amounts.begin();
i != bal.amounts.end();
i++)
temp += abs((*i).second);
balance_t temp = bal;
temp.abs();
return temp;
}

View file

@ -60,17 +60,21 @@ mask_t::~mask_t() {
}
void value_expr_t::compute(balance_t& result, const details_t& details) const
void value_expr_t::compute(value_t& result, const details_t& details,
value_t::type_t type) const
{
switch (type) {
case CONSTANT_A:
result = constant_a;
switch (kind) {
case CONSTANT_I:
result = constant_i;
break;
case CONSTANT_T:
result = (unsigned int) constant_t;
break;
case CONSTANT_A:
result = constant_a;
break;
case AMOUNT:
if (details.xact)
result = details.xact->amount;
@ -183,11 +187,15 @@ void value_expr_t::compute(balance_t& result, const details_t& details) const
case INDEX:
if (details.xact)
result = details.xact->index + 1;
else
result = 0U;
break;
case DEPTH:
if (details.account)
result = details.account->depth - 1;
result = (unsigned int) (details.account->depth - 1);
else
result = 0U;
break;
case F_ARITH_MEAN:
@ -212,15 +220,21 @@ void value_expr_t::compute(balance_t& result, const details_t& details) const
case F_ABS:
assert(left);
left->compute(result, details);
result = abs(result);
result.abs();
break;
case F_STRIP: {
assert(left);
left->compute(result, details);
amount_t amt = result.amount();
amt.commodity = commodity_t::null_commodity;
result = amt;
if (result.type == value_t::BALANCE) {
// jww (2004-08-17): do something smarter here
result.cast(value_t::AMOUNT);
}
if (result.type == value_t::AMOUNT) {
amount_t amt = result;
amt.commodity = commodity_t::null_commodity;
result = amt;
}
break;
}
@ -244,11 +258,11 @@ void value_expr_t::compute(balance_t& result, const details_t& details) const
case F_VALUE: {
assert(left);
left->compute(result, details);
left->compute(result, details, value_t::BALANCE);
std::time_t moment = now;
if (right) {
switch (right->type) {
switch (right->kind) {
case DATE:
if (details.entry)
moment = details.entry->date;
@ -262,20 +276,20 @@ void value_expr_t::compute(balance_t& result, const details_t& details) const
throw compute_error("Invalid date passed to P(value,date)");
}
}
result = result.value(moment);
result = (*((balance_t *)result.data)).value(moment);
break;
}
case O_NOT:
left->compute(result, details);
result = result ? false : true;
left->compute(result, details, value_t::BOOLEAN);
result.negate();
break;
case O_QUES:
assert(left);
assert(right);
assert(right->type == O_COL);
left->compute(result, details);
assert(right->kind == O_COL);
left->compute(result, details, value_t::BOOLEAN);
if (result)
right->left->compute(result, details);
else
@ -285,17 +299,17 @@ void value_expr_t::compute(balance_t& result, const details_t& details) const
case O_AND:
assert(left);
assert(right);
left->compute(result, details);
left->compute(result, details, value_t::BOOLEAN);
if (result)
right->compute(result, details);
right->compute(result, details, value_t::BOOLEAN);
break;
case O_OR:
assert(left);
assert(right);
left->compute(result, details);
left->compute(result, details, value_t::BOOLEAN);
if (! result)
right->compute(result, details);
right->compute(result, details, value_t::BOOLEAN);
break;
case O_EQ:
@ -305,10 +319,10 @@ void value_expr_t::compute(balance_t& result, const details_t& details) const
case O_GTE: {
assert(left);
assert(right);
balance_t temp;
value_t temp;
left->compute(temp, details);
right->compute(result, details);
switch (type) {
switch (kind) {
case O_EQ: result = temp == result; break;
case O_LT: result = temp < result; break;
case O_LTE: result = temp <= result; break;
@ -325,10 +339,10 @@ void value_expr_t::compute(balance_t& result, const details_t& details) const
case O_DIV: {
assert(left);
assert(right);
balance_t temp;
value_t temp;
right->compute(temp, details);
left->compute(result, details);
switch (type) {
switch (kind) {
case O_ADD: result += temp; break;
case O_SUB: result -= temp; break;
case O_MUL: result *= temp; break;
@ -343,6 +357,9 @@ void value_expr_t::compute(balance_t& result, const details_t& details) const
assert(0);
break;
}
if (type < value_t::ANY && type != result.type)
result.cast(type);
}
value_expr_t * parse_value_term(std::istream& in);
@ -357,18 +374,22 @@ value_expr_t * parse_value_term(std::istream& in)
value_expr_t * node = NULL;
char c = peek_next_nonws(in);
if (std::isdigit(c) || c == '.' || c == '{') {
if (std::isdigit(c)) {
static char buf[2048];
if (c == '{') {
READ_INTO(in, buf, 2048, c, std::isdigit(c));
node = new value_expr_t(value_expr_t::CONSTANT_I);
node->constant_i = std::atol(buf);
return node;
}
else if (c == '{') {
static char buf[2048];
in.get(c);
READ_INTO(in, buf, 2048, c, c != '}');
if (c == '}')
in.get(c);
READ_INTO(in, buf, 2048, c, c != '}');
if (c == '}')
in.get(c);
else
throw value_expr_error("Missing '}'");
} else {
READ_INTO(in, buf, 2048, c, std::isdigit(c) || c == '.');
}
else
throw value_expr_error("Missing '}'");
node = new value_expr_t(value_expr_t::CONSTANT_A);
node->constant_a.parse(buf);
@ -613,7 +634,7 @@ value_expr_t * parse_logic_expr(std::istream& in)
node = new value_expr_t(value_expr_t::O_LT);
if (peek_next_nonws(in) == '=') {
in.get(c);
node->type = value_expr_t::O_LTE;
node->kind = value_expr_t::O_LTE;
}
node->left = prev;
node->right = parse_add_expr(in);
@ -625,7 +646,7 @@ value_expr_t * parse_logic_expr(std::istream& in)
node = new value_expr_t(value_expr_t::O_GT);
if (peek_next_nonws(in) == '=') {
in.get(c);
node->type = value_expr_t::O_GTE;
node->kind = value_expr_t::O_GTE;
}
node->left = prev;
node->right = parse_add_expr(in);
@ -708,13 +729,16 @@ value_expr_t * parse_value_expr(std::istream& in)
void dump_value_expr(std::ostream& out, const value_expr_t * node)
{
switch (node->type) {
case value_expr_t::CONSTANT_A:
out << "CONST[" << node->constant_a << "]";
switch (node->kind) {
case value_expr_t::CONSTANT_I:
out << "UINT[" << node->constant_i << "]";
break;
case value_expr_t::CONSTANT_T:
out << "DATE/TIME[" << node->constant_t << "]";
break;
case value_expr_t::CONSTANT_A:
out << "CONST[" << node->constant_a << "]";
break;
case value_expr_t::AMOUNT: out << "AMOUNT"; break;
case value_expr_t::COST: out << "COST"; break;
@ -794,7 +818,7 @@ void dump_value_expr(std::ostream& out, const value_expr_t * node)
case value_expr_t::O_OR:
out << "(";
dump_value_expr(out, node->left);
switch (node->type) {
switch (node->kind) {
case value_expr_t::O_AND: out << " & "; break;
case value_expr_t::O_OR: out << " | "; break;
default: assert(0); break;
@ -810,7 +834,7 @@ void dump_value_expr(std::ostream& out, const value_expr_t * node)
case value_expr_t::O_GTE:
out << "(";
dump_value_expr(out, node->left);
switch (node->type) {
switch (node->kind) {
case value_expr_t::O_EQ: out << "="; break;
case value_expr_t::O_LT: out << "<"; break;
case value_expr_t::O_LTE: out << "<="; break;
@ -828,7 +852,7 @@ void dump_value_expr(std::ostream& out, const value_expr_t * node)
case value_expr_t::O_DIV:
out << "(";
dump_value_expr(out, node->left);
switch (node->type) {
switch (node->kind) {
case value_expr_t::O_ADD: out << "+"; break;
case value_expr_t::O_SUB: out << "-"; break;
case value_expr_t::O_MUL: out << "*"; break;

View file

@ -2,6 +2,7 @@
#define _EXPR_H
#include "ledger.h"
#include "value.h"
#include "error.h"
namespace ledger {
@ -42,8 +43,9 @@ struct value_expr_t
{
enum kind_t {
// Constants
CONSTANT_A,
CONSTANT_I,
CONSTANT_T,
CONSTANT_A,
// Item details
AMOUNT,
@ -93,16 +95,19 @@ struct value_expr_t
LAST
};
kind_t type;
kind_t kind;
value_expr_t * left;
value_expr_t * right;
amount_t constant_a;
std::time_t constant_t;
mask_t * mask;
union {
std::time_t constant_t;
unsigned int constant_i;
};
amount_t constant_a;
mask_t * mask;
value_expr_t(const kind_t _type)
: type(_type), left(NULL), right(NULL), mask(NULL) {}
value_expr_t(const kind_t _kind)
: kind(_kind), left(NULL), right(NULL), mask(NULL) {}
~value_expr_t() {
if (mask) delete mask;
@ -110,7 +115,14 @@ struct value_expr_t
if (right) delete right;
}
void compute(balance_t& result, const details_t& details) const;
void compute(value_t& result, const details_t& details,
value_t::type_t type = value_t::ANY) const;
void compute(balance_t& result, const details_t& details) const {
value_t value;
compute(value, details, value_t::BALANCE);
result = value.operator balance_t();
}
};
value_expr_t * parse_value_expr(std::istream& in);
@ -170,7 +182,7 @@ class item_predicate
bool operator()(const T * item) const {
if (predicate) {
balance_t result;
value_t result;
predicate->compute(result, details_t(item));
return result;
} else {

995
value.h Normal file
View file

@ -0,0 +1,995 @@
#ifndef _VALUE_H
#define _VALUE_H
#include "amount.h"
#include "balance.h"
namespace ledger {
// The following type is a polymorphous value type used solely for
// performance reasons. The alternative is to compute value
// expressions (valexpr.cc) in terms of the largest data type,
// balance_t. This was found to be prohibitively expensive, especially
// when large logic chains were involved, since many temporary
// allocations would occur for every operator. With value_t, and the
// fact that logic chains only need boolean values to continue, no
// memory allocations need to take place at all.
class value_t
{
bool constructed;
value_t(const value_t& copy);
public:
char data[sizeof(balance_t)];
enum type_t {
BOOLEAN,
INTEGER,
AMOUNT,
BALANCE,
ANY
} type;
value_t() : constructed(false) {
*this = 0U;
}
value_t(const bool value) : constructed(false) {
*((bool *) data) = value;
type = BOOLEAN;
}
value_t(const unsigned int value) : constructed(false) {
*((unsigned int *) data) = value;
type = INTEGER;
}
value_t(const amount_t& value) : constructed(true) {
new((amount_t *)data) amount_t(value);
type = AMOUNT;
}
value_t(const balance_t& value) : constructed(true) {
new((balance_t *)data) balance_t(value);
type = BALANCE;
}
~value_t() {
destroy();
}
void destroy() {
if (constructed) {
switch (type) {
case AMOUNT:
((amount_t *)data)->~amount_t();
break;
case BALANCE:
((balance_t *)data)->~balance_t();
break;
default:
break;
}
constructed = false;
}
}
value_t& operator=(const bool value) {
destroy();
*((bool *) data) = value;
type = BOOLEAN;
return *this;
}
value_t& operator=(const unsigned int value) {
destroy();
*((unsigned int *) data) = value;
type = INTEGER;
return *this;
}
value_t& operator=(const amount_t& value) {
destroy();
new((amount_t *)data) amount_t(value);
type = AMOUNT;
return *this;
}
value_t& operator=(const balance_t& value) {
destroy();
new((balance_t *)data) balance_t(value);
type = BALANCE;
return *this;
}
value_t& operator+=(const value_t& value) {
switch (value.type) {
case BOOLEAN:
case INTEGER:
switch (type) {
case BOOLEAN:
cast(INTEGER);
case INTEGER:
*((unsigned int *) data) += *((unsigned int *) value.data);
break;
case AMOUNT:
*((amount_t *) data) += *((unsigned int *) value.data);
break;
case BALANCE:
*((balance_t *) data) += amount_t(*((unsigned int *) value.data));
break;
default:
assert(0);
break;
}
break;
case AMOUNT:
switch (type) {
case BOOLEAN:
case INTEGER:
cast(AMOUNT);
case AMOUNT:
*((amount_t *) data) += *((amount_t *) value.data);
break;
case BALANCE:
*((balance_t *) data) += *((amount_t *) value.data);
break;
default:
assert(0);
break;
}
break;
case BALANCE:
switch (type) {
case BOOLEAN:
case INTEGER:
case AMOUNT:
cast(BALANCE);
case BALANCE:
*((balance_t *) data) += *((balance_t *) value.data);
break;
default:
assert(0);
break;
}
break;
default:
assert(0);
break;
}
return *this;
}
value_t& operator-=(const value_t& value) {
switch (value.type) {
case BOOLEAN:
case INTEGER:
switch (type) {
case BOOLEAN:
cast(INTEGER);
case INTEGER:
*((unsigned int *) data) -= *((unsigned int *) value.data);
break;
case AMOUNT:
*((amount_t *) data) -= *((unsigned int *) value.data);
break;
case BALANCE:
*((balance_t *) data) -= amount_t(*((unsigned int *) value.data));
break;
default:
assert(0);
break;
}
break;
case AMOUNT:
switch (type) {
case BOOLEAN:
case INTEGER:
cast(AMOUNT);
case AMOUNT:
*((amount_t *) data) -= *((amount_t *) value.data);
break;
case BALANCE:
*((balance_t *) data) -= *((amount_t *) value.data);
break;
default:
assert(0);
break;
}
break;
case BALANCE:
switch (type) {
case BOOLEAN:
case INTEGER:
case AMOUNT:
cast(BALANCE);
case BALANCE:
*((balance_t *) data) -= *((balance_t *) value.data);
break;
default:
assert(0);
break;
}
break;
default:
assert(0);
break;
}
return *this;
}
value_t& operator*=(const value_t& value) {
switch (value.type) {
case BOOLEAN:
case INTEGER:
switch (type) {
case BOOLEAN:
cast(INTEGER);
case INTEGER:
*((unsigned int *) data) *= *((unsigned int *) value.data);
break;
case AMOUNT:
*((amount_t *) data) *= *((unsigned int *) value.data);
break;
case BALANCE:
*((balance_t *) data) *= amount_t(*((unsigned int *) value.data));
break;
default:
assert(0);
break;
}
break;
case AMOUNT:
switch (type) {
case BOOLEAN:
case INTEGER:
cast(AMOUNT);
case AMOUNT:
*((amount_t *) data) *= *((amount_t *) value.data);
break;
case BALANCE:
*((balance_t *) data) *= *((amount_t *) value.data);
break;
default:
assert(0);
break;
}
break;
case BALANCE:
switch (type) {
case BOOLEAN:
case INTEGER:
case AMOUNT:
cast(BALANCE);
case BALANCE:
*((balance_t *) data) *= *((balance_t *) value.data);
break;
default:
assert(0);
break;
}
break;
default:
assert(0);
break;
}
return *this;
}
value_t& operator/=(const value_t& value) {
switch (value.type) {
case BOOLEAN:
case INTEGER:
switch (type) {
case BOOLEAN:
cast(INTEGER);
case INTEGER:
*((unsigned int *) data) /= *((unsigned int *) value.data);
break;
case AMOUNT:
*((amount_t *) data) /= *((unsigned int *) value.data);
break;
case BALANCE:
*((balance_t *) data) /= amount_t(*((unsigned int *) value.data));
break;
default:
assert(0);
break;
}
break;
case AMOUNT:
switch (type) {
case BOOLEAN:
case INTEGER:
cast(AMOUNT);
case AMOUNT:
*((amount_t *) data) /= *((amount_t *) value.data);
break;
case BALANCE:
*((balance_t *) data) /= *((amount_t *) value.data);
break;
default:
assert(0);
break;
}
break;
case BALANCE:
switch (type) {
case BOOLEAN:
case INTEGER:
case AMOUNT:
cast(BALANCE);
case BALANCE:
*((balance_t *) data) /= *((balance_t *) value.data);
break;
default:
assert(0);
break;
}
break;
default:
assert(0);
break;
}
return *this;
}
bool operator==(const value_t& value) {
switch (value.type) {
case BOOLEAN:
switch (type) {
case BOOLEAN:
return *((bool *) data) == *((bool *) value.data);
case INTEGER:
return bool(*((unsigned int *) data)) == *((bool *) value.data);
case AMOUNT:
return bool(*((amount_t *) data)) == *((bool *) value.data);
case BALANCE:
return bool(*((balance_t *) data)) == *((bool *) value.data);
default:
assert(0);
break;
}
break;
case INTEGER:
switch (type) {
case BOOLEAN:
return ((unsigned int) *((bool *) data)) == *((unsigned int *) value.data);
case INTEGER:
return *((unsigned int *) data) == *((unsigned int *) value.data);
case AMOUNT:
return ((unsigned int) *((amount_t *) data)) == *((unsigned int *) value.data);
case BALANCE:
return ((unsigned int) *((balance_t *) data)) == *((unsigned int *) value.data);
default:
assert(0);
break;
}
break;
case AMOUNT:
switch (type) {
case BOOLEAN:
return amount_t(*((bool *) data)) == *((amount_t *) value.data);
case INTEGER:
return amount_t(*((unsigned int *) data)) == *((amount_t *) value.data);
case AMOUNT:
return *((amount_t *) data) == *((amount_t *) value.data);
case BALANCE:
return ((balance_t *) data)->amount() == *((amount_t *) value.data);
default:
assert(0);
break;
}
break;
case BALANCE:
switch (type) {
case BOOLEAN:
return balance_t(*((bool *) data)) == *((balance_t *) value.data);
case INTEGER:
return balance_t(*((unsigned int *) data)) == *((balance_t *) value.data);
case AMOUNT:
return balance_t(*((amount_t *) data)) == *((balance_t *) value.data);
case BALANCE:
return *((balance_t *) data) == *((balance_t *) value.data);
default:
assert(0);
break;
}
break;
default:
assert(0);
break;
}
return *this;
}
bool operator!=(const value_t& value) {
return ! (*this == value);
}
bool operator<(const value_t& value) {
switch (value.type) {
case BOOLEAN:
switch (type) {
case BOOLEAN:
return *((bool *) data) < *((bool *) value.data);
case INTEGER:
return bool(*((unsigned int *) data)) < *((bool *) value.data);
case AMOUNT:
return bool(*((amount_t *) data)) < *((bool *) value.data);
case BALANCE:
return bool(*((balance_t *) data)) < *((bool *) value.data);
default:
assert(0);
break;
}
break;
case INTEGER:
switch (type) {
case BOOLEAN:
return ((unsigned int) *((bool *) data)) < *((unsigned int *) value.data);
case INTEGER:
return *((unsigned int *) data) < *((unsigned int *) value.data);
case AMOUNT:
return *((amount_t *) data) < *((unsigned int *) value.data);
case BALANCE:
return *((balance_t *) data) < *((unsigned int *) value.data);
default:
assert(0);
break;
}
break;
case AMOUNT:
switch (type) {
case BOOLEAN:
return amount_t(*((bool *) data)) < *((amount_t *) value.data);
case INTEGER:
return amount_t(*((unsigned int *) data)) < *((amount_t *) value.data);
case AMOUNT:
return *((amount_t *) data) < *((amount_t *) value.data);
case BALANCE:
return ((balance_t *) data)->amount(((amount_t *) value.data)->commodity) < *((amount_t *) value.data);
default:
assert(0);
break;
}
break;
case BALANCE:
switch (type) {
case BOOLEAN:
return balance_t(*((bool *) data)) < *((balance_t *) value.data);
case INTEGER:
return balance_t(*((unsigned int *) data)) < *((balance_t *) value.data);
case AMOUNT:
return balance_t(*((amount_t *) data)) < *((balance_t *) value.data);
case BALANCE:
return *((balance_t *) data) < *((balance_t *) value.data);
default:
assert(0);
break;
}
break;
default:
assert(0);
break;
}
return *this;
}
bool operator<=(const value_t& value) {
switch (value.type) {
case BOOLEAN:
switch (type) {
case BOOLEAN:
return *((bool *) data) <= *((bool *) value.data);
case INTEGER:
return bool(*((unsigned int *) data)) <= *((bool *) value.data);
case AMOUNT:
return bool(*((amount_t *) data)) <= *((bool *) value.data);
case BALANCE:
return bool(*((balance_t *) data)) <= *((bool *) value.data);
default:
assert(0);
break;
}
break;
case INTEGER:
switch (type) {
case BOOLEAN:
return ((unsigned int) *((bool *) data)) <= *((unsigned int *) value.data);
case INTEGER:
return *((unsigned int *) data) <= *((unsigned int *) value.data);
case AMOUNT:
return ((unsigned int) *((amount_t *) data)) <= *((unsigned int *) value.data);
case BALANCE:
return ((unsigned int) *((balance_t *) data)) <= *((unsigned int *) value.data);
default:
assert(0);
break;
}
break;
case AMOUNT:
switch (type) {
case BOOLEAN:
return amount_t(*((bool *) data)) <= *((amount_t *) value.data);
case INTEGER:
return amount_t(*((unsigned int *) data)) <= *((amount_t *) value.data);
case AMOUNT:
return *((amount_t *) data) <= *((amount_t *) value.data);
case BALANCE:
return ((balance_t *) data)->amount() <= *((amount_t *) value.data);
default:
assert(0);
break;
}
break;
case BALANCE:
switch (type) {
case BOOLEAN:
return balance_t(*((bool *) data)) <= *((balance_t *) value.data);
case INTEGER:
return balance_t(*((unsigned int *) data)) <= *((balance_t *) value.data);
case AMOUNT:
return balance_t(*((amount_t *) data)) <= *((balance_t *) value.data);
case BALANCE:
return *((balance_t *) data) <= *((balance_t *) value.data);
default:
assert(0);
break;
}
break;
default:
assert(0);
break;
}
return *this;
}
bool operator>(const value_t& value) {
switch (value.type) {
case BOOLEAN:
switch (type) {
case BOOLEAN:
return *((bool *) data) > *((bool *) value.data);
case INTEGER:
return bool(*((unsigned int *) data)) > *((bool *) value.data);
case AMOUNT:
return bool(*((amount_t *) data)) > *((bool *) value.data);
case BALANCE:
return bool(*((balance_t *) data)) > *((bool *) value.data);
default:
assert(0);
break;
}
break;
case INTEGER:
switch (type) {
case BOOLEAN:
return ((unsigned int) *((bool *) data)) > *((unsigned int *) value.data);
case INTEGER:
return *((unsigned int *) data) > *((unsigned int *) value.data);
case AMOUNT:
return ((unsigned int) *((amount_t *) data)) > *((unsigned int *) value.data);
case BALANCE:
return ((unsigned int) *((balance_t *) data)) > *((unsigned int *) value.data);
default:
assert(0);
break;
}
break;
case AMOUNT:
switch (type) {
case BOOLEAN:
return amount_t(*((bool *) data)) > *((amount_t *) value.data);
case INTEGER:
return amount_t(*((unsigned int *) data)) > *((amount_t *) value.data);
case AMOUNT:
return *((amount_t *) data) > *((amount_t *) value.data);
case BALANCE:
return ((balance_t *) data)->amount(((amount_t *) value.data)->commodity) > *((amount_t *) value.data);
default:
assert(0);
break;
}
break;
case BALANCE:
switch (type) {
case BOOLEAN:
return balance_t(*((bool *) data)) > *((balance_t *) value.data);
case INTEGER:
return balance_t(*((unsigned int *) data)) > *((balance_t *) value.data);
case AMOUNT:
return balance_t(*((amount_t *) data)) > *((balance_t *) value.data);
case BALANCE:
return *((balance_t *) data) > *((balance_t *) value.data);
default:
assert(0);
break;
}
break;
default:
assert(0);
break;
}
return *this;
}
bool operator>=(const value_t& value) {
switch (value.type) {
case BOOLEAN:
switch (type) {
case BOOLEAN:
return *((bool *) data) >= *((bool *) value.data);
case INTEGER:
return bool(*((unsigned int *) data)) >= *((bool *) value.data);
case AMOUNT:
return bool(*((amount_t *) data)) >= *((bool *) value.data);
case BALANCE:
return bool(*((balance_t *) data)) >= *((bool *) value.data);
default:
assert(0);
break;
}
break;
case INTEGER:
switch (type) {
case BOOLEAN:
return ((unsigned int) *((bool *) data)) >= *((unsigned int *) value.data);
case INTEGER:
return *((unsigned int *) data) >= *((unsigned int *) value.data);
case AMOUNT:
return ((unsigned int) *((amount_t *) data)) >= *((unsigned int *) value.data);
case BALANCE:
return ((unsigned int) *((balance_t *) data)) >= *((unsigned int *) value.data);
default:
assert(0);
break;
}
break;
case AMOUNT:
switch (type) {
case BOOLEAN:
return amount_t(*((bool *) data)) >= *((amount_t *) value.data);
case INTEGER:
return amount_t(*((unsigned int *) data)) >= *((amount_t *) value.data);
case AMOUNT:
return *((amount_t *) data) >= *((amount_t *) value.data);
case BALANCE:
return ((balance_t *) data)->amount() >= *((amount_t *) value.data);
default:
assert(0);
break;
}
break;
case BALANCE:
switch (type) {
case BOOLEAN:
return balance_t(*((bool *) data)) >= *((balance_t *) value.data);
case INTEGER:
return balance_t(*((unsigned int *) data)) >= *((balance_t *) value.data);
case AMOUNT:
return balance_t(*((amount_t *) data)) >= *((balance_t *) value.data);
case BALANCE:
return *((balance_t *) data) >= *((balance_t *) value.data);
default:
assert(0);
break;
}
break;
default:
assert(0);
break;
}
return *this;
}
template <typename T>
operator T() const {
switch (type) {
case BOOLEAN:
return *((bool *) data);
case INTEGER:
return *((unsigned int *) data);
case AMOUNT:
return *((amount_t *) data);
case BALANCE:
return *((balance_t *) data);
default:
assert(0);
break;
}
assert(0);
return 0;
}
void cast(type_t cast_type) {
switch (type) {
case BOOLEAN:
switch (cast_type) {
case BOOLEAN:
break;
case INTEGER:
*((unsigned int *) data) = *((bool *) data);
break;
case AMOUNT:
new((amount_t *)data) amount_t(*((bool *) data));
constructed = true;
break;
case BALANCE:
new((balance_t *)data) balance_t(*((bool *) data));
constructed = true;
break;
default:
assert(0);
break;
}
break;
case INTEGER:
switch (cast_type) {
case BOOLEAN:
*((bool *) data) = *((unsigned int *) data);
break;
case INTEGER:
break;
case AMOUNT:
new((amount_t *)data) amount_t(*((unsigned int *) data));
constructed = true;
break;
case BALANCE:
new((balance_t *)data) balance_t(*((unsigned int *) data));
constructed = true;
break;
default:
assert(0);
break;
}
break;
case AMOUNT:
switch (cast_type) {
case BOOLEAN: {
bool temp = *((amount_t *) data);
destroy();
*((bool *)data) = temp;
break;
}
case INTEGER: {
unsigned int temp = *((amount_t *) data);
destroy();
*((unsigned int *)data) = temp;
break;
}
case AMOUNT:
break;
case BALANCE: {
amount_t temp = *((amount_t *) data);
destroy();
new((balance_t *)data) balance_t(temp);
constructed = true;
break;
}
default:
assert(0);
break;
}
break;
case BALANCE:
switch (cast_type) {
case BOOLEAN: {
bool temp = *((balance_t *) data);
destroy();
*((bool *)data) = temp;
break;
}
case INTEGER: {
unsigned int temp = ((balance_t *) data)->amount();
destroy();
*((unsigned int *)data) = temp;
break;
}
case AMOUNT: {
amount_t temp = ((balance_t *) data)->amount();
destroy();
new((amount_t *)data) amount_t(temp);
constructed = true;
break;
}
case BALANCE:
break;
default:
assert(0);
break;
}
break;
default:
assert(0);
break;
}
type = cast_type;
}
void negate() {
switch (type) {
case BOOLEAN:
*((bool *) data) = ! *((bool *) data);
break;
case INTEGER:
*((unsigned int *) data) = - *((unsigned int *) data);
break;
case AMOUNT:
((amount_t *) data)->negate();
break;
case BALANCE:
((balance_t *) data)->negate();
break;
default:
assert(0);
break;
}
}
void abs() {
switch (type) {
case BOOLEAN:
break;
case INTEGER:
if (*((unsigned int *) data) < 0)
*((unsigned int *) data) = - *((unsigned int *) data);
break;
case AMOUNT:
((amount_t *) data)->abs();
break;
case BALANCE:
((balance_t *) data)->abs();
break;
default:
assert(0);
break;
}
}
};
} // namespace ledger
#endif // _VALUE_H