Commit 3ce51cbc authored by Yukihiro "Matz" Matsumoto's avatar Yukihiro "Matz" Matsumoto Committed by GitHub

Merge pull request #3257 from ksss/range-size

Fix Range#size results
parents 0ff3ae1f 22390aa1
#include <mruby.h> #include <mruby.h>
#include <mruby/range.h> #include <mruby/range.h>
#include <math.h> #include <math.h>
#include <float.h>
static mrb_bool static mrb_bool
r_le(mrb_state *mrb, mrb_value a, mrb_value b) r_le(mrb_state *mrb, mrb_value a, mrb_value b)
...@@ -138,13 +139,15 @@ mrb_range_size(mrb_state *mrb, mrb_value range) ...@@ -138,13 +139,15 @@ mrb_range_size(mrb_state *mrb, mrb_value range)
{ {
struct RRange *r = mrb_range_ptr(range); struct RRange *r = mrb_range_ptr(range);
mrb_value beg, end; mrb_value beg, end;
double beg_f, end_f; mrb_float beg_f, end_f;
mrb_bool num_p = TRUE; mrb_bool num_p = TRUE;
mrb_bool excl;
beg = r->edges->beg; beg = r->edges->beg;
end = r->edges->end; end = r->edges->end;
excl = r->excl;
if (mrb_fixnum_p(beg)) { if (mrb_fixnum_p(beg)) {
beg_f = (double)mrb_fixnum(beg); beg_f = (mrb_float)mrb_fixnum(beg);
} }
else if (mrb_float_p(beg)) { else if (mrb_float_p(beg)) {
beg_f = mrb_float(beg); beg_f = mrb_float(beg);
...@@ -153,7 +156,7 @@ mrb_range_size(mrb_state *mrb, mrb_value range) ...@@ -153,7 +156,7 @@ mrb_range_size(mrb_state *mrb, mrb_value range)
num_p = FALSE; num_p = FALSE;
} }
if (mrb_fixnum_p(end)) { if (mrb_fixnum_p(end)) {
end_f = (double)mrb_fixnum(end); end_f = (mrb_float)mrb_fixnum(end);
} }
else if (mrb_float_p(end)) { else if (mrb_float_p(end)) {
end_f = mrb_float(end); end_f = mrb_float(end);
...@@ -162,14 +165,24 @@ mrb_range_size(mrb_state *mrb, mrb_value range) ...@@ -162,14 +165,24 @@ mrb_range_size(mrb_state *mrb, mrb_value range)
num_p = FALSE; num_p = FALSE;
} }
if (num_p) { if (num_p) {
double f; mrb_float n = end_f - beg_f;
mrb_float err = (fabs(beg_f) + fabs(end_f) + fabs(end_f-beg_f)) * DBL_EPSILON;
if (beg_f > end_f) return mrb_fixnum_value(0);
f = end_f - beg_f; if (err>0.5) err=0.5;
if (!r->excl) { if (excl) {
return mrb_fixnum_value((mrb_int)ceil(f + 1)); if (n<=0) return mrb_fixnum_value(0);
if (n<1)
n = 0;
else
n = floor(n - err);
}
else {
if (n<0) return mrb_fixnum_value(0);
n = floor(n + err);
} }
return mrb_fixnum_value((mrb_int)ceil(f)); if (isinf(n+1))
return mrb_float_value(mrb, INFINITY);
return mrb_fixnum_value(n+1);
} }
return mrb_nil_value(); return mrb_nil_value();
} }
......
...@@ -25,5 +25,7 @@ assert('Range#size') do ...@@ -25,5 +25,7 @@ assert('Range#size') do
assert_equal 6, (1...6.3).size assert_equal 6, (1...6.3).size
assert_equal 5, (1...6.0).size assert_equal 5, (1...6.0).size
assert_equal 5, (1.1...6).size assert_equal 5, (1.1...6).size
assert_equal 15, (1.0..15.9).size
assert_equal Float::INFINITY, (0..Float::INFINITY).size
assert_nil ('a'..'z').size assert_nil ('a'..'z').size
end end
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment