diff options
author | John Wiegley <johnw@newartisans.com> | 2010-06-02 06:24:25 -0400 |
---|---|---|
committer | John Wiegley <johnw@newartisans.com> | 2010-06-02 06:24:25 -0400 |
commit | cbc0a125c0326d8c638362fa979e41369fed29f5 (patch) | |
tree | e61d882862c0dd06dd9c0357ae4345ea931ced26 | |
parent | 90d5ef83b60c8ba6d4b8971d82e3d2ec4bf1d0b6 (diff) | |
download | fork-ledger-cbc0a125c0326d8c638362fa979e41369fed29f5.tar.gz fork-ledger-cbc0a125c0326d8c638362fa979e41369fed29f5.tar.bz2 fork-ledger-cbc0a125c0326d8c638362fa979e41369fed29f5.zip |
Correct display of amounts with keep_precision
Fixes #167 / 1D275740-D1A6-42B7-BDE4-F2F85E30CE8E
-rw-r--r-- | src/amount.cc | 52 | ||||
-rw-r--r-- | test/regress/1D275740.test | 177 | ||||
-rw-r--r-- | test/regress/2E3496BD.test | 2 |
3 files changed, 217 insertions, 14 deletions
diff --git a/src/amount.cc b/src/amount.cc index 1cba92f8..9b7c3676 100644 --- a/src/amount.cc +++ b/src/amount.cc @@ -47,6 +47,8 @@ static mpz_t temp; static mpq_t tempq; static mpfr_t tempf; static mpfr_t tempfb; +static mpfr_t tempfnum; +static mpfr_t tempfden; #endif struct amount_t::bigint_t : public supports_flags<> @@ -111,7 +113,7 @@ bool amount_t::is_initialized = false; namespace { void stream_out_mpq(std::ostream& out, mpq_t quant, - amount_t::precision_t prec, + amount_t::precision_t precision, int zeros_prec = -1, const optional<commodity_t&>& comm = none) { @@ -125,17 +127,39 @@ namespace { // Convert the rational number to a floating-point, extending the // floating-point to a large enough size to get a precise answer. - const std::size_t bits = (mpz_sizeinbase(mpq_numref(quant), 2) + - mpz_sizeinbase(mpq_denref(quant), 2)); - mpfr_set_prec(tempfb, bits + amount_t::extend_by_digits*8); - mpfr_set_q(tempfb, quant, GMP_RNDN); - if (mpfr_asprintf(&buf, "%.*Rf", prec, tempfb) < 0) + mp_prec_t num_prec = mpz_sizeinbase(mpq_numref(quant), 2); + num_prec += amount_t::extend_by_digits*64; + if (num_prec < MPFR_PREC_MIN) + num_prec = MPFR_PREC_MIN; + DEBUG("amount.convert", "num prec = " << num_prec); + + mpfr_set_prec(tempfnum, num_prec); + mpfr_set_z(tempfnum, mpq_numref(quant), GMP_RNDN); + + mp_prec_t den_prec = mpz_sizeinbase(mpq_denref(quant), 2); + den_prec += amount_t::extend_by_digits*64; + if (den_prec < MPFR_PREC_MIN) + den_prec = MPFR_PREC_MIN; + DEBUG("amount.convert", "den prec = " << den_prec); + + mpfr_set_prec(tempfden, den_prec); + mpfr_set_z(tempfden, mpq_denref(quant), GMP_RNDN); + + mpfr_set_prec(tempfb, num_prec + den_prec); + mpfr_div(tempfb, tempfnum, tempfden, GMP_RNDN); + + char bigbuf[4096]; + mpfr_sprintf(bigbuf, "%.RNf", tempfb); + DEBUG("amount.convert", "num/den = " << bigbuf); + + if (mpfr_asprintf(&buf, "%.*RNf", precision, tempfb) < 0) throw_(amount_error, _("Cannot output amount to a floating-point representation")); - DEBUG("amount.convert", - "mpfr_print = " << buf << " (precision " << prec << ")"); + DEBUG("amount.convert", "mpfr_print = " << buf + << " (precision " << precision + << ", zeros_prec " << zeros_prec << ")"); if (zeros_prec >= 0) { string::size_type index = std::strlen(buf); @@ -211,6 +235,8 @@ void amount_t::initialize() mpq_init(tempq); mpfr_init(tempf); mpfr_init(tempfb); + mpfr_init(tempfnum); + mpfr_init(tempfden); commodity_pool_t::current_pool.reset(new commodity_pool_t); @@ -238,6 +264,8 @@ void amount_t::shutdown() mpq_clear(tempq); mpfr_clear(tempf); mpfr_clear(tempfb); + mpfr_clear(tempfnum); + mpfr_clear(tempfden); commodity_pool_t::current_pool.reset(); @@ -556,12 +584,10 @@ amount_t::precision_t amount_t::display_precision() const commodity_t& comm(commodity()); - if (! comm || keep_precision()) - return quantity->prec; - else if (comm.precision() != quantity->prec) + if (comm && ! keep_precision()) return comm.precision(); else - return quantity->prec; + return comm ? std::max(quantity->prec, comm.precision()) : quantity->prec; } void amount_t::in_place_negate() @@ -643,7 +669,7 @@ void amount_t::in_place_floor() _dup(); std::ostringstream out; - stream_out_mpq(out, MP(quantity), 0); + stream_out_mpq(out, MP(quantity), precision_t(0)); mpq_set_str(MP(quantity), out.str().c_str(), 10); } diff --git a/test/regress/1D275740.test b/test/regress/1D275740.test new file mode 100644 index 00000000..72eb1769 --- /dev/null +++ b/test/regress/1D275740.test @@ -0,0 +1,177 @@ +print +<<< +D 1.200,40 € + +1999/11/01 * Achat + Actif:SSB 125 STK + Actif:SSB -1672,42 $ + +1999/11/04 * Vente + Actif:SSB -125 STK + Dépense:SSB:Commissions 55,07 $ + Actif:SSB 1821,54 $ + +2001/05/01 * Vente + Actif:SSEA -188,7974 STK @ 14,200 $ + Dépense:SSEA:Commissions 19,60 $ + Actif:SSEA 2661,32 $ + +2001/12/21 * Achat + Actif:LPG 7,34316 AMD @ 200,340 € + Actif:LPG -1471,13 € + +2002/12/31 * Réinv. des dividendes + Actif:LPG 0,03032 AMD @ 135,060 € + Revenu:Dividende:AMD -4,10 € + +2003/12/31 * Réinv. des dividendes + Actif:LPG 0,02356 AMD @ 147,830 € + Revenu:Dividende:AMD -3,48 € + +2004/02/17 * Vente + Actif:LPG -7,39704 AMD @ 148,860 € + Actif:LPG 1101,12 € + +2005/12/31 * Réinv. des dividendes + Actif:LPG 0,87704 LAPD @ 22,680 € + Revenu:Dividende:LAPD -19,89 € + +2006/06/30 * Achat + Actif:CPE 54,7328 PM @ 33,200 € + Actif:CPE -1817,13 € + +2006/06/30 * Achat + Actif:CPE 13,8913 PM @ 33,200 € + Actif:CPE -461,19 € + +2007/04/01 Achat + Actif:SV 0,2087 CE @ 622,900 € + Actif:BC -130,00 € + +2007/12/27 Vente + Actif:SV -0,2086 EA @ 183,800 € + Actif:SV 38,34 € + +2008/01/01 Achat + Actif:SV 0,1757 CE @ 739,900 € + Actif:BC -130,00 € + +2008/02/01 Achat + Actif:SV 3,1863 EA @ 163,200 € + Actif:BC -520,00 € + +2008/05/01 Achat + Actif:SV 0,2599 CE @ 654,100 € + Actif:BC -170,00 € + +2008/10/30 Vente + Actif:SV -0,0405 CD @ 155,800 € + Actif:SV 6,31 € + +2008/12/31 Vente + Actif:SV -0,0357 MFE @ 259,100 € + Actif:SV 9,25 € + +2009/06/29 Vente + Actif:SV -0,0786 CD @ 155,600 € + Actif:SV 12,23 € + +2009/07/30 Vente + Actif:SV -0,0417 MFE @ 321,100 € + Actif:SV 13,39 € + +2009/08/01 Achat + Actif:SV 1,0204 MFE @ 333,200 € + Actif:BC -340,00 € + +2009/09/29 Vente + Actif:SV -0,0415 MFE @ 358,800 € + Actif:SV 14,89 € +>>>1 +1999/11/01 * Achat + Actif:SSB 125,0000 STK @ 13,37936 $ + Actif:SSB -1672,42 $ + +1999/11/04 * Vente + Actif:SSB -125,0000 STK @ 15,01288 $ + Dépense:SSB:Commissions 55,07 $ + Actif:SSB 1821,54 $ + +2001/05/01 * Vente + Actif:SSEA -188,7974 STK @ 14,20 $ + Dépense:SSEA:Commissions 19,60 $ + Actif:SSEA 2661,32 $ + +2001/12/21 * Achat + Actif:LPG 7,34316 AMD @ 200,34 € + Actif:LPG -1.471,13 € + +2002/12/31 * Réinv. des dividendes + Actif:LPG 0,03032 AMD @ 135,06 € + Revenu:Dividende:AMD -4,10 € + +2003/12/31 * Réinv. des dividendes + Actif:LPG 0,02356 AMD @ 147,83 € + Revenu:Dividende:AMD -3,48 € + +2004/02/17 * Vente + Actif:LPG -7,39704 AMD @ 148,86 € + Actif:LPG 1.101,12 € + +2005/12/31 * Réinv. des dividendes + Actif:LPG 0,87704 LAPD @ 22,68 € + Revenu:Dividende:LAPD -19,89 € + +2006/06/30 * Achat + Actif:CPE 54,7328 PM @ 33,20 € + Actif:CPE -1.817,13 € + +2006/06/30 * Achat + Actif:CPE 13,8913 PM @ 33,20 € + Actif:CPE -461,19 € + +2007/04/01 Achat + Actif:SV 0,2087 CE @ 622,90 € + Actif:BC -130,00 € + +2007/12/27 Vente + Actif:SV -0,2086 EA @ 183,80 € + Actif:SV 38,34 € + +2008/01/01 Achat + Actif:SV 0,1757 CE @ 739,90 € + Actif:BC -130,00 € + +2008/02/01 Achat + Actif:SV 3,1863 EA @ 163,20 € + Actif:BC -520,00 € + +2008/05/01 Achat + Actif:SV 0,2599 CE @ 654,10 € + Actif:BC -170,00 € + +2008/10/30 Vente + Actif:SV -0,0405 CD @ 155,80 € + Actif:SV 6,31 € + +2008/12/31 Vente + Actif:SV -0,0357 MFE @ 259,10 € + Actif:SV 9,25 € + +2009/06/29 Vente + Actif:SV -0,0786 CD @ 155,60 € + Actif:SV 12,23 € + +2009/07/30 Vente + Actif:SV -0,0417 MFE @ 321,10 € + Actif:SV 13,39 € + +2009/08/01 Achat + Actif:SV 1,0204 MFE @ 333,20 € + Actif:BC -340,00 € + +2009/09/29 Vente + Actif:SV -0,0415 MFE @ 358,80 € + Actif:SV 14,89 € +>>>2 +=== 0 diff --git a/test/regress/2E3496BD.test b/test/regress/2E3496BD.test index cb105f08..466464b3 100644 --- a/test/regress/2E3496BD.test +++ b/test/regress/2E3496BD.test @@ -15,6 +15,6 @@ While balancing transaction from "$FILE", lines 3-5: Unbalanced remainder is: 100.00 USD Amount to balance against: - 1,600.0 USD + 1,600.00 USD Error: Transaction does not balance === 1 |