From 8fc3cb2d90617954e8a441d4f1900cb8b5b3c085 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Beno=C3=AEt=20Minisini?= Date: Sat, 28 Apr 2012 15:08:24 +0000 Subject: [PATCH] [INTERPRETER] * BUG: Fix precision in both string to Float and Float to string conversions. git-svn-id: svn://localhost/gambas/trunk@4688 867c0c6c-44f3-4631-809d-bfa615b0a4ec --- main/gbx/gbx_local.c | 7 +++++-- main/gbx/gbx_math.c | 25 +++++++++++++++++++------ main/gbx/gbx_math.h | 7 +++++-- main/gbx/gbx_number.c | 6 ++++-- 4 files changed, 33 insertions(+), 12 deletions(-) diff --git a/main/gbx/gbx_local.c b/main/gbx/gbx_local.c index c49de4669..3f2c93811 100644 --- a/main/gbx/gbx_local.c +++ b/main/gbx/gbx_local.c @@ -955,16 +955,19 @@ _FORMAT: if (isfinite(number)) { number_mant = frexp10(fabs(number), &number_exp); - ndigit = after; if (!exposant) ndigit += number_exp; ndigit = MinMax(ndigit, 0, MAX_FLOAT_DIGIT); + //fprintf(stderr, "number_mant = %.24g number_exp = %d ndigit = %d\n", number_mant, number_exp, ndigit); + + power = pow10_uint64_p(ndigit + 1); - power = pow10(ndigit + 1); mantisse = number_mant * power; if ((mantisse % 10) >= 5) mantisse += 10; + //fprintf(stderr, "-> power = %" PRId64 " mantisse = %" PRId64 "\n", power, mantisse); + if (mantisse >= power) { ndigit = sprintf(buf, ".%" PRId64, mantisse); diff --git a/main/gbx/gbx_math.c b/main/gbx/gbx_math.c index f57ef521b..f24cbb9af 100644 --- a/main/gbx/gbx_math.c +++ b/main/gbx/gbx_math.c @@ -23,18 +23,17 @@ #define __GBX_MATH_C +#include "gb_common.h" + #include #include #include -#include "gb_common.h" #include "gb_hash.h" #include "gbx_math.h" -const double MATH_pow10[] = { - 1E-10, 1E-9, 1E-8, 1E-7, 1E-6, 1E-5, 1E-4, 1E-3, 1E-2, 0.1, 1, - 10, 100, 1E3, 1E4, 1E5, 1E6, 1E7, 1E8, 1E9, 1E10, 1E11, 1E12, 1E13, 1E14, 1E15, 1E16 -}; +const double MATH_pow10_double[] = {1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000}; +static const uint _pow10_uint[] = {1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000}; /* This is a twisted generalized feedback shift register that generates pseudo-random numbers. @@ -142,7 +141,7 @@ double frexp10(double x, int *exp) } p = (int)log10(x); - x /= pow(10, p); + x /= pow10(p); if (x >= 1) { @@ -225,3 +224,17 @@ void MATH_init(void) HASH_seed = seed; } + +uint64_t pow10_uint64_p(int n) +{ + uint64_t v = 1; + + while (n > 8) + { + v *= 100000000; + n -= 8; + } + v *= _pow10_uint[n]; + return v; +} + diff --git a/main/gbx/gbx_math.h b/main/gbx/gbx_math.h index 4685aefe4..6abbfe15b 100644 --- a/main/gbx/gbx_math.h +++ b/main/gbx/gbx_math.h @@ -31,7 +31,7 @@ #endif #ifndef __GBX_MATH_C -extern const double MATH_pow10[]; +extern const double MATH_pow10_double[]; #endif void MATH_init(void); @@ -46,7 +46,10 @@ float fixf(float x); double fix(double x); double frexp10(double x, int *exp); -#define pow10(_n) (((_n) >= -10 && (_n) <= 16) ? MATH_pow10[(_n) + 10] : exp10(_n)) +#define pow10(_n) (((_n) >= 0 && (_n) <= 9) ? MATH_pow10_double[_n] : (((_n) < 0 && (_n) >= -9) ? (1.0 / MATH_pow10_double[-(_n)]) : exp10(_n))) +//#define mulpow10(_v, _n) (((_n) >= 0 && (_n) <= 9) ? ((_v) * MATH_pow10_double[_n]) : (((_n) < 0 && (_n) >= -9) ? ((_v) / MATH_pow10[-(_n)]) : ((_v) * exp10(_n)))) + +uint64_t pow10_uint64_p(int n); void randomize(bool set, uint seed); double rnd(void); diff --git a/main/gbx/gbx_number.c b/main/gbx/gbx_number.c index f4f232bd8..02e6ebff1 100644 --- a/main/gbx/gbx_number.c +++ b/main/gbx/gbx_number.c @@ -34,7 +34,7 @@ #include "gbx_type.h" #include "gb_common_buffer.h" #include "gbx_local.h" - +#include "gbx_math.h" #include "gbx_string.h" #include "gbx_number.h" @@ -300,7 +300,9 @@ __END: else nexp -= ndigit_frac; - *result = ((double)mantisse * pow10(nexp)); + //fprintf(stderr, "%.24g %d\n", (double)mantisse, nexp); + //*result = mulpow10((double)mantisse, nexp); + *result = (double)mantisse * pow10(nexp); return FALSE; }