more cleanup
This commit is contained in:
parent
6392b01799
commit
7dbd7bce59
8 changed files with 146 additions and 160 deletions
1
Makefile
1
Makefile
|
|
@ -6,7 +6,6 @@ CODE = account.cc \
|
||||||
config.cc \
|
config.cc \
|
||||||
datetime.cc \
|
datetime.cc \
|
||||||
debug.cc \
|
debug.cc \
|
||||||
error.cc \
|
|
||||||
format.cc \
|
format.cc \
|
||||||
ledger.cc \
|
ledger.cc \
|
||||||
option.cc \
|
option.cc \
|
||||||
|
|
|
||||||
233
amount.cc
233
amount.cc
|
|
@ -25,23 +25,29 @@ static struct ctor_dtor_info {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
class amount_t::bigint_t {
|
class amount_t::bigint_t {
|
||||||
bigint_t(const bigint_t&);
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
mpz_t val;
|
mpz_t val;
|
||||||
|
unsigned int prec;
|
||||||
unsigned int ref;
|
unsigned int ref;
|
||||||
unsigned int index;
|
unsigned int index;
|
||||||
|
|
||||||
bigint_t() : ref(1), index(0) {
|
bigint_t() : prec(0), ref(1), index(0) {
|
||||||
mpz_init(val);
|
mpz_init(val);
|
||||||
#ifdef DEBUG_ENABLED
|
#ifdef DEBUG_ENABLED
|
||||||
bigint_ctors++;
|
bigint_ctors++;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
bigint_t(mpz_t _val) : ref(1), index(0) {
|
bigint_t(mpz_t _val) : prec(0), ref(1), index(0) {
|
||||||
mpz_init_set(val, _val);
|
mpz_init_set(val, _val);
|
||||||
#ifdef DEBUG_ENABLED
|
#ifdef DEBUG_ENABLED
|
||||||
bigint_ctors++;
|
bigint_ctors++;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
bigint_t(const bigint_t& other)
|
||||||
|
: prec(other.prec), ref(1), index(0) {
|
||||||
|
mpz_init_set(val, other.val);
|
||||||
|
#ifdef DEBUG_ENABLED
|
||||||
|
bigint_ctors++;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
~bigint_t() {
|
~bigint_t() {
|
||||||
|
|
@ -133,11 +139,9 @@ amount_t::amount_t(const bool value)
|
||||||
{
|
{
|
||||||
if (value) {
|
if (value) {
|
||||||
quantity = new bigint_t(true_value);
|
quantity = new bigint_t(true_value);
|
||||||
precision = 0;
|
|
||||||
commodity = commodity_t::null_commodity;
|
commodity = commodity_t::null_commodity;
|
||||||
} else {
|
} else {
|
||||||
quantity = NULL;
|
quantity = NULL;
|
||||||
precision = 0;
|
|
||||||
commodity = NULL;
|
commodity = NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -145,13 +149,11 @@ amount_t::amount_t(const bool value)
|
||||||
amount_t::amount_t(const int value)
|
amount_t::amount_t(const int value)
|
||||||
{
|
{
|
||||||
if (value != 0) {
|
if (value != 0) {
|
||||||
_init();
|
quantity = new bigint_t;
|
||||||
mpz_set_si(MPZ(quantity), value);
|
mpz_set_si(MPZ(quantity), value);
|
||||||
precision = 0;
|
|
||||||
commodity = commodity_t::null_commodity;
|
commodity = commodity_t::null_commodity;
|
||||||
} else {
|
} else {
|
||||||
quantity = NULL;
|
quantity = NULL;
|
||||||
precision = 0;
|
|
||||||
commodity = NULL;
|
commodity = NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -159,13 +161,11 @@ amount_t::amount_t(const int value)
|
||||||
amount_t::amount_t(const unsigned int value)
|
amount_t::amount_t(const unsigned int value)
|
||||||
{
|
{
|
||||||
if (value != 0) {
|
if (value != 0) {
|
||||||
_init();
|
quantity = new bigint_t;
|
||||||
mpz_set_ui(MPZ(quantity), value);
|
mpz_set_ui(MPZ(quantity), value);
|
||||||
precision = 0;
|
|
||||||
commodity = commodity_t::null_commodity;
|
commodity = commodity_t::null_commodity;
|
||||||
} else {
|
} else {
|
||||||
quantity = NULL;
|
quantity = NULL;
|
||||||
precision = 0;
|
|
||||||
commodity = NULL;
|
commodity = NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -173,14 +173,12 @@ amount_t::amount_t(const unsigned int value)
|
||||||
amount_t::amount_t(const double value)
|
amount_t::amount_t(const double value)
|
||||||
{
|
{
|
||||||
if (value != 0.0) {
|
if (value != 0.0) {
|
||||||
_init();
|
quantity = new bigint_t;
|
||||||
mpz_set_d(MPZ(quantity), value);
|
mpz_set_d(MPZ(quantity), value);
|
||||||
// jww (2004-08-20): How do I calculate this?
|
// jww (2004-08-20): How do I calculate this?
|
||||||
precision = 0;
|
|
||||||
commodity = commodity_t::null_commodity;
|
commodity = commodity_t::null_commodity;
|
||||||
} else {
|
} else {
|
||||||
quantity = NULL;
|
quantity = NULL;
|
||||||
precision = 0;
|
|
||||||
commodity = NULL;
|
commodity = NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -193,13 +191,19 @@ void amount_t::_release()
|
||||||
|
|
||||||
void amount_t::_init()
|
void amount_t::_init()
|
||||||
{
|
{
|
||||||
|
if (! quantity) {
|
||||||
quantity = new bigint_t;
|
quantity = new bigint_t;
|
||||||
|
}
|
||||||
|
else if (quantity->ref > 1) {
|
||||||
|
_release();
|
||||||
|
quantity = new bigint_t;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void amount_t::_dup()
|
void amount_t::_dup()
|
||||||
{
|
{
|
||||||
if (quantity->ref > 1) {
|
if (quantity->ref > 1) {
|
||||||
bigint_t * q = new bigint_t(MPZ(quantity));
|
bigint_t * q = new bigint_t(*quantity);
|
||||||
_release();
|
_release();
|
||||||
quantity = q;
|
quantity = q;
|
||||||
}
|
}
|
||||||
|
|
@ -207,14 +211,14 @@ void amount_t::_dup()
|
||||||
|
|
||||||
void amount_t::_copy(const amount_t& amt)
|
void amount_t::_copy(const amount_t& amt)
|
||||||
{
|
{
|
||||||
|
if (quantity != amt.quantity) {
|
||||||
if (quantity)
|
if (quantity)
|
||||||
_release();
|
_release();
|
||||||
|
|
||||||
quantity = amt.quantity;
|
quantity = amt.quantity;
|
||||||
quantity->ref++;
|
quantity->ref++;
|
||||||
|
}
|
||||||
commodity = amt.commodity;
|
commodity = amt.commodity;
|
||||||
precision = amt.precision;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
amount_t& amount_t::operator=(const std::string& value)
|
amount_t& amount_t::operator=(const std::string& value)
|
||||||
|
|
@ -250,14 +254,7 @@ amount_t& amount_t::operator=(const bool value)
|
||||||
_clear();
|
_clear();
|
||||||
} else {
|
} else {
|
||||||
commodity = commodity_t::null_commodity;
|
commodity = commodity_t::null_commodity;
|
||||||
precision = 0;
|
|
||||||
if (! quantity) {
|
|
||||||
_init();
|
_init();
|
||||||
}
|
|
||||||
else if (quantity->ref > 1) {
|
|
||||||
_release();
|
|
||||||
_init();
|
|
||||||
}
|
|
||||||
mpz_set(MPZ(quantity), true_value);
|
mpz_set(MPZ(quantity), true_value);
|
||||||
}
|
}
|
||||||
return *this;
|
return *this;
|
||||||
|
|
@ -270,14 +267,7 @@ amount_t& amount_t::operator=(const int value)
|
||||||
_clear();
|
_clear();
|
||||||
} else {
|
} else {
|
||||||
commodity = commodity_t::null_commodity;
|
commodity = commodity_t::null_commodity;
|
||||||
precision = 0;
|
|
||||||
if (! quantity) {
|
|
||||||
_init();
|
_init();
|
||||||
}
|
|
||||||
else if (quantity->ref > 1) {
|
|
||||||
_release();
|
|
||||||
_init();
|
|
||||||
}
|
|
||||||
mpz_set_si(MPZ(quantity), value);
|
mpz_set_si(MPZ(quantity), value);
|
||||||
}
|
}
|
||||||
return *this;
|
return *this;
|
||||||
|
|
@ -290,14 +280,7 @@ amount_t& amount_t::operator=(const unsigned int value)
|
||||||
_clear();
|
_clear();
|
||||||
} else {
|
} else {
|
||||||
commodity = commodity_t::null_commodity;
|
commodity = commodity_t::null_commodity;
|
||||||
precision = 0;
|
|
||||||
if (! quantity) {
|
|
||||||
_init();
|
_init();
|
||||||
}
|
|
||||||
else if (quantity->ref > 1) {
|
|
||||||
_release();
|
|
||||||
_init();
|
|
||||||
}
|
|
||||||
mpz_set_ui(MPZ(quantity), value);
|
mpz_set_ui(MPZ(quantity), value);
|
||||||
}
|
}
|
||||||
return *this;
|
return *this;
|
||||||
|
|
@ -310,72 +293,89 @@ amount_t& amount_t::operator=(const double value)
|
||||||
_clear();
|
_clear();
|
||||||
} else {
|
} else {
|
||||||
commodity = commodity_t::null_commodity;
|
commodity = commodity_t::null_commodity;
|
||||||
// jww (2004-08-20): How do I calculate?
|
|
||||||
precision = 0;
|
|
||||||
if (! quantity) {
|
|
||||||
_init();
|
_init();
|
||||||
}
|
// jww (2004-08-20): How do I calculate precision?
|
||||||
else if (quantity->ref > 1) {
|
|
||||||
_release();
|
|
||||||
_init();
|
|
||||||
}
|
|
||||||
mpz_set_d(MPZ(quantity), value);
|
mpz_set_d(MPZ(quantity), value);
|
||||||
}
|
}
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void amount_t::_resize(int prec)
|
void amount_t::_resize(unsigned int prec)
|
||||||
{
|
{
|
||||||
if (prec == precision)
|
if (! quantity || prec == quantity->prec)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
_dup();
|
_dup();
|
||||||
|
|
||||||
if (prec < precision) {
|
if (prec < quantity->prec) {
|
||||||
mpz_ui_pow_ui(divisor, 10, precision - prec);
|
mpz_ui_pow_ui(divisor, 10, quantity->prec - prec);
|
||||||
mpz_tdiv_q(MPZ(quantity), MPZ(quantity), divisor);
|
mpz_tdiv_q(MPZ(quantity), MPZ(quantity), divisor);
|
||||||
} else {
|
} else {
|
||||||
mpz_ui_pow_ui(divisor, 10, prec - precision);
|
mpz_ui_pow_ui(divisor, 10, prec - quantity->prec);
|
||||||
mpz_mul(MPZ(quantity), MPZ(quantity), divisor);
|
mpz_mul(MPZ(quantity), MPZ(quantity), divisor);
|
||||||
}
|
}
|
||||||
|
|
||||||
precision = prec;
|
quantity->prec = prec;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#define DEF_OPERATOR(OP, FUNC) \
|
amount_t& amount_t::operator+=(const amount_t& amt)
|
||||||
amount_t& amount_t::operator OP(const amount_t& amt) \
|
{
|
||||||
{ \
|
if (amt.quantity) {
|
||||||
if (amt.quantity) { \
|
if (! quantity) {
|
||||||
if (! quantity) { \
|
quantity = new bigint_t(*amt.quantity);
|
||||||
_init(); \
|
commodity = amt.commodity;
|
||||||
commodity = amt.commodity; \
|
} else {
|
||||||
precision = amt.precision; \
|
_dup();
|
||||||
} else { \
|
|
||||||
_dup(); \
|
if (commodity != amt.commodity)
|
||||||
} \
|
throw amount_error("Adding amounts with different commodities");
|
||||||
\
|
|
||||||
if (commodity != amt.commodity) \
|
if (quantity->prec == amt.quantity->prec) {
|
||||||
throw amount_error("+/- amounts with different commodities"); \
|
mpz_add(MPZ(quantity), MPZ(quantity), MPZ(amt.quantity));
|
||||||
\
|
}
|
||||||
if (precision == amt.precision) { \
|
else if (quantity->prec < amt.quantity->prec) {
|
||||||
FUNC(MPZ(quantity), MPZ(quantity), MPZ(amt.quantity)); \
|
_resize(amt.quantity->prec);
|
||||||
} \
|
mpz_add(MPZ(quantity), MPZ(quantity), MPZ(amt.quantity));
|
||||||
else if (precision < amt.precision) { \
|
} else {
|
||||||
_resize(amt.precision); \
|
amount_t temp = amt;
|
||||||
FUNC(MPZ(quantity), MPZ(quantity), MPZ(amt.quantity)); \
|
temp._resize(quantity->prec);
|
||||||
} else { \
|
mpz_add(MPZ(quantity), MPZ(quantity), MPZ(temp.quantity));
|
||||||
amount_t temp = amt; \
|
}
|
||||||
temp._resize(precision); \
|
}
|
||||||
FUNC(MPZ(quantity), MPZ(quantity), MPZ(temp.quantity)); \
|
}
|
||||||
} \
|
return *this;
|
||||||
} \
|
|
||||||
return *this; \
|
|
||||||
}
|
}
|
||||||
|
|
||||||
DEF_OPERATOR(+=, mpz_add)
|
amount_t& amount_t::operator-=(const amount_t& amt)
|
||||||
DEF_OPERATOR(-=, mpz_sub)
|
{
|
||||||
|
if (amt.quantity) {
|
||||||
|
if (! quantity) {
|
||||||
|
quantity = new bigint_t(*amt.quantity);
|
||||||
|
mpz_neg(MPZ(quantity), MPZ(quantity));
|
||||||
|
commodity = amt.commodity;
|
||||||
|
} else {
|
||||||
|
_dup();
|
||||||
|
|
||||||
|
if (commodity != amt.commodity)
|
||||||
|
throw amount_error("Subtracting amounts with different commodities");
|
||||||
|
|
||||||
|
if (quantity->prec == amt.quantity->prec) {
|
||||||
|
mpz_sub(MPZ(quantity), MPZ(quantity), MPZ(amt.quantity));
|
||||||
|
}
|
||||||
|
else if (quantity->prec < amt.quantity->prec) {
|
||||||
|
_resize(amt.quantity->prec);
|
||||||
|
mpz_sub(MPZ(quantity), MPZ(quantity), MPZ(amt.quantity));
|
||||||
|
} else {
|
||||||
|
amount_t temp = amt;
|
||||||
|
temp._resize(quantity->prec);
|
||||||
|
mpz_sub(MPZ(quantity), MPZ(quantity), MPZ(temp.quantity));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
// unary negation
|
// unary negation
|
||||||
amount_t& amount_t::negate()
|
amount_t& amount_t::negate()
|
||||||
|
|
@ -510,17 +510,17 @@ bool amount_t::operator OP(const amount_t& amt) const \
|
||||||
if (commodity != amt.commodity) \
|
if (commodity != amt.commodity) \
|
||||||
throw amount_error("Comparing amounts with different commodities"); \
|
throw amount_error("Comparing amounts with different commodities"); \
|
||||||
\
|
\
|
||||||
if (precision == amt.precision) { \
|
if (quantity->prec == amt.quantity->prec) { \
|
||||||
return mpz_cmp(MPZ(quantity), MPZ(amt.quantity)) OP 0; \
|
return mpz_cmp(MPZ(quantity), MPZ(amt.quantity)) OP 0; \
|
||||||
} \
|
} \
|
||||||
else if (precision < amt.precision) { \
|
else if (quantity->prec < amt.quantity->prec) { \
|
||||||
amount_t temp = *this; \
|
amount_t temp = *this; \
|
||||||
temp._resize(amt.precision); \
|
temp._resize(amt.quantity->prec); \
|
||||||
return mpz_cmp(MPZ(temp.quantity), MPZ(amt.quantity)) OP 0; \
|
return mpz_cmp(MPZ(temp.quantity), MPZ(amt.quantity)) OP 0; \
|
||||||
} \
|
} \
|
||||||
else { \
|
else { \
|
||||||
amount_t temp = amt; \
|
amount_t temp = amt; \
|
||||||
temp._resize(precision); \
|
temp._resize(quantity->prec); \
|
||||||
return mpz_cmp(MPZ(quantity), MPZ(temp.quantity)) OP 0; \
|
return mpz_cmp(MPZ(quantity), MPZ(temp.quantity)) OP 0; \
|
||||||
} \
|
} \
|
||||||
}
|
}
|
||||||
|
|
@ -534,12 +534,12 @@ DEF_CMP_OPERATOR(==)
|
||||||
amount_t::operator bool() const
|
amount_t::operator bool() const
|
||||||
{
|
{
|
||||||
if (quantity) {
|
if (quantity) {
|
||||||
if (precision <= commodity->precision) {
|
if (quantity->prec <= commodity->precision) {
|
||||||
return mpz_sgn(MPZ(quantity)) != 0;
|
return mpz_sgn(MPZ(quantity)) != 0;
|
||||||
} else {
|
} else {
|
||||||
assert(commodity);
|
assert(commodity);
|
||||||
mpz_set(temp, MPZ(quantity));
|
mpz_set(temp, MPZ(quantity));
|
||||||
mpz_ui_pow_ui(divisor, 10, precision - commodity->precision);
|
mpz_ui_pow_ui(divisor, 10, quantity->prec - commodity->precision);
|
||||||
mpz_tdiv_q(temp, temp, divisor);
|
mpz_tdiv_q(temp, temp, divisor);
|
||||||
bool zero = mpz_sgn(temp) == 0;
|
bool zero = mpz_sgn(temp) == 0;
|
||||||
return ! zero;
|
return ! zero;
|
||||||
|
|
@ -553,7 +553,7 @@ amount_t amount_t::value(const std::time_t moment) const
|
||||||
{
|
{
|
||||||
if (quantity && ! (commodity->flags & COMMODITY_STYLE_NOMARKET))
|
if (quantity && ! (commodity->flags & COMMODITY_STYLE_NOMARKET))
|
||||||
if (amount_t amt = commodity->value(moment))
|
if (amount_t amt = commodity->value(moment))
|
||||||
return (amt * *this).round();
|
return (amt * *this).round(commodity->precision);
|
||||||
|
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
@ -566,7 +566,7 @@ amount_t& amount_t::operator*=(const amount_t& amt)
|
||||||
_dup();
|
_dup();
|
||||||
|
|
||||||
mpz_mul(MPZ(quantity), MPZ(quantity), MPZ(amt.quantity));
|
mpz_mul(MPZ(quantity), MPZ(quantity), MPZ(amt.quantity));
|
||||||
precision += amt.precision;
|
quantity->prec += amt.quantity->prec;
|
||||||
|
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
@ -575,7 +575,6 @@ amount_t& amount_t::operator/=(const amount_t& amt)
|
||||||
{
|
{
|
||||||
if (! quantity)
|
if (! quantity)
|
||||||
return *this;
|
return *this;
|
||||||
|
|
||||||
if (! amt.quantity)
|
if (! amt.quantity)
|
||||||
throw amount_error("Divide by zero");
|
throw amount_error("Divide by zero");
|
||||||
|
|
||||||
|
|
@ -583,26 +582,27 @@ amount_t& amount_t::operator/=(const amount_t& amt)
|
||||||
|
|
||||||
// Increase the value's precision, to capture fractional parts after
|
// Increase the value's precision, to capture fractional parts after
|
||||||
// the divide.
|
// the divide.
|
||||||
mpz_ui_pow_ui(divisor, 10, amt.precision + 6);
|
mpz_ui_pow_ui(divisor, 10, amt.quantity->prec + 6);
|
||||||
mpz_mul(MPZ(quantity), MPZ(quantity), divisor);
|
mpz_mul(MPZ(quantity), MPZ(quantity), divisor);
|
||||||
mpz_tdiv_q(MPZ(quantity), MPZ(quantity), MPZ(amt.quantity));
|
mpz_tdiv_q(MPZ(quantity), MPZ(quantity), MPZ(amt.quantity));
|
||||||
precision += 6;
|
quantity->prec += 6;
|
||||||
|
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
amount_t amount_t::round(int prec) const
|
amount_t amount_t::round(unsigned int prec) const
|
||||||
{
|
{
|
||||||
if (prec == -1)
|
if (! quantity || quantity->prec <= prec) {
|
||||||
prec = commodity->precision;
|
|
||||||
|
|
||||||
if (! quantity || precision <= prec) {
|
|
||||||
return *this;
|
return *this;
|
||||||
} else {
|
} else {
|
||||||
amount_t temp = *this;
|
amount_t temp = *this;
|
||||||
temp._dup();
|
temp._dup();
|
||||||
mpz_round(MPZ(temp.quantity), MPZ(temp.quantity),
|
mpz_round(MPZ(temp.quantity), MPZ(temp.quantity), quantity->prec, prec);
|
||||||
precision, prec == -1 ? commodity->precision : prec);
|
#if 0
|
||||||
|
mpz_ui_pow_ui(divisor, 10, quantity->prec - prec);
|
||||||
|
mpz_tdiv_q(MPZ(temp.quantity), MPZ(temp.quantity), divisor);
|
||||||
|
quantity->prec = prec;
|
||||||
|
#endif
|
||||||
return temp;
|
return temp;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -625,22 +625,22 @@ std::ostream& operator<<(std::ostream& out, const amount_t& amt)
|
||||||
// Ensure the value is rounded to the commodity's precision before
|
// Ensure the value is rounded to the commodity's precision before
|
||||||
// outputting it. NOTE: `rquotient' is used here as a temp variable!
|
// outputting it. NOTE: `rquotient' is used here as a temp variable!
|
||||||
|
|
||||||
if (amt.commodity->precision < amt.precision) {
|
if (amt.commodity->precision < amt.quantity->prec) {
|
||||||
mpz_round(rquotient, MPZ(amt.quantity),
|
mpz_round(rquotient, MPZ(amt.quantity),
|
||||||
amt.precision, amt.commodity->precision);
|
amt.quantity->prec, amt.commodity->precision);
|
||||||
mpz_ui_pow_ui(divisor, 10, amt.precision - amt.commodity->precision);
|
mpz_ui_pow_ui(divisor, 10, amt.quantity->prec - amt.commodity->precision);
|
||||||
mpz_tdiv_q(rquotient, rquotient, divisor);
|
mpz_tdiv_q(rquotient, rquotient, divisor);
|
||||||
mpz_ui_pow_ui(divisor, 10, amt.commodity->precision);
|
mpz_ui_pow_ui(divisor, 10, amt.commodity->precision);
|
||||||
mpz_tdiv_qr(quotient, remainder, rquotient, divisor);
|
mpz_tdiv_qr(quotient, remainder, rquotient, divisor);
|
||||||
}
|
}
|
||||||
else if (amt.commodity->precision > amt.precision) {
|
else if (amt.commodity->precision > amt.quantity->prec) {
|
||||||
mpz_ui_pow_ui(divisor, 10, amt.commodity->precision - amt.precision);
|
mpz_ui_pow_ui(divisor, 10, amt.commodity->precision - amt.quantity->prec);
|
||||||
mpz_mul(rquotient, MPZ(amt.quantity), divisor);
|
mpz_mul(rquotient, MPZ(amt.quantity), divisor);
|
||||||
mpz_ui_pow_ui(divisor, 10, amt.commodity->precision);
|
mpz_ui_pow_ui(divisor, 10, amt.commodity->precision);
|
||||||
mpz_tdiv_qr(quotient, remainder, rquotient, divisor);
|
mpz_tdiv_qr(quotient, remainder, rquotient, divisor);
|
||||||
}
|
}
|
||||||
else if (amt.precision) {
|
else if (amt.quantity->prec) {
|
||||||
mpz_ui_pow_ui(divisor, 10, amt.precision);
|
mpz_ui_pow_ui(divisor, 10, amt.quantity->prec);
|
||||||
mpz_tdiv_qr(quotient, remainder, MPZ(amt.quantity), divisor);
|
mpz_tdiv_qr(quotient, remainder, MPZ(amt.quantity), divisor);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
|
@ -778,8 +778,6 @@ void amount_t::parse(std::istream& in)
|
||||||
std::string quant;
|
std::string quant;
|
||||||
unsigned int flags = COMMODITY_STYLE_DEFAULTS;;
|
unsigned int flags = COMMODITY_STYLE_DEFAULTS;;
|
||||||
|
|
||||||
if (quantity)
|
|
||||||
_release();
|
|
||||||
_init();
|
_init();
|
||||||
|
|
||||||
char c = peek_next_nonws(in);
|
char c = peek_next_nonws(in);
|
||||||
|
|
@ -807,6 +805,8 @@ void amount_t::parse(std::istream& in)
|
||||||
std::string::size_type last_comma = quant.rfind(',');
|
std::string::size_type last_comma = quant.rfind(',');
|
||||||
std::string::size_type last_period = quant.rfind('.');
|
std::string::size_type last_period = quant.rfind('.');
|
||||||
|
|
||||||
|
unsigned int precision = 0;
|
||||||
|
|
||||||
if (last_comma != std::string::npos && last_period != std::string::npos) {
|
if (last_comma != std::string::npos && last_period != std::string::npos) {
|
||||||
flags |= COMMODITY_STYLE_THOUSANDS;
|
flags |= COMMODITY_STYLE_THOUSANDS;
|
||||||
if (last_comma > last_period) {
|
if (last_comma > last_period) {
|
||||||
|
|
@ -823,9 +823,8 @@ void amount_t::parse(std::istream& in)
|
||||||
else if (last_period != std::string::npos) {
|
else if (last_period != std::string::npos) {
|
||||||
precision = quant.length() - last_period - 1;
|
precision = quant.length() - last_period - 1;
|
||||||
}
|
}
|
||||||
else {
|
|
||||||
precision = 0;
|
quantity->prec = precision;
|
||||||
}
|
|
||||||
|
|
||||||
// Create the commodity if has not already been seen.
|
// Create the commodity if has not already been seen.
|
||||||
commodity = commodity_t::find_commodity(symbol, true);
|
commodity = commodity_t::find_commodity(symbol, true);
|
||||||
|
|
@ -854,6 +853,7 @@ void amount_t::parse(std::istream& in)
|
||||||
delete[] buf;
|
delete[] buf;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static char buf[4096];
|
static char buf[4096];
|
||||||
static int index = 0;
|
static int index = 0;
|
||||||
|
|
||||||
|
|
@ -884,7 +884,7 @@ void amount_t::write_quantity(std::ostream& out) const
|
||||||
byte = mpz_sgn(MPZ(quantity)) < 0 ? 1 : 0;
|
byte = mpz_sgn(MPZ(quantity)) < 0 ? 1 : 0;
|
||||||
out.write(&byte, sizeof(byte));
|
out.write(&byte, sizeof(byte));
|
||||||
|
|
||||||
out.write((char *)&precision, sizeof(precision));
|
out.write((char *)&quantity->prec, sizeof(quantity->prec));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
assert(quantity->ref > 1);
|
assert(quantity->ref > 1);
|
||||||
|
|
@ -908,7 +908,7 @@ void amount_t::read_quantity(std::istream& in)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (byte == 1) {
|
if (byte == 1) {
|
||||||
_init();
|
quantity = new bigint_t;
|
||||||
bigints.push_back(quantity);
|
bigints.push_back(quantity);
|
||||||
|
|
||||||
unsigned short len;
|
unsigned short len;
|
||||||
|
|
@ -921,7 +921,7 @@ void amount_t::read_quantity(std::istream& in)
|
||||||
if (negative)
|
if (negative)
|
||||||
mpz_neg(MPZ(quantity), MPZ(quantity));
|
mpz_neg(MPZ(quantity), MPZ(quantity));
|
||||||
|
|
||||||
in.read((char *)&precision, sizeof(precision));
|
in.read((char *)&quantity->prec, sizeof(quantity->prec));
|
||||||
} else {
|
} else {
|
||||||
unsigned int index;
|
unsigned int index;
|
||||||
in.read((char *)&index, sizeof(index));
|
in.read((char *)&index, sizeof(index));
|
||||||
|
|
@ -931,6 +931,7 @@ void amount_t::read_quantity(std::istream& in)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
commodity_t::updater_t * commodity_t::updater = NULL;
|
commodity_t::updater_t * commodity_t::updater = NULL;
|
||||||
commodities_map commodity_t::commodities;
|
commodities_map commodity_t::commodities;
|
||||||
commodity_t * commodity_t::null_commodity =
|
commodity_t * commodity_t::null_commodity =
|
||||||
|
|
|
||||||
16
amount.h
16
amount.h
|
|
@ -17,21 +17,19 @@ class amount_t
|
||||||
void _copy(const amount_t& amt);
|
void _copy(const amount_t& amt);
|
||||||
void _release();
|
void _release();
|
||||||
void _dup();
|
void _dup();
|
||||||
void _resize(int prec);
|
void _resize(unsigned int prec);
|
||||||
|
|
||||||
void _clear() {
|
void _clear() {
|
||||||
if (quantity)
|
if (quantity)
|
||||||
_release();
|
_release();
|
||||||
quantity = NULL;
|
quantity = NULL;
|
||||||
commodity = NULL;
|
commodity = NULL;
|
||||||
precision = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
class bigint_t;
|
class bigint_t;
|
||||||
|
|
||||||
bigint_t * quantity; // amount, to MAX_PRECISION
|
bigint_t * quantity;
|
||||||
unsigned short precision;
|
|
||||||
commodity_t * commodity;
|
commodity_t * commodity;
|
||||||
|
|
||||||
bool valid() const {
|
bool valid() const {
|
||||||
|
|
@ -43,16 +41,14 @@ class amount_t
|
||||||
|
|
||||||
// constructors
|
// constructors
|
||||||
amount_t(commodity_t * _commodity = NULL)
|
amount_t(commodity_t * _commodity = NULL)
|
||||||
: quantity(NULL), precision(0), commodity(_commodity) {}
|
: quantity(NULL), commodity(_commodity) {}
|
||||||
|
|
||||||
amount_t(const amount_t& amt) : quantity(NULL) {
|
amount_t(const amount_t& amt) : quantity(NULL) {
|
||||||
if (amt.quantity) {
|
if (amt.quantity)
|
||||||
_copy(amt);
|
_copy(amt);
|
||||||
} else {
|
else
|
||||||
precision = 0;
|
|
||||||
commodity = NULL;
|
commodity = NULL;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
amount_t(const std::string& value) : quantity(NULL) {
|
amount_t(const std::string& value) : quantity(NULL) {
|
||||||
parse(value);
|
parse(value);
|
||||||
}
|
}
|
||||||
|
|
@ -80,7 +76,7 @@ class amount_t
|
||||||
amount_t& operator=(const double value);
|
amount_t& operator=(const double value);
|
||||||
|
|
||||||
// general methods
|
// general methods
|
||||||
amount_t round(int prec = -1) const;
|
amount_t round(unsigned int prec) const;
|
||||||
|
|
||||||
// in-place arithmetic
|
// in-place arithmetic
|
||||||
amount_t& operator*=(const amount_t& amt);
|
amount_t& operator*=(const amount_t& amt);
|
||||||
|
|
|
||||||
2
debug.cc
2
debug.cc
|
|
@ -103,14 +103,12 @@ static struct init_streams {
|
||||||
free_debug_stream = true;
|
free_debug_stream = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#ifndef NO_CLEANUP
|
|
||||||
~init_streams() {
|
~init_streams() {
|
||||||
if (free_debug_stream && debug_stream) {
|
if (free_debug_stream && debug_stream) {
|
||||||
delete debug_stream;
|
delete debug_stream;
|
||||||
debug_stream = NULL;
|
debug_stream = NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
} _debug_init;
|
} _debug_init;
|
||||||
|
|
||||||
} // namespace ledger
|
} // namespace ledger
|
||||||
|
|
|
||||||
12
error.cc
12
error.cc
|
|
@ -1,12 +0,0 @@
|
||||||
#include "error.h"
|
|
||||||
|
|
||||||
namespace ledger {
|
|
||||||
|
|
||||||
const char* parse_error::what() const throw()
|
|
||||||
{
|
|
||||||
std::ostringstream msg;
|
|
||||||
msg << file << ", line " << line << ": " << error::what();
|
|
||||||
return msg.str().c_str();
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace ledger
|
|
||||||
6
error.h
6
error.h
|
|
@ -58,7 +58,11 @@ class parse_error : public error {
|
||||||
: error(reason), line(_line), file(_file) {}
|
: error(reason), line(_line), file(_file) {}
|
||||||
virtual ~parse_error() throw() {}
|
virtual ~parse_error() throw() {}
|
||||||
|
|
||||||
virtual const char* what() const throw();
|
virtual const char* what() const throw() {
|
||||||
|
std::ostringstream msg;
|
||||||
|
msg << file << ", line " << line << ": " << error::what();
|
||||||
|
return msg.str().c_str();
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace ledger
|
} // namespace ledger
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue