From 1838099e00c007613ef3946e852ccc6955a76a18 Mon Sep 17 00:00:00 2001 From: cremno Date: Mon, 17 Feb 2014 12:37:39 +0100 Subject: more mrb_flo_to_str fixes - remove float check (take mrb_float instead of mrb_value) - support -0.0 - fix range error if log10 is called when n == 0.0 - MSVC older than 2013: add signbit macro (for double) --- include/mruby/numeric.h | 2 +- include/mruby/value.h | 1 + src/numeric.c | 28 ++++++++++++++++------------ 3 files changed, 18 insertions(+), 13 deletions(-) diff --git a/include/mruby/numeric.h b/include/mruby/numeric.h index d866d36d1..800f33394 100644 --- a/include/mruby/numeric.h +++ b/include/mruby/numeric.h @@ -16,7 +16,7 @@ extern "C" { #define FIXABLE(f) (POSFIXABLE(f) && NEGFIXABLE(f)) mrb_value mrb_flo_to_fixnum(mrb_state *mrb, mrb_value val); -mrb_value mrb_flo_to_str(mrb_state *mrb, mrb_value flo); +mrb_value mrb_flo_to_str(mrb_state *mrb, mrb_float flo); mrb_value mrb_fixnum_to_str(mrb_state *mrb, mrb_value x, int base); diff --git a/include/mruby/value.h b/include/mruby/value.h index 13acd039e..a0f0c2ef9 100644 --- a/include/mruby/value.h +++ b/include/mruby/value.h @@ -59,6 +59,7 @@ typedef short mrb_sym; # include # define isnan _isnan # define isinf(n) (!_finite(n) && !_isnan(n)) +# define signbit(n) (_copysign(1.0, (n)) < 0.0) # define strtoll _strtoi64 # define strtof (float)strtod # define PRId32 "I32d" diff --git a/src/numeric.c b/src/numeric.c index 0789a7654..f9fddaa76 100644 --- a/src/numeric.c +++ b/src/numeric.c @@ -107,17 +107,11 @@ num_div(mrb_state *mrb, mrb_value x) */ mrb_value -mrb_flo_to_str(mrb_state *mrb, mrb_value flo) +mrb_flo_to_str(mrb_state *mrb, mrb_float flo) { - double n; + double n = (double)flo; int max_digits = FLO_MAX_DIGITS; - if (!mrb_float_p(flo)) { - mrb_raise(mrb, E_TYPE_ERROR, "non float value"); - } - - n = (double)mrb_float(flo); - if (isnan(n)) { return mrb_str_new_lit(mrb, "NaN"); } @@ -137,12 +131,22 @@ mrb_flo_to_str(mrb_state *mrb, mrb_value flo) char s[48]; char *c = &s[0]; - if (n < 0) { + if (signbit(n)) { n = -n; *(c++) = '-'; } - exp = (n > 1) ? floor(log10(n)) : -ceil(-log10(n)); + if (n != 0.0) { + if (n > 1.0) { + exp = (int)floor(log10(n)); + } + else { + exp = (int)-ceil(-log10(n)); + } + } + else { + exp = 0; + } if ((exp < 0 ? -exp : exp) >= FLO_MAX_DIGITS) { /* exponent representation */ @@ -160,7 +164,7 @@ mrb_flo_to_str(mrb_state *mrb, mrb_value flo) while (max_digits >= 0) { double weight = pow(10.0, m); double fdigit = n / weight; - + if (fdigit < 0) fdigit = n = 0; if (m < -1 && fdigit < FLO_EPSILON) { if (e || exp > 0 || m <= -abs(exp)) { @@ -226,7 +230,7 @@ mrb_flo_to_str(mrb_state *mrb, mrb_value flo) static mrb_value flo_to_s(mrb_state *mrb, mrb_value flt) { - return mrb_flo_to_str(mrb, flt); + return mrb_flo_to_str(mrb, mrb_float(flt)); } /* 15.2.9.3.2 */ -- cgit v1.2.3 From 61577e8d6b69efe8da23070abab0dfc7a00f5ee3 Mon Sep 17 00:00:00 2001 From: cremno Date: Tue, 18 Feb 2014 04:37:35 +0100 Subject: mrb_flo_to_str: internal linkage --- include/mruby/numeric.h | 1 - src/numeric.c | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/include/mruby/numeric.h b/include/mruby/numeric.h index 800f33394..d0305160c 100644 --- a/include/mruby/numeric.h +++ b/include/mruby/numeric.h @@ -16,7 +16,6 @@ extern "C" { #define FIXABLE(f) (POSFIXABLE(f) && NEGFIXABLE(f)) mrb_value mrb_flo_to_fixnum(mrb_state *mrb, mrb_value val); -mrb_value mrb_flo_to_str(mrb_state *mrb, mrb_float flo); mrb_value mrb_fixnum_to_str(mrb_state *mrb, mrb_value x, int base); diff --git a/src/numeric.c b/src/numeric.c index f9fddaa76..2140a8411 100644 --- a/src/numeric.c +++ b/src/numeric.c @@ -106,7 +106,7 @@ num_div(mrb_state *mrb, mrb_value x) * representation. */ -mrb_value +static mrb_value mrb_flo_to_str(mrb_state *mrb, mrb_float flo) { double n = (double)flo; -- cgit v1.2.3