summaryrefslogtreecommitdiffhomepage
path: root/mrbgems/mruby-range-ext
diff options
context:
space:
mode:
authorYukihiro "Matz" Matsumoto <[email protected]>2014-05-19 18:04:27 +0900
committerYukihiro "Matz" Matsumoto <[email protected]>2014-05-19 18:04:27 +0900
commit91a025b1e663f9d6516c28bbfbc6cf03225e46fc (patch)
tree72505313e34ff74ab0fb6450ad4b54b3ccb6cbe3 /mrbgems/mruby-range-ext
parent90fa54767acdf86429d490d056ac366584d70a57 (diff)
downloadmruby-91a025b1e663f9d6516c28bbfbc6cf03225e46fc.tar.gz
mruby-91a025b1e663f9d6516c28bbfbc6cf03225e46fc.zip
reimplement Range#size using double with fixing corner cases; ref #2293
Diffstat (limited to 'mrbgems/mruby-range-ext')
-rw-r--r--mrbgems/mruby-range-ext/src/range.c44
1 files changed, 29 insertions, 15 deletions
diff --git a/mrbgems/mruby-range-ext/src/range.c b/mrbgems/mruby-range-ext/src/range.c
index 93393e487..35632ad20 100644
--- a/mrbgems/mruby-range-ext/src/range.c
+++ b/mrbgems/mruby-range-ext/src/range.c
@@ -1,5 +1,6 @@
#include "mruby.h"
#include "mruby/range.h"
+#include <math.h>
static mrb_bool
r_le(mrb_state *mrb, mrb_value a, mrb_value b)
@@ -136,26 +137,39 @@ static mrb_value
mrb_range_size(mrb_state *mrb, mrb_value range)
{
struct RRange *r = mrb_range_ptr(range);
- mrb_value beg, end, end_f;
- mrb_bool dec = TRUE;
+ mrb_value beg, end;
+ double beg_f, end_f;
+ mrb_bool num_p = TRUE;
beg = r->edges->beg;
end = r->edges->end;
- if (mrb_obj_is_kind_of(mrb, beg, mrb->float_class)) {
- beg = mrb_funcall(mrb, beg, "to_i", 0);
+ if (mrb_fixnum_p(beg)) {
+ beg_f = (double)mrb_fixnum(beg);
}
- if (mrb_obj_is_kind_of(mrb, end, mrb->float_class)) {
- end_f = end;
- end = mrb_funcall(mrb, end, "to_i", 0);
- if (r->excl && mrb_obj_eq(mrb, mrb_funcall(mrb, end_f, "==", 1, end), mrb_false_value())) {
- dec = FALSE;
- }
+ else if (mrb_float_p(beg)) {
+ beg_f = mrb_float(beg);
+ }
+ else {
+ num_p = FALSE;
+ }
+ if (mrb_fixnum_p(end)) {
+ end_f = (double)mrb_fixnum(end);
}
- if (mrb_obj_is_kind_of(mrb, beg, mrb->fixnum_class) &&
- mrb_obj_is_kind_of(mrb, end, mrb->fixnum_class)) {
- mrb_int end_i = mrb_fixnum(end);
- if (r->excl && dec) end_i--;
- return mrb_fixnum_value(end_i - mrb_fixnum(beg) + 1);
+ else if (mrb_float_p(end)) {
+ end_f = mrb_float(end);
+ }
+ else {
+ 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));
+ }
+ return mrb_fixnum_value((mrb_int)ceil(f));
}
return mrb_nil_value();
}