summaryrefslogtreecommitdiffhomepage
path: root/mrbgems
diff options
context:
space:
mode:
authorYukihiro "Matz" Matsumoto <[email protected]>2016-11-21 01:15:37 +0900
committerGitHub <[email protected]>2016-11-21 01:15:37 +0900
commit3ce51cbc7c8aad796b89aea4a7dffb0b00c5e92c (patch)
treef4bff95955cd0e61eb8e240e82a0e8b4878fb9d6 /mrbgems
parent0ff3ae1fbaed62010c54c43235e29cdc85da2f78 (diff)
parent22390aa1c8e17135e1d298e5e66776c77234c0b5 (diff)
downloadmruby-3ce51cbc7c8aad796b89aea4a7dffb0b00c5e92c.tar.gz
mruby-3ce51cbc7c8aad796b89aea4a7dffb0b00c5e92c.zip
Merge pull request #3257 from ksss/range-size
Fix Range#size results
Diffstat (limited to 'mrbgems')
-rw-r--r--mrbgems/mruby-range-ext/src/range.c33
-rw-r--r--mrbgems/mruby-range-ext/test/range.rb2
2 files changed, 25 insertions, 10 deletions
diff --git a/mrbgems/mruby-range-ext/src/range.c b/mrbgems/mruby-range-ext/src/range.c
index 4d6f1684f..1d9312b03 100644
--- a/mrbgems/mruby-range-ext/src/range.c
+++ b/mrbgems/mruby-range-ext/src/range.c
@@ -1,6 +1,7 @@
#include <mruby.h>
#include <mruby/range.h>
#include <math.h>
+#include <float.h>
static mrb_bool
r_le(mrb_state *mrb, mrb_value a, mrb_value b)
@@ -138,13 +139,15 @@ mrb_range_size(mrb_state *mrb, mrb_value range)
{
struct RRange *r = mrb_range_ptr(range);
mrb_value beg, end;
- double beg_f, end_f;
+ mrb_float beg_f, end_f;
mrb_bool num_p = TRUE;
+ mrb_bool excl;
beg = r->edges->beg;
end = r->edges->end;
+ excl = r->excl;
if (mrb_fixnum_p(beg)) {
- beg_f = (double)mrb_fixnum(beg);
+ beg_f = (mrb_float)mrb_fixnum(beg);
}
else if (mrb_float_p(beg)) {
beg_f = mrb_float(beg);
@@ -153,7 +156,7 @@ mrb_range_size(mrb_state *mrb, mrb_value range)
num_p = FALSE;
}
if (mrb_fixnum_p(end)) {
- end_f = (double)mrb_fixnum(end);
+ end_f = (mrb_float)mrb_fixnum(end);
}
else if (mrb_float_p(end)) {
end_f = mrb_float(end);
@@ -162,14 +165,24 @@ mrb_range_size(mrb_state *mrb, mrb_value range)
num_p = FALSE;
}
if (num_p) {
- double f;
-
- if (beg_f > end_f) return mrb_fixnum_value(0);
- f = end_f - beg_f;
- if (!r->excl) {
- return mrb_fixnum_value((mrb_int)ceil(f + 1));
+ mrb_float n = end_f - beg_f;
+ mrb_float err = (fabs(beg_f) + fabs(end_f) + fabs(end_f-beg_f)) * DBL_EPSILON;
+
+ if (err>0.5) err=0.5;
+ if (excl) {
+ 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();
}
diff --git a/mrbgems/mruby-range-ext/test/range.rb b/mrbgems/mruby-range-ext/test/range.rb
index 18e7dafe4..ea1e12f2e 100644
--- a/mrbgems/mruby-range-ext/test/range.rb
+++ b/mrbgems/mruby-range-ext/test/range.rb
@@ -25,5 +25,7 @@ assert('Range#size') do
assert_equal 6, (1...6.3).size
assert_equal 5, (1...6.0).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
end