From 92f72c749006407db4fa4a4faf123bde4a3043e4 Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Wed, 16 Nov 2016 02:04:56 +0900 Subject: make String#[]= to take Ranges as position argument --- mrblib/string.rb | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) (limited to 'mrblib') diff --git a/mrblib/string.rb b/mrblib/string.rb index 37441ec98..f22071b36 100644 --- a/mrblib/string.rb +++ b/mrblib/string.rb @@ -159,16 +159,27 @@ class String anum = args.size if anum == 2 pos, value = args - if pos.kind_of? String + case pos + when String posnum = self.index(pos) if posnum b = self[0, posnum.to_i] a = self[(posnum + pos.length)..-1] self.replace([b, value, a].join('')) - return value else raise IndexError, "string not matched" end + when Range + head = pos.begin + tail = pos.end + tail += self.length if tail < 0 + if pos.exclude_end? + tail -= 1 + end + if tail < 0 || tail > self.length + raise IndexError, "index #{args[0]} out of string" + end + return self[head, tail-head]=value else pos += self.length if pos < 0 if pos < 0 || pos > self.length @@ -177,8 +188,8 @@ class String b = self[0, pos.to_i] a = self[pos + 1..-1] self.replace([b, value, a].join('')) - return value end + return value elsif anum == 3 pos, len, value = args pos += self.length if pos < 0 -- cgit v1.2.3 From 1685eff2a5e672173d67916a1c96648df92b7271 Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Wed, 16 Nov 2016 10:16:14 +0900 Subject: Fixed off-by-one error in String#[]= with Ranges --- mrblib/string.rb | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) (limited to 'mrblib') diff --git a/mrblib/string.rb b/mrblib/string.rb index f22071b36..aa2ca9973 100644 --- a/mrblib/string.rb +++ b/mrblib/string.rb @@ -173,11 +173,8 @@ class String head = pos.begin tail = pos.end tail += self.length if tail < 0 - if pos.exclude_end? - tail -= 1 - end - if tail < 0 || tail > self.length - raise IndexError, "index #{args[0]} out of string" + unless pos.exclude_end? + tail += 1 end return self[head, tail-head]=value else -- cgit v1.2.3 From efebbbbf260e8ac5b8efbd0d4336a777cfeac514 Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Wed, 23 Nov 2016 09:45:50 +0900 Subject: Implement Float shift methods in C --- mrblib/numeric.rb | 30 +----------------------------- src/numeric.c | 50 ++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 51 insertions(+), 29 deletions(-) (limited to 'mrblib') diff --git a/mrblib/numeric.rb b/mrblib/numeric.rb index 6e4c5027f..17155bfd6 100644 --- a/mrblib/numeric.rb +++ b/mrblib/numeric.rb @@ -160,35 +160,7 @@ end # # ISO 15.2.9 class Float - include Integral # mruby special - since mruby integers may be upgraded to floats, # floats should be compatible to integers. - def >> other - n = self.to_i - other = other.to_i - if other < 0 - n << -other - else - other.times { n /= 2 } - if n.abs < 1 - if n >= 0 - 0 - else - -1 - end - else - n.to_i - end - end - end - def << other - n = self.to_i - other = other.to_i - if other < 0 - n >> -other - else - other.times { n *= 2 } - n - end - end + include Integral end diff --git a/src/numeric.c b/src/numeric.c index cdf8c8afb..c86373318 100644 --- a/src/numeric.c +++ b/src/numeric.c @@ -15,6 +15,7 @@ #include #ifdef MRB_USE_FLOAT +#define trunc(f) truncf(f) #define floor(f) floorf(f) #define ceil(f) ceilf(f) #define fmod(x,y) fmodf(x,y) @@ -342,6 +343,53 @@ flo_xor(mrb_state *mrb, mrb_value x) return int64_value(mrb, v1 ^ v2); } +static mrb_value +flo_shift(mrb_state *mrb, mrb_value x, mrb_int width) +{ + mrb_float val; + + if (width == 0) { + return x; + } + val = mrb_float(x); + if (width < 0) { + while (width++) { + val /= 2; + } + val = trunc(val); + if (val == 0 && mrb_float(x) < 0) { + return mrb_fixnum_value(-1); + } + } + else { + while (width--) { + val *= 2; + } + } + if (FIXABLE(val)) { + return mrb_fixnum_value(val); + } + return mrb_float_value(mrb, val); +} + +static mrb_value +flo_lshift(mrb_state *mrb, mrb_value x) +{ + mrb_int width; + + mrb_get_args(mrb, "i", &width); + return flo_shift(mrb, x, -width); +} + +static mrb_value +flo_rshift(mrb_state *mrb, mrb_value x) +{ + mrb_int width; + + mrb_get_args(mrb, "i", &width); + return flo_shift(mrb, x, width); +} + /* 15.2.8.3.18 */ /* * call-seq: @@ -1253,6 +1301,8 @@ mrb_init_numeric(mrb_state *mrb) mrb_define_method(mrb, fl, "&", flo_and, MRB_ARGS_REQ(1)); mrb_define_method(mrb, fl, "|", flo_or, MRB_ARGS_REQ(1)); mrb_define_method(mrb, fl, "^", flo_xor, MRB_ARGS_REQ(1)); + mrb_define_method(mrb, fl, ">>", flo_lshift, MRB_ARGS_REQ(1)); + mrb_define_method(mrb, fl, "<<", flo_rshift, MRB_ARGS_REQ(1)); mrb_define_method(mrb, fl, "ceil", flo_ceil, MRB_ARGS_NONE()); /* 15.2.9.3.8 */ mrb_define_method(mrb, fl, "finite?", flo_finite_p, MRB_ARGS_NONE()); /* 15.2.9.3.9 */ mrb_define_method(mrb, fl, "floor", flo_floor, MRB_ARGS_NONE()); /* 15.2.9.3.10 */ -- cgit v1.2.3 From b23fb45f9ce3cb12b33eecc9cab37adc2890f49f Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Fri, 20 Jan 2017 17:58:29 +0900 Subject: Integral#step without arg should loop forever as CRuby does. --- mrblib/numeric.rb | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) (limited to 'mrblib') diff --git a/mrblib/numeric.rb b/mrblib/numeric.rb index 17155bfd6..975ad973f 100644 --- a/mrblib/numeric.rb +++ b/mrblib/numeric.rb @@ -100,11 +100,18 @@ module Integral # Calls the given block from +self+ to +num+ # incremented by +step+ (default 1). # - def step(num, step = 1, &block) + def step(num=nil, step=1, &block) raise ArgumentError, "step can't be 0" if step == 0 return to_enum(:step, num, step) unless block_given? i = if num.kind_of? Float then self.to_f else self end + if num == nil + while true + block.call(i) + i+=step + end + return self + end if step > 0 while i <= num block.call(i) -- cgit v1.2.3