diff options
Diffstat (limited to 'src/amount.cc')
-rw-r--r-- | src/amount.cc | 584 |
1 files changed, 58 insertions, 526 deletions
diff --git a/src/amount.cc b/src/amount.cc index bc7d5a6a..ae61495c 100644 --- a/src/amount.cc +++ b/src/amount.cc @@ -47,26 +47,18 @@ bool amount_t::stream_fullstrings = false; #if !defined(THREADSAFE) // These global temporaries are pre-initialized for the sake of // efficiency, and are reused over and over again. -static mpz_t temp; +static mpz_t temp; +static mpq_t tempq; static mpfr_t tempf; -#ifdef INTEGER_MATH -static mpz_t divisor; -#else -static mpq_t tempq; static mpfr_t tempfb; #endif -#endif struct amount_t::bigint_t : public supports_flags<> { #define BIGINT_BULK_ALLOC 0x01 #define BIGINT_KEEP_PREC 0x02 -#ifdef INTEGER_MATH - mpz_t val; -#else mpq_t val; -#endif precision_t prec; uint_least16_t ref; uint_fast32_t index; @@ -75,31 +67,19 @@ struct amount_t::bigint_t : public supports_flags<> bigint_t() : prec(0), ref(1), index(0) { TRACE_CTOR(bigint_t, ""); -#ifdef INTEGER_MATH - mpz_init(val); -#else mpq_init(val); -#endif } bigint_t(const bigint_t& other) : supports_flags<>(other.flags() & ~BIGINT_BULK_ALLOC), prec(other.prec), ref(1), index(0) { TRACE_CTOR(bigint_t, "copy"); -#ifdef INTEGER_MATH - mpz_init_set(val, other.val); -#else mpq_init(val); mpq_set(val, other.val); -#endif } ~bigint_t() { TRACE_DTOR(bigint_t); assert(ref == 0); -#ifdef INTEGER_MATH - mpz_clear(val); -#else mpq_clear(val); -#endif } bool valid() const { @@ -125,15 +105,11 @@ amount_t * one = NULL; void amount_t::initialize() { mpz_init(temp); - mpfr_init(tempf); -#ifdef INTEGER_MATH - mpz_init(divisor); -#else mpq_init(tempq); + mpfr_init(tempf); mpfr_init(tempfb); -#endif - one = new amount_t(amount_t(1L).unround()); + one = new amount_t(amount_t(1L).unrounded()); if (! current_pool) current_pool = new commodity_pool_t; @@ -153,13 +129,9 @@ void amount_t::initialize() void amount_t::shutdown() { mpz_clear(temp); - mpfr_clear(tempf); -#ifdef INTEGER_MATH - mpz_clear(divisor); -#else mpq_clear(tempq); + mpfr_clear(tempf); mpfr_clear(tempfb); -#endif checked_delete(one); @@ -206,28 +178,6 @@ void amount_t::_dup() assert(valid()); } -#ifdef INTEGER_MATH - -void amount_t::_resize(precision_t prec) -{ - assert(prec < 256); - - if (! quantity || prec == quantity->prec) - return; - - _dup(); - - assert(prec > quantity->prec); - mpz_ui_pow_ui(divisor, 10, prec - quantity->prec); - mpz_mul(MP(quantity), MP(quantity), divisor); - - quantity->prec = prec; - - assert(valid()); -} - -#endif // INTEGER_MATH - void amount_t::_clear() { if (quantity) { @@ -262,12 +212,7 @@ amount_t::amount_t(const double val) : commodity_(NULL) { TRACE_CTOR(amount_t, "const double"); quantity = new bigint_t; -#ifdef INTEGER_MATH - mpfr_set_d(tempf, val, GMP_RNDN); - mpfr_get_z(MP(quantity), tempf); -#else mpq_set_d(MP(quantity), val); -#endif quantity->prec = extend_by_digits; // an approximation } @@ -275,22 +220,14 @@ amount_t::amount_t(const unsigned long val) : commodity_(NULL) { TRACE_CTOR(amount_t, "const unsigned long"); quantity = new bigint_t; -#ifdef INTEGER_MATH - mpz_set_ui(MP(quantity), val); -#else mpq_set_ui(MP(quantity), val, 1); -#endif } amount_t::amount_t(const long val) : commodity_(NULL) { TRACE_CTOR(amount_t, "const long"); quantity = new bigint_t; -#ifdef INTEGER_MATH - mpz_set_si(MP(quantity), val); -#else mpq_set_si(MP(quantity), val, 1); -#endif } @@ -325,23 +262,7 @@ int amount_t::compare(const amount_t& amt) const "Cannot compare amounts with different commodities: " << commodity().symbol() << " and " << amt.commodity().symbol()); -#ifdef INTEGER_MATH - if (quantity->prec == amt.quantity->prec) { - return mpz_cmp(MP(quantity), MP(amt.quantity)); - } - else if (quantity->prec < amt.quantity->prec) { - amount_t t(*this); - t._resize(amt.quantity->prec); - return mpz_cmp(MP(t.quantity), MP(amt.quantity)); - } - else { - amount_t t = amt; - t._resize(quantity->prec); - return mpz_cmp(MP(quantity), MP(t.quantity)); - } -#else return mpq_cmp(MP(quantity), MP(amt.quantity)); -#endif } @@ -367,25 +288,10 @@ amount_t& amount_t::operator+=(const amount_t& amt) _dup(); -#ifdef INTEGER_MATH - if (quantity->prec == amt.quantity->prec) { - mpz_add(MP(quantity), MP(quantity), MP(amt.quantity)); - } - else if (quantity->prec < amt.quantity->prec) { - _resize(amt.quantity->prec); - mpz_add(MP(quantity), MP(quantity), MP(amt.quantity)); - } - else { - amount_t t = amt; - t._resize(quantity->prec); - mpz_add(MP(quantity), MP(quantity), MP(t.quantity)); - } -#else mpq_add(MP(quantity), MP(quantity), MP(amt.quantity)); if (quantity->prec < amt.quantity->prec) quantity->prec = amt.quantity->prec; -#endif return *this; } @@ -412,81 +318,14 @@ amount_t& amount_t::operator-=(const amount_t& amt) _dup(); -#ifdef INTEGER_MATH - if (quantity->prec == amt.quantity->prec) { - mpz_sub(MP(quantity), MP(quantity), MP(amt.quantity)); - } - else if (quantity->prec < amt.quantity->prec) { - _resize(amt.quantity->prec); - mpz_sub(MP(quantity), MP(quantity), MP(amt.quantity)); - } - else { - amount_t t = amt; - t._resize(quantity->prec); - mpz_sub(MP(quantity), MP(quantity), MP(t.quantity)); - } -#else mpq_sub(MP(quantity), MP(quantity), MP(amt.quantity)); if (quantity->prec < amt.quantity->prec) quantity->prec = amt.quantity->prec; -#endif return *this; } -#ifdef INTEGER_MATH - -namespace { - void mpz_round(mpz_t out, mpz_t value, int value_prec, int round_prec) - { - // Round `value', with an encoding precision of `value_prec', to a - // rounded value with precision `round_prec'. Result is stored in - // `out'. - - assert(value_prec > round_prec); - - mpz_t quotient; - mpz_t remainder; - - mpz_init(quotient); - mpz_init(remainder); - - mpz_ui_pow_ui(divisor, 10, value_prec - round_prec); - mpz_tdiv_qr(quotient, remainder, value, divisor); - mpz_divexact_ui(divisor, divisor, 10); - mpz_mul_ui(divisor, divisor, 5); - - if (mpz_sgn(remainder) < 0) { - mpz_neg(divisor, divisor); - if (mpz_cmp(remainder, divisor) < 0) { - mpz_ui_pow_ui(divisor, 10, value_prec - round_prec); - mpz_add(remainder, divisor, remainder); - mpz_ui_sub(remainder, 0, remainder); - mpz_add(out, value, remainder); - } else { - mpz_sub(out, value, remainder); - } - } else { - if (mpz_cmp(remainder, divisor) >= 0) { - mpz_ui_pow_ui(divisor, 10, value_prec - round_prec); - mpz_sub(remainder, divisor, remainder); - mpz_add(out, value, remainder); - } else { - mpz_sub(out, value, remainder); - } - } - mpz_clear(quotient); - mpz_clear(remainder); - - // chop off the rounded bits - mpz_ui_pow_ui(divisor, 10, value_prec - round_prec); - mpz_tdiv_q(out, out, divisor); - } -} - -#endif // INTEGER_MATH - amount_t& amount_t::operator*=(const amount_t& amt) { assert(amt.valid()); @@ -502,11 +341,7 @@ amount_t& amount_t::operator*=(const amount_t& amt) _dup(); -#ifdef INTEGER_MATH - mpz_mul(MP(quantity), MP(quantity), MP(amt.quantity)); -#else mpq_mul(MP(quantity), MP(quantity), MP(amt.quantity)); -#endif quantity->prec += amt.quantity->prec; if (! has_commodity()) @@ -514,13 +349,8 @@ amount_t& amount_t::operator*=(const amount_t& amt) if (has_commodity() && ! keep_precision()) { precision_t comm_prec = commodity().precision(); - if (quantity->prec > comm_prec + extend_by_digits) { -#ifdef INTEGER_MATH - mpz_round(MP(quantity), MP(quantity), quantity->prec, - comm_prec + extend_by_digits); -#endif // INTEGER_MATH + if (quantity->prec > comm_prec + extend_by_digits) quantity->prec = comm_prec + extend_by_digits; - } } return *this; @@ -547,19 +377,8 @@ amount_t& amount_t::operator/=(const amount_t& amt) // Increase the value's precision, to capture fractional parts after // the divide. Round up in the last position. -#ifdef INTEGER_MATH - mpz_ui_pow_ui(divisor, 10, (2 * amt.quantity->prec) + quantity->prec + - extend_by_digits + 1U); - mpz_mul(MP(quantity), MP(quantity), divisor); - mpz_tdiv_q(MP(quantity), MP(quantity), MP(amt.quantity)); - quantity->prec += amt.quantity->prec + quantity->prec + extend_by_digits + 1U; - - mpz_round(MP(quantity), MP(quantity), quantity->prec, quantity->prec - 1); - quantity->prec -= 1; -#else mpq_div(MP(quantity), MP(quantity), MP(amt.quantity)); quantity->prec += amt.quantity->prec + quantity->prec + extend_by_digits; -#endif if (! has_commodity()) commodity_ = amt.commodity_; @@ -571,13 +390,8 @@ amount_t& amount_t::operator/=(const amount_t& amt) if (has_commodity() && ! keep_precision()) { precision_t comm_prec = commodity().precision(); - if (quantity->prec > comm_prec + extend_by_digits) { -#ifdef INTEGER_MATH - mpz_round(MP(quantity), MP(quantity), quantity->prec, - comm_prec + extend_by_digits); -#endif // INTEGER_MATH + if (quantity->prec > comm_prec + extend_by_digits) quantity->prec = comm_prec + extend_by_digits; - } } return *this; @@ -634,59 +448,28 @@ amount_t& amount_t::in_place_negate() { if (quantity) { _dup(); -#ifdef INTEGER_MATH - mpz_neg(MP(quantity), MP(quantity)); -#else mpq_neg(MP(quantity), MP(quantity)); -#endif } else { throw_(amount_error, "Cannot negate an uninitialized amount"); } return *this; } -#ifdef INTEGER_MATH - -amount_t& amount_t::in_place_round() -{ - if (! quantity) - throw_(amount_error, "Cannot round an uninitialized amount"); - - if (has_commodity()) - in_place_round(commodity().precision()); - - return *this; -} - -amount_t& amount_t::in_place_round(precision_t prec) +amount_t amount_t::rounded() const { if (! quantity) - throw_(amount_error, "Cannot round an uninitialized amount"); - - if (quantity && quantity->prec <= prec) { - if (keep_precision()) { - _dup(); - set_keep_precision(false); - } + throw_(amount_error, "Cannot set rounding for an uninitialized amount"); + else if (! keep_precision()) return *this; - } - - DEBUG("amount.round", "Rounding " << *this << " to precision " << prec); - - _dup(); - mpz_round(MP(quantity), MP(quantity), quantity->prec, prec); - - quantity->prec = prec; - set_keep_precision(false); - DEBUG("amount.round", " result = " << *this); + amount_t t(*this); + t._dup(); + t.set_keep_precision(false); - return *this; + return t; } -#endif // INTEGER_MATH - -amount_t amount_t::unround() const +amount_t amount_t::unrounded() const { if (! quantity) throw_(amount_error, "Cannot unround an uninitialized amount"); @@ -732,11 +515,7 @@ optional<amount_t> amount_t::value(const optional<datetime_t>& moment, if (quantity) { optional<price_point_t> point(commodity().find_price(in_terms_of, moment)); if (point) -#ifdef INTEGER_MATH - return (point->price * number()).round(); -#else - return point->price * number(); -#endif + return (point->price * number()).rounded(); } else { throw_(amount_error, "Cannot determine value of an uninitialized amount"); } @@ -749,15 +528,9 @@ int amount_t::sign() const if (! quantity) throw_(amount_error, "Cannot determine sign of an uninitialized amount"); -#ifdef INTEGER_MATH - return mpz_sgn(MP(quantity)); -#else return mpq_sgn(MP(quantity)); -#endif } -#ifndef INTEGER_MATH - namespace { void stream_out_mpq(std::ostream& out, mpq_t quant, amount_t::precision_t prec, @@ -826,8 +599,6 @@ namespace { } } -#endif // INTEGER_MATH - bool amount_t::is_zero() const { if (! quantity) @@ -837,9 +608,6 @@ bool amount_t::is_zero() const if (keep_precision() || quantity->prec <= commodity().precision()) { return is_realzero(); } else { -#ifdef INTEGER_MATH - return round(commodity().precision()).sign() == 0; -#else std::ostringstream out; stream_out_mpq(out, MP(quantity), commodity().precision()); @@ -847,80 +615,34 @@ bool amount_t::is_zero() const if (*p != '0' && *p != '.') return false; return true; -#endif } } return is_realzero(); } -double amount_t::to_double(bool no_check) const +double amount_t::to_double() const { if (! quantity) throw_(amount_error, "Cannot convert an uninitialized amount to a double"); -#ifdef INTEGER_MATH - mpz_t remainder; - mpz_init(remainder); - - mpz_set(temp, MP(quantity)); - mpz_ui_pow_ui(divisor, 10, quantity->prec); - mpz_tdiv_qr(temp, remainder, temp, divisor); - - char * quotient_s = mpz_get_str(NULL, 10, temp); - char * remainder_s = mpz_get_str(NULL, 10, remainder); - - std::ostringstream num; - num << quotient_s << '.' << remainder_s; - - std::free(quotient_s); - std::free(remainder_s); - - mpz_clear(remainder); - - double value = lexical_cast<double>(num.str()); -#else mpfr_set_q(tempf, MP(quantity), GMP_RNDN); - double value = mpfr_get_d(tempf, GMP_RNDN); -#endif - - if (! no_check && *this != value) - throw_(amount_error, "Conversion of amount to_double loses precision"); - - return value; + return mpfr_get_d(tempf, GMP_RNDN); } -long amount_t::to_long(bool no_check) const +long amount_t::to_long() const { if (! quantity) throw_(amount_error, "Cannot convert an uninitialized amount to a long"); -#ifdef INTEGER_MATH - mpz_set(temp, MP(quantity)); - mpz_ui_pow_ui(divisor, 10, quantity->prec); - mpz_tdiv_q(temp, temp, divisor); - long value = mpz_get_si(temp); -#else mpfr_set_q(tempf, MP(quantity), GMP_RNDN); - long value = mpfr_get_si(tempf, GMP_RNDN); -#endif - - if (! no_check && *this != value) - throw_(amount_error, "Conversion of amount to_long loses precision"); - - return value; -} - -bool amount_t::fits_in_double() const -{ - double value = to_double(true); - return *this == amount_t(value); + return mpfr_get_si(tempf, GMP_RNDN); } bool amount_t::fits_in_long() const { - long value = to_long(true); - return *this == amount_t(value); + mpfr_set_q(tempf, MP(quantity), GMP_RNDN); + return mpfr_fits_slong_p(tempf, GMP_RNDN); } @@ -1170,9 +892,6 @@ bool amount_t::parse(std::istream& in, const parse_flags_t& flags) } *t = '\0'; -#ifdef INTEGER_MATH - mpz_set_str(MP(quantity), buf.get(), 10); -#else mpq_set_str(MP(quantity), buf.get(), 10); mpz_ui_pow_ui(temp, 10, quantity->prec); mpq_set_z(tempq, temp); @@ -1183,13 +902,8 @@ bool amount_t::parse(std::istream& in, const parse_flags_t& flags) DEBUG("amount.parse", "Rational parsed = " << buf); std::free(buf); } -#endif } else { -#ifdef INTEGER_MATH - mpz_set_str(MP(quantity), quant.c_str(), 10); -#else mpq_set_str(MP(quantity), quant.c_str(), 10); -#endif } if (negative) @@ -1243,156 +957,6 @@ void amount_t::print(std::ostream& _out, bool omit_commodity, commodity_t& comm(base.commodity()); precision_t precision = 0; -#ifdef INTEGER_MATH - - mpz_t quotient; - mpz_t rquotient; - mpz_t remainder; - - mpz_init(quotient); - mpz_init(rquotient); - mpz_init(remainder); - - bool negative = false; - - // Ensure the value is rounded to the commodity's precision before - // outputting it. NOTE: `rquotient' is used here as a temp variable! - - if (quantity) { - if (! comm || full_precision || base.keep_precision()) { - mpz_ui_pow_ui(divisor, 10, base.quantity->prec); - mpz_tdiv_qr(quotient, remainder, MP(base.quantity), divisor); - precision = base.quantity->prec; - } - else if (comm.precision() < base.quantity->prec) { - mpz_round(rquotient, MP(base.quantity), base.quantity->prec, - comm.precision()); - mpz_ui_pow_ui(divisor, 10, comm.precision()); - mpz_tdiv_qr(quotient, remainder, rquotient, divisor); - precision = comm.precision(); - } - else if (comm.precision() > base.quantity->prec) { - mpz_ui_pow_ui(divisor, 10, comm.precision() - base.quantity->prec); - mpz_mul(rquotient, MP(base.quantity), divisor); - mpz_ui_pow_ui(divisor, 10, comm.precision()); - mpz_tdiv_qr(quotient, remainder, rquotient, divisor); - precision = comm.precision(); - } - else if (base.quantity->prec) { - mpz_ui_pow_ui(divisor, 10, base.quantity->prec); - mpz_tdiv_qr(quotient, remainder, MP(base.quantity), divisor); - precision = base.quantity->prec; - } - else { - mpz_set(quotient, MP(base.quantity)); - mpz_set_ui(remainder, 0); - precision = 0; - } - - if (mpz_sgn(quotient) < 0 || mpz_sgn(remainder) < 0) { - negative = true; - - mpz_abs(quotient, quotient); - mpz_abs(remainder, remainder); - } - mpz_set(rquotient, remainder); - } - - if (! omit_commodity && ! comm.has_flags(COMMODITY_STYLE_SUFFIXED)) { - comm.print(out); - if (comm.has_flags(COMMODITY_STYLE_SEPARATED)) - out << " "; - } - - if (negative) - out << "-"; - - if (! quantity || mpz_sgn(quotient) == 0) { - out << '0'; - } - else if (omit_commodity || ! comm.has_flags(COMMODITY_STYLE_THOUSANDS)) { - char * p = mpz_get_str(NULL, 10, quotient); - out << p; - std::free(p); - } - else { - std::list<string> strs; - char buf[4]; - - for (int powers = 0; true; powers += 3) { - if (powers > 0) { - mpz_ui_pow_ui(divisor, 10, powers); - mpz_tdiv_q(temp, quotient, divisor); - if (mpz_sgn(temp) == 0) - break; - mpz_tdiv_r_ui(temp, temp, 1000); - } else { - mpz_tdiv_r_ui(temp, quotient, 1000); - } - mpz_get_str(buf, 10, temp); - strs.push_back(buf); - } - - bool printed = false; - - for (std::list<string>::reverse_iterator i = strs.rbegin(); - i != strs.rend(); - i++) { - if (printed) { - out << (comm.has_flags(COMMODITY_STYLE_EUROPEAN) ? '.' : ','); - out.width(3); - out.fill('0'); - } - out << *i; - - printed = true; - } - } - - if (quantity && precision) { - std::ostringstream final; - final.width(precision); - final.fill('0'); - char * p = mpz_get_str(NULL, 10, rquotient); - final << p; - std::free(p); - - const string& str(final.str()); - int i, len = str.length(); - const char * q = str.c_str(); - for (i = len; i > 0; i--) - if (q[i - 1] != '0') - break; - - string ender; - if (i == len) - ender = str; - else if (i < comm.precision()) - ender = string(str, 0, comm.precision()); - else - ender = string(str, 0, i); - - if (! ender.empty()) { - if (omit_commodity) - out << '.'; - else - out << (comm.has_flags(COMMODITY_STYLE_EUROPEAN) ? ',' : '.'); - out << ender; - } - } - - if (! omit_commodity && comm.has_flags(COMMODITY_STYLE_SUFFIXED)) { - if (comm.has_flags(COMMODITY_STYLE_SEPARATED)) - out << " "; - comm.print(out); - } - - mpz_clear(quotient); - mpz_clear(rquotient); - mpz_clear(remainder); - -#else // INTEGER_MATH - if (! omit_commodity && ! comm.has_flags(COMMODITY_STYLE_SUFFIXED)) { comm.print(out); if (comm.has_flags(COMMODITY_STYLE_SEPARATED)) @@ -1408,8 +972,6 @@ void amount_t::print(std::ostream& _out, bool omit_commodity, comm.print(out); } -#endif // INTEGER_MATH - // If there are any annotations associated with this commodity, // output them now. @@ -1451,43 +1013,27 @@ void amount_t::read(std::istream& in) if (byte < 3) { quantity = new bigint_t; -#ifndef INTEGER_MATH - mpz_t numerator; - mpz_t denominator; -#endif - unsigned short len; in.read(reinterpret_cast<char *>(&len), sizeof(len)); assert(len < 4096); static char buf[4096]; in.read(buf, len); -#ifdef INTEGER_MATH - mpz_import(MP(quantity), len / sizeof(short), 1, sizeof(short), - 0, 0, buf); -#else - mpz_init(numerator); - mpz_import(numerator, len / sizeof(short), 1, sizeof(short), + + mpz_import(temp, len / sizeof(short), 1, sizeof(short), 0, 0, buf); + mpq_set_num(MP(quantity), temp); in.read(reinterpret_cast<char *>(&len), sizeof(len)); assert(len < 4096); in.read(buf, len); - mpz_init(denominator); - mpz_import(denominator, len / sizeof(short), 1, sizeof(short), + mpz_import(temp, len / sizeof(short), 1, sizeof(short), 0, 0, buf); - - mpq_set_num(MP(quantity), numerator); - mpq_set_den(MP(quantity), denominator); -#endif + mpq_set_den(MP(quantity), temp); char negative; in.read(&negative, sizeof(negative)); if (negative) -#ifdef INTEGER_MATH - mpz_neg(MP(quantity), MP(quantity)); -#else mpq_neg(MP(quantity), MP(quantity)); -#endif in.read(reinterpret_cast<char *>(&quantity->prec), sizeof(quantity->prec)); @@ -1531,40 +1077,28 @@ void amount_t::read(const char *& data, quantity = new bigint_t; } -#ifndef INTEGER_MATH - mpz_t numerator; - mpz_t denominator; -#endif - unsigned short len = *reinterpret_cast<unsigned short *>(const_cast<char *>(data)); data += sizeof(unsigned short); -#ifdef INTEGER_MATH - mpz_import(MP(quantity), len / sizeof(short), 1, sizeof(short), - 0, 0, data); -#else - mpz_init(numerator); - mpz_import(numerator, len / sizeof(short), 1, sizeof(short), + mpz_init(temp); + mpz_import(temp, len / sizeof(short), 1, sizeof(short), 0, 0, data); + data += len; + + mpq_set_num(MP(quantity), temp); len = *reinterpret_cast<unsigned short *>(const_cast<char *>(data)); data += sizeof(unsigned short); - mpz_init(denominator); - mpz_import(denominator, len / sizeof(short), 1, sizeof(short), + mpz_init(temp); + mpz_import(temp, len / sizeof(short), 1, sizeof(short), 0, 0, data); - - mpq_set_num(MP(quantity), numerator); - mpq_set_den(MP(quantity), denominator); -#endif data += len; + mpq_set_den(MP(quantity), temp); + char negative = *data++; if (negative) -#ifdef INTEGER_MATH - mpz_neg(MP(quantity), MP(quantity)); -#else mpq_neg(MP(quantity), MP(quantity)); -#endif quantity->prec = *reinterpret_cast<precision_t *>(const_cast<char *>(data)); data += sizeof(precision_t); @@ -1585,6 +1119,20 @@ void amount_t::read(const char *& data, } } +namespace { + void write_bytes(std::ostream& out, + const char * buf, + const std::size_t size) + { + unsigned short len = size * sizeof(short); + out.write(reinterpret_cast<char *>(&len), sizeof(len)); + if (len) { + assert(len < 4096); + out.write(buf, len); + } + } +} + void amount_t::write(std::ostream& out, std::size_t index) const { using namespace ledger::binary; @@ -1614,32 +1162,16 @@ void amount_t::write(std::ostream& out, std::size_t index) const std::size_t size; static char buf[4096]; -#ifdef INTEGER_MATH - mpz_export(buf, &size, 1, sizeof(short), 0, 0, MP(quantity)); -#else - mpz_t numerator; - mpz_t denominator; - - mpz_init(numerator); - mpq_get_num(numerator, MP(quantity)); - mpz_export(buf, &size, 1, sizeof(short), 0, 0, numerator); - - mpz_init(denominator); - mpq_get_den(denominator, MP(quantity)); - mpz_export(buf, &size, 1, sizeof(short), 0, 0, denominator); -#endif - unsigned short len = size * sizeof(short); - out.write(reinterpret_cast<char *>(&len), sizeof(len)); - if (len) { - assert(len < 4096); - out.write(buf, len); - } -#ifdef INTEGER_MATH - byte = mpz_sgn(MP(quantity)) < 0 ? 1 : 0; -#else + mpq_get_num(temp, MP(quantity)); + mpz_export(buf, &size, 1, sizeof(short), 0, 0, temp); + write_bytes(out, buf, size); + + mpq_get_den(temp, MP(quantity)); + mpz_export(buf, &size, 1, sizeof(short), 0, 0, temp); + write_bytes(out, buf, size); + byte = mpq_sgn(MP(quantity)) < 0 ? 1 : 0; -#endif out.write(&byte, sizeof(byte)); out.write(reinterpret_cast<char *>(&quantity->prec), sizeof(quantity->prec)); |