From 005ccd9c7ec8e40ec05afd2e461566324e2d6eb6 Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Wed, 1 Aug 2018 21:55:11 +0900 Subject: Small refactoring of `flodivmod()`. --- src/numeric.c | 41 ++++++++++++++++++++++++++--------------- 1 file changed, 26 insertions(+), 15 deletions(-) (limited to 'src/numeric.c') diff --git a/src/numeric.c b/src/numeric.c index 4e5fc394e..c3e7d77a3 100644 --- a/src/numeric.c +++ b/src/numeric.c @@ -220,29 +220,40 @@ flo_mul(mrb_state *mrb, mrb_value x) } static void -flodivmod(mrb_state *mrb, mrb_float x, mrb_float y, mrb_float *divp, mrb_float *modp) +flodivmod(mrb_state *mrb, double x, double y, mrb_float *divp, mrb_float *modp) { - mrb_float div; - mrb_float mod; + double div, mod; + if (isnan(y)) { + /* y is NaN so all results are NaN */ + div = mod = y; + goto exit; + } if (y == 0.0) { - if (x > 0.0) div = INFINITY; - else if (x < 0.0) div = -INFINITY; - else div = NAN; /* x == 0.0 */ + if (x == 0) div = NAN; + else if (x > 0.0) div = INFINITY; + else div = -INFINITY; /* x < 0.0 */ mod = NAN; + goto exit; + } + if ((x == 0.0) || (isinf(y) && !isinf(x))) { + mod = x; } else { mod = fmod(x, y); - if (isinf(x) && isfinite(y)) - div = x; - else - div = (x - mod) / y; - if (y*mod < 0) { - mod += y; - div -= 1.0; - } } - + if (isinf(x) && !isinf(y)) { + div = x; + } + else { + div = (x - mod) / y; + if (modp && divp) div = round(div); + } + if (y*mod < 0) { + mod += y; + div -= 1.0; + } + exit: if (modp) *modp = mod; if (divp) *divp = div; } -- cgit v1.2.3 From 366848996a6cce8e733246bce6c3f76d797003bb Mon Sep 17 00:00:00 2001 From: dearblue Date: Fri, 7 Sep 2018 00:22:36 +0900 Subject: Clear terminated space --- examples/targets/build_config_android_arm64-v8a.rb | 4 ++-- examples/targets/build_config_android_armeabi.rb | 4 ++-- mrbgems/mruby-array-ext/test/array.rb | 2 +- mrbgems/mruby-compiler/core/codegen.c | 8 ++++---- mrbgems/mruby-random/src/random.c | 2 +- src/array.c | 2 +- src/codedump.c | 2 +- src/gc.c | 2 +- src/numeric.c | 2 +- src/variable.c | 10 +++++----- src/vm.c | 4 ++-- tasks/toolchains/gcc.rake | 2 +- test/t/kernel.rb | 2 +- test/t/syntax.rb | 6 +++--- 14 files changed, 26 insertions(+), 26 deletions(-) (limited to 'src/numeric.c') diff --git a/examples/targets/build_config_android_arm64-v8a.rb b/examples/targets/build_config_android_arm64-v8a.rb index 6188c13ec..70b0f4b97 100644 --- a/examples/targets/build_config_android_arm64-v8a.rb +++ b/examples/targets/build_config_android_arm64-v8a.rb @@ -15,8 +15,8 @@ end # Requires Android NDK r13 or later. MRuby::CrossBuild.new('android-arm64-v8a') do |conf| - params = { - :arch => 'arm64-v8a', + params = { + :arch => 'arm64-v8a', :platform => 'android-24', :toolchain => :clang, } diff --git a/examples/targets/build_config_android_armeabi.rb b/examples/targets/build_config_android_armeabi.rb index b7eb33a92..17330242a 100644 --- a/examples/targets/build_config_android_armeabi.rb +++ b/examples/targets/build_config_android_armeabi.rb @@ -15,8 +15,8 @@ end # Requires Android NDK r13 or later. MRuby::CrossBuild.new('android-armeabi') do |conf| - params = { - :arch => 'armeabi', + params = { + :arch => 'armeabi', :platform => 'android-24', :toolchain => :clang, } diff --git a/mrbgems/mruby-array-ext/test/array.rb b/mrbgems/mruby-array-ext/test/array.rb index 7d810acc2..4f54c65c3 100644 --- a/mrbgems/mruby-array-ext/test/array.rb +++ b/mrbgems/mruby-array-ext/test/array.rb @@ -418,5 +418,5 @@ assert('Array#transpose') do assert_equal([[1], [2], [3]].transpose, [[1,2,3]]) assert_equal([[1,2], [3,4], [5,6]].transpose, [[1,3,5], [2,4,6]]) assert_raise(TypeError) { [1].transpose } - assert_raise(IndexError) { [[1], [2,3,4]].transpose } + assert_raise(IndexError) { [[1], [2,3,4]].transpose } end diff --git a/mrbgems/mruby-compiler/core/codegen.c b/mrbgems/mruby-compiler/core/codegen.c index 8be9a8ebe..74504ffd1 100644 --- a/mrbgems/mruby-compiler/core/codegen.c +++ b/mrbgems/mruby-compiler/core/codegen.c @@ -419,7 +419,7 @@ gen_move(codegen_scope *s, uint16_t dst, uint16_t src, int nopeep) } else { struct mrb_insn_data data = mrb_last_insn(s); - + switch (data.insn) { case OP_MOVE: if (dst == src) return; /* remove useless MOVE */ @@ -456,7 +456,7 @@ gen_return(codegen_scope *s, uint8_t op, uint16_t src) } else { struct mrb_insn_data data = mrb_last_insn(s); - + if (data.insn == OP_MOVE && src == data.a) { s->pc = s->lastpc; genop_1(s, op, data.b); @@ -764,7 +764,7 @@ lambda_body(codegen_scope *s, node *tree, int blk) kd = tail && tail->cdr->cdr->car? 1 : 0; /* block argument? */ ba = tail && tail->cdr->cdr->cdr->car ? 1 : 0; - + if (ma > 0x1f || oa > 0x1f || pa > 0x1f || ka > 0x1f) { codegen_error(s, "too many formal arguments"); } @@ -3118,7 +3118,7 @@ generate_code(mrb_state *mrb, parser_state *p, int val) scope->filename_index = p->current_filename_index; MRB_TRY(&scope->jmp) { - mrb->jmp = &scope->jmp; + mrb->jmp = &scope->jmp; /* prepare irep */ codegen(scope, p->tree, val); proc = mrb_proc_new(mrb, scope->irep); diff --git a/mrbgems/mruby-random/src/random.c b/mrbgems/mruby-random/src/random.c index b865244cc..5b926a228 100644 --- a/mrbgems/mruby-random/src/random.c +++ b/mrbgems/mruby-random/src/random.c @@ -219,7 +219,7 @@ mrb_ary_shuffle_bang(mrb_state *mrb, mrb_value ary) mrb_int j; mrb_value *ptr = RARRAY_PTR(ary); mrb_value tmp; - + j = mrb_fixnum(mrb_random_mt_rand(mrb, random, mrb_fixnum_value(RARRAY_LEN(ary)))); diff --git a/src/array.c b/src/array.c index 2152e292d..f0c32bc7f 100644 --- a/src/array.c +++ b/src/array.c @@ -231,7 +231,7 @@ ary_expand_capa(mrb_state *mrb, struct RArray *a, mrb_int len) static void ary_shrink_capa(mrb_state *mrb, struct RArray *a) { - + mrb_int capa; if (ARY_EMBED_P(a)) return; diff --git a/src/codedump.c b/src/codedump.c index 454b16b36..30a14f937 100644 --- a/src/codedump.c +++ b/src/codedump.c @@ -516,7 +516,7 @@ codedump(mrb_state *mrb, mrb_irep *irep) #undef OPCODE } break; - + default: printf("OP_unknown (0x%x)\n", ins); break; diff --git a/src/gc.c b/src/gc.c index 9858e45fc..e429603dd 100644 --- a/src/gc.c +++ b/src/gc.c @@ -1559,7 +1559,7 @@ mrb_objspace_each_objects(mrb_state *mrb, mrb_each_object_callback *callback, vo mrb->jmp = &c_jmp; gc_each_objects(mrb, &mrb->gc, callback, data); mrb->jmp = prev_jmp; - mrb->gc.iterating = iterating; + mrb->gc.iterating = iterating; } MRB_CATCH(&c_jmp) { mrb->gc.iterating = iterating; mrb->jmp = prev_jmp; diff --git a/src/numeric.c b/src/numeric.c index c3e7d77a3..f7f0318e8 100644 --- a/src/numeric.c +++ b/src/numeric.c @@ -433,7 +433,7 @@ flo_shift(mrb_state *mrb, mrb_value x, mrb_int width) val = trunc(val); #else if (val > 0){ - val = floor(val); + val = floor(val); } else { val = ceil(val); } diff --git a/src/variable.c b/src/variable.c index 00bdb4b8d..506b4b63e 100644 --- a/src/variable.c +++ b/src/variable.c @@ -790,7 +790,7 @@ mrb_vm_const_get(mrb_state *mrb, mrb_sym sym) proc = mrb->c->ci->proc; while (proc) { c2 = MRB_PROC_TARGET_CLASS(proc); - if (c2 && iv_get(mrb, c2->iv, sym, &v)) { + if (c2 && iv_get(mrb, c2->iv, sym, &v)) { return v; } proc = proc->upper; @@ -988,25 +988,25 @@ struct csym_arg { struct RClass *c; mrb_sym sym; }; - + static int csym_i(mrb_state *mrb, mrb_sym sym, mrb_value v, void *p) { struct csym_arg *a = (struct csym_arg*)p; struct RClass *c = a->c; - + if (mrb_type(v) == c->tt && mrb_class_ptr(v) == c) { a->sym = sym; return 1; /* stop iteration */ } return 0; } - + static mrb_sym find_class_sym(mrb_state *mrb, struct RClass *outer, struct RClass *c) { struct csym_arg arg; - + if (!outer) return 0; if (outer == c) return 0; arg.c = c; diff --git a/src/vm.c b/src/vm.c index 9c4580fb3..14c42984e 100644 --- a/src/vm.c +++ b/src/vm.c @@ -1818,7 +1818,7 @@ RETRY_TRY_BLOCK: } regs[blk_pos] = *blk; /* move block */ if (kd) regs[len + 1] = kdict; - + /* copy mandatory and optional arguments */ if (argv0 != argv) { value_move(®s[1], argv, argc-mlen); /* m1 + o */ @@ -2077,7 +2077,7 @@ RETRY_TRY_BLOCK: break; case OP_R_BREAK: if (MRB_PROC_STRICT_P(proc)) goto NORMAL_RETURN; - if (MRB_PROC_ORPHAN_P(proc)) { + if (MRB_PROC_ORPHAN_P(proc)) { mrb_value exc; L_BREAK_ERROR: diff --git a/tasks/toolchains/gcc.rake b/tasks/toolchains/gcc.rake index fc2e0bff3..e0eb36f26 100644 --- a/tasks/toolchains/gcc.rake +++ b/tasks/toolchains/gcc.rake @@ -55,7 +55,7 @@ MRuby::Toolchain.new(:gcc) do |conf, _params| @header_search_paths end end - + def conf.enable_sanitizer(*opts) fail 'sanitizer already set' if @sanitizer_list diff --git a/test/t/kernel.rb b/test/t/kernel.rb index a730bdb24..74176fbd0 100644 --- a/test/t/kernel.rb +++ b/test/t/kernel.rb @@ -157,7 +157,7 @@ assert('Kernel#clone', '15.3.1.3.8') do assert_true a.respond_to?(:test) assert_false b.respond_to?(:test) assert_true c.respond_to?(:test) - + a.freeze d = a.clone assert_true d.frozen? diff --git a/test/t/syntax.rb b/test/t/syntax.rb index c5405aa9c..883cbd1ba 100644 --- a/test/t/syntax.rb +++ b/test/t/syntax.rb @@ -454,15 +454,15 @@ assert('multiline comments work correctly') do =begin this is a comment with nothing after begin and end =end -=begin this is a comment +=begin this is a comment this is a comment with extra after =begin =end =begin this is a comment that has =end with spaces after it -=end +=end =begin this is a comment this is a comment that has extra after =begin and =end with spaces after it -=end +=end line = __LINE__ =begin this is a comment this is a comment that has extra after =begin and =end with tabs after it -- cgit v1.2.3 From afca99a40b8a3415b3a9a0e8fc41c93ddcbb11d8 Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Wed, 19 Sep 2018 20:53:32 +0900 Subject: Remove implicit conversion using `to_int` method. The ISO standard does not include implicit type conversion using `to_int`. This implicit conversion often causes vulnerability. There will be no more attacks like #4120. In addition, we have added internal convenience method `__to_int` which does type check and conversion (from floats). --- include/mruby.h | 1 - mrbgems/mruby-enum-ext/mrblib/enum.rb | 27 +++++-------- mrbgems/mruby-enumerator/mrblib/enumerator.rb | 8 ++-- mrbgems/mruby-enumerator/test/enumerator.rb | 6 --- mrbgems/mruby-kernel-ext/src/kernel.c | 5 +-- mrbgems/mruby-numeric-ext/src/numeric_ext.c | 17 ++++---- mrbgems/mruby-pack/src/pack.c | 6 ++- mrbgems/mruby-random/src/random.c | 12 +++--- mrbgems/mruby-random/test/random.rb | 12 ------ mrbgems/mruby-range-ext/mrblib/range.rb | 5 +-- mrbgems/mruby-string-ext/test/string.rb | 12 ------ mrblib/array.rb | 2 +- src/kernel.c | 2 + src/numeric.c | 4 -- src/object.c | 57 ++++++++------------------- 15 files changed, 51 insertions(+), 125 deletions(-) (limited to 'src/numeric.c') diff --git a/include/mruby.h b/include/mruby.h index 8eff31746..33597101a 100644 --- a/include/mruby.h +++ b/include/mruby.h @@ -716,7 +716,6 @@ MRB_API mrb_value mrb_notimplement_m(mrb_state*, mrb_value); * @return [mrb_value] The newly duplicated object. */ MRB_API mrb_value mrb_obj_dup(mrb_state *mrb, mrb_value obj); -MRB_API mrb_value mrb_check_to_integer(mrb_state *mrb, mrb_value val, const char *method); /** * Returns true if obj responds to the given method. If the method was defined for that diff --git a/mrbgems/mruby-enum-ext/mrblib/enum.rb b/mrbgems/mruby-enum-ext/mrblib/enum.rb index ba92decee..fedf8b1ae 100644 --- a/mrbgems/mruby-enum-ext/mrblib/enum.rb +++ b/mrbgems/mruby-enum-ext/mrblib/enum.rb @@ -13,10 +13,9 @@ module Enumerable # a.drop(3) #=> [4, 5, 0] def drop(n) - raise TypeError, "no implicit conversion of #{n.class} into Integer" unless n.respond_to?(:to_int) + n = n.__to_int raise ArgumentError, "attempt to drop negative size" if n < 0 - n = n.to_int ary = [] self.each {|*val| n == 0 ? ary << val.__svalue : n -= 1 } ary @@ -57,8 +56,8 @@ module Enumerable # a.take(3) #=> [1, 2, 3] def take(n) - raise TypeError, "no implicit conversion of #{n.class} into Integer" unless n.respond_to?(:to_int) - i = n.to_int + n = n.__to_int + i = n.to_i raise ArgumentError, "attempt to take negative size" if i < 0 ary = [] return ary if i == 0 @@ -113,12 +112,12 @@ module Enumerable # [8, 9, 10] def each_cons(n, &block) - raise TypeError, "no implicit conversion of #{n.class} into Integer" unless n.respond_to?(:to_int) + n = n.__to_int raise ArgumentError, "invalid size" if n <= 0 return to_enum(:each_cons,n) unless block ary = [] - n = n.to_int + n = n.to_i self.each do |*val| ary.shift if ary.size == n ary << val.__svalue @@ -141,12 +140,12 @@ module Enumerable # [10] def each_slice(n, &block) - raise TypeError, "no implicit conversion of #{n.class} into Integer" unless n.respond_to?(:to_int) + n = n.__to_int raise ArgumentError, "invalid slice size" if n <= 0 return to_enum(:each_slice,n) unless block ary = [] - n = n.to_int + n = n.to_i self.each do |*val| ary << val.__svalue if ary.size == n @@ -223,9 +222,7 @@ module Enumerable end return nil when 1 - n = args[0] - raise TypeError, "no implicit conversion of #{n.class} into Integer" unless n.respond_to?(:to_int) - i = n.to_int + i = args[0].__to_int raise ArgumentError, "attempt to take negative size" if i < 0 ary = [] return ary if i == 0 @@ -673,13 +670,7 @@ module Enumerable if nv.nil? n = -1 else - unless nv.respond_to?(:to_int) - raise TypeError, "no implicit conversion of #{nv.class} into Integer" - end - n = nv.to_int - unless n.kind_of?(Integer) - raise TypeError, "no implicit conversion of #{nv.class} into Integer" - end + n = nv.__to_int return nil if n <= 0 end diff --git a/mrbgems/mruby-enumerator/mrblib/enumerator.rb b/mrbgems/mruby-enumerator/mrblib/enumerator.rb index dbc7d3004..6dd971f3a 100644 --- a/mrbgems/mruby-enumerator/mrblib/enumerator.rb +++ b/mrbgems/mruby-enumerator/mrblib/enumerator.rb @@ -157,12 +157,10 @@ class Enumerator def with_index(offset=0, &block) return to_enum :with_index, offset unless block - offset = if offset.nil? - 0 - elsif offset.respond_to?(:to_int) - offset.to_int + if offset.nil? + offset = 0 else - raise TypeError, "no implicit conversion of #{offset.class} into Integer" + offset = offset.__to_int end n = offset - 1 diff --git a/mrbgems/mruby-enumerator/test/enumerator.rb b/mrbgems/mruby-enumerator/test/enumerator.rb index ef4970883..f3bd1bdba 100644 --- a/mrbgems/mruby-enumerator/test/enumerator.rb +++ b/mrbgems/mruby-enumerator/test/enumerator.rb @@ -54,12 +54,6 @@ assert 'Enumerator#with_index' do assert_equal [[[1, 10], 20], [[2, 11], 21], [[3, 12], 22]], a end -assert 'Enumerator#with_index nonnum offset' do - s = Object.new - def s.to_int; 1 end - assert_equal([[1,1],[2,2],[3,3]], @obj.to_enum(:foo, 1, 2, 3).with_index(s).to_a) -end - assert 'Enumerator#with_index string offset' do assert_raise(TypeError){ @obj.to_enum(:foo, 1, 2, 3).with_index('1').to_a } end diff --git a/mrbgems/mruby-kernel-ext/src/kernel.c b/mrbgems/mruby-kernel-ext/src/kernel.c index 32d86376a..a60e9a210 100644 --- a/mrbgems/mruby-kernel-ext/src/kernel.c +++ b/mrbgems/mruby-kernel-ext/src/kernel.c @@ -93,9 +93,8 @@ mrb_f_method(mrb_state *mrb, mrb_value self) * (0, 0b, and 0x) are honored. * In any case, strings should be strictly conformed to numeric * representation. This behavior is different from that of - * String#to_i. Non string values will be converted using - * to_int, and to_i. Passing nil - * raises a TypeError. + * String#to_i. Non string values will be treated as integers. + * Passing nil raises a TypeError. * * Integer(123.999) #=> 123 * Integer("0x1a") #=> 26 diff --git a/mrbgems/mruby-numeric-ext/src/numeric_ext.c b/mrbgems/mruby-numeric-ext/src/numeric_ext.c index 1d6a07769..cd8bbf187 100644 --- a/mrbgems/mruby-numeric-ext/src/numeric_ext.c +++ b/mrbgems/mruby-numeric-ext/src/numeric_ext.c @@ -2,13 +2,10 @@ #include static inline mrb_int -to_int(mrb_value x) +to_int(mrb_state *mrb, mrb_value x) { - double f; - - if (mrb_fixnum_p(x)) return mrb_fixnum(x); - f = mrb_float(x); - return (mrb_int)f; + x = mrb_to_int(mrb, x); + return mrb_fixnum(x); } /* @@ -28,7 +25,7 @@ mrb_int_chr(mrb_state *mrb, mrb_value x) mrb_int chr; char c; - chr = to_int(x); + chr = to_int(mrb, x); if (chr >= (1 << CHAR_BIT)) { mrb_raisef(mrb, E_RANGE_ERROR, "%S out of char range", x); } @@ -48,8 +45,8 @@ mrb_int_allbits(mrb_state *mrb, mrb_value self) { mrb_int n, m; - n = to_int(self); mrb_get_args(mrb, "i", &m); + n = to_int(mrb, self); return mrb_bool_value((n & m) == m); } @@ -64,8 +61,8 @@ mrb_int_anybits(mrb_state *mrb, mrb_value self) { mrb_int n, m; - n = to_int(self); mrb_get_args(mrb, "i", &m); + n = to_int(mrb, self); return mrb_bool_value((n & m) != 0); } @@ -80,8 +77,8 @@ mrb_int_nobits(mrb_state *mrb, mrb_value self) { mrb_int n, m; - n = to_int(self); mrb_get_args(mrb, "i", &m); + n = to_int(mrb, self); return mrb_bool_value((n & m) == 0); } diff --git a/mrbgems/mruby-pack/src/pack.c b/mrbgems/mruby-pack/src/pack.c index 796ba4d34..5caf7b62b 100644 --- a/mrbgems/mruby-pack/src/pack.c +++ b/mrbgems/mruby-pack/src/pack.c @@ -1124,14 +1124,16 @@ mrb_pack_pack(mrb_state *mrb, mrb_value ary) o = mrb_ary_ref(mrb, ary, aidx); if (type == PACK_TYPE_INTEGER) { o = mrb_to_int(mrb, o); + } #ifndef MRB_WITHOUT_FLOAT - } else if (type == PACK_TYPE_FLOAT) { + else if (type == PACK_TYPE_FLOAT) { if (!mrb_float_p(o)) { mrb_float f = mrb_to_flo(mrb, o); o = mrb_float_value(mrb, f); } + } #endif - } else if (type == PACK_TYPE_STRING) { + else if (type == PACK_TYPE_STRING) { if (!mrb_string_p(o)) { mrb_raisef(mrb, E_TYPE_ERROR, "can't convert %S into String", mrb_class_path(mrb, mrb_obj_class(mrb, o))); } diff --git a/mrbgems/mruby-random/src/random.c b/mrbgems/mruby-random/src/random.c index 5b926a228..68209840a 100644 --- a/mrbgems/mruby-random/src/random.c +++ b/mrbgems/mruby-random/src/random.c @@ -79,12 +79,12 @@ get_opt(mrb_state* mrb) mrb_get_args(mrb, "|o", &arg); if (!mrb_nil_p(arg)) { - arg = mrb_check_convert_type(mrb, arg, MRB_TT_FIXNUM, "Fixnum", "to_int"); - if (mrb_nil_p(arg)) { - mrb_raise(mrb, E_ARGUMENT_ERROR, "invalid argument type"); - } - if (mrb_fixnum(arg) < 0) { - arg = mrb_fixnum_value(0 - mrb_fixnum(arg)); + mrb_int i; + + arg = mrb_to_int(mrb, arg); + i = mrb_fixnum(arg); + if (i < 0) { + arg = mrb_fixnum_value(0 - i); } } return arg; diff --git a/mrbgems/mruby-random/test/random.rb b/mrbgems/mruby-random/test/random.rb index 1c59be3a6..1653ae4a6 100644 --- a/mrbgems/mruby-random/test/random.rb +++ b/mrbgems/mruby-random/test/random.rb @@ -74,15 +74,3 @@ assert('Array#shuffle!(random)') do ary1 != [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] and 10.times { |x| ary1.include? x } and ary1 == ary2 end - -assert('Array#sample checks input length after reading arguments') do - $ary = [1, 2, 3] - class ArrayChange - def to_i - $ary << 4 - 4 - end - end - - assert_equal [1, 2, 3, 4], $ary.sample(ArrayChange.new).sort -end diff --git a/mrbgems/mruby-range-ext/mrblib/range.rb b/mrbgems/mruby-range-ext/mrblib/range.rb index e5d1fb079..de7925ba7 100644 --- a/mrbgems/mruby-range-ext/mrblib/range.rb +++ b/mrbgems/mruby-range-ext/mrblib/range.rb @@ -15,10 +15,7 @@ class Range raise ArgumentError, "wrong number of arguments (given #{args.length}, expected 1)" unless args.length == 1 nv = args[0] - raise TypeError, "no implicit conversion from nil to integer" if nv.nil? - raise TypeError, "no implicit conversion of #{nv.class} into Integer" unless nv.respond_to?(:to_int) - n = nv.to_int - raise TypeError, "no implicit conversion of #{nv.class} into Integer" unless n.kind_of?(Integer) + n = nv.__to_int raise ArgumentError, "negative array size (or size too big)" unless 0 <= n ary = [] each do |i| diff --git a/mrbgems/mruby-string-ext/test/string.rb b/mrbgems/mruby-string-ext/test/string.rb index f0f8be6b3..781506949 100644 --- a/mrbgems/mruby-string-ext/test/string.rb +++ b/mrbgems/mruby-string-ext/test/string.rb @@ -31,18 +31,6 @@ assert('String#setbyte') do assert_equal("Hello", str1) end -assert("String#setbyte raises IndexError if arg conversion resizes String") do - $s = "01234\n" - class Tmp - def to_i - $s.chomp! '' - 95 - end - end - tmp = Tmp.new - assert_raise(IndexError) { $s.setbyte(5, tmp) } -end - assert('String#byteslice') do str1 = "hello" assert_equal("e", str1.byteslice(1)) diff --git a/mrblib/array.rb b/mrblib/array.rb index 53d880660..a677b2a1f 100644 --- a/mrblib/array.rb +++ b/mrblib/array.rb @@ -66,7 +66,7 @@ class Array # # ISO 15.2.12.5.15 def initialize(size=0, obj=nil, &block) - raise TypeError, "expected Integer for 1st argument" unless size.kind_of? Integral + size = size.__to_int raise ArgumentError, "negative array size" if size < 0 self.clear diff --git a/src/kernel.c b/src/kernel.c index db681d510..195594d6b 100644 --- a/src/kernel.c +++ b/src/kernel.c @@ -830,6 +830,7 @@ mrb_obj_ceqq(mrb_state *mrb, mrb_value self) } mrb_value mrb_obj_equal_m(mrb_state *mrb, mrb_value); + void mrb_init_kernel(mrb_state *mrb) { @@ -871,6 +872,7 @@ mrb_init_kernel(mrb_state *mrb) mrb_define_method(mrb, krn, "respond_to?", obj_respond_to, MRB_ARGS_ANY()); /* 15.3.1.3.43 */ mrb_define_method(mrb, krn, "to_s", mrb_any_to_s, MRB_ARGS_NONE()); /* 15.3.1.3.46 */ mrb_define_method(mrb, krn, "__case_eqq", mrb_obj_ceqq, MRB_ARGS_REQ(1)); /* internal */ + mrb_define_method(mrb, krn, "__to_int", mrb_to_int, MRB_ARGS_NONE()); /* internal */ mrb_define_method(mrb, krn, "class_defined?", mrb_krn_class_defined, MRB_ARGS_REQ(1)); diff --git a/src/numeric.c b/src/numeric.c index f7f0318e8..3624831cc 100644 --- a/src/numeric.c +++ b/src/numeric.c @@ -674,7 +674,6 @@ flo_round(mrb_state *mrb, mrb_value num) /* * call-seq: * flt.to_i -> integer - * flt.to_int -> integer * flt.truncate -> integer * * Returns flt truncated to an Integer. @@ -714,7 +713,6 @@ flo_nan_p(mrb_state *mrb, mrb_value num) /* * call-seq: * int.to_i -> integer - * int.to_int -> integer * * As int is already an Integer, all these * methods simply return the receiver. @@ -1513,7 +1511,6 @@ mrb_init_numeric(mrb_state *mrb) MRB_SET_INSTANCE_TT(integer, MRB_TT_FIXNUM); mrb_undef_class_method(mrb, integer, "new"); mrb_define_method(mrb, integer, "to_i", int_to_i, MRB_ARGS_NONE()); /* 15.2.8.3.24 */ - mrb_define_method(mrb, integer, "to_int", int_to_i, MRB_ARGS_NONE()); #ifndef MRB_WITHOUT_FLOAT mrb_define_method(mrb, integer, "ceil", int_to_i, MRB_ARGS_REQ(1)); /* 15.2.8.3.8 (x) */ mrb_define_method(mrb, integer, "floor", int_to_i, MRB_ARGS_REQ(1)); /* 15.2.8.3.10 (x) */ @@ -1565,7 +1562,6 @@ mrb_init_numeric(mrb_state *mrb) mrb_define_method(mrb, fl, "round", flo_round, MRB_ARGS_OPT(1)); /* 15.2.9.3.12 */ mrb_define_method(mrb, fl, "to_f", flo_to_f, MRB_ARGS_NONE()); /* 15.2.9.3.13 */ mrb_define_method(mrb, fl, "to_i", flo_truncate, MRB_ARGS_NONE()); /* 15.2.9.3.14 */ - mrb_define_method(mrb, fl, "to_int", flo_truncate, MRB_ARGS_NONE()); mrb_define_method(mrb, fl, "truncate", flo_truncate, MRB_ARGS_NONE()); /* 15.2.9.3.15 */ mrb_define_method(mrb, fl, "divmod", flo_divmod, MRB_ARGS_REQ(1)); mrb_define_method(mrb, fl, "eql?", flo_eql, MRB_ARGS_REQ(1)); /* 15.2.8.3.16 */ diff --git a/src/object.c b/src/object.c index 8724c5416..ba6fa3947 100644 --- a/src/object.c +++ b/src/object.c @@ -322,19 +322,6 @@ convert_type(mrb_state *mrb, mrb_value val, const char *tname, const char *metho return mrb_funcall_argv(mrb, val, m, 0, 0); } -MRB_API mrb_value -mrb_check_to_integer(mrb_state *mrb, mrb_value val, const char *method) -{ - mrb_value v; - - if (mrb_fixnum_p(val)) return val; - v = convert_type(mrb, val, "Integer", method, FALSE); - if (mrb_nil_p(v) || !mrb_fixnum_p(v)) { - return mrb_nil_value(); - } - return v; -} - MRB_API mrb_value mrb_convert_type(mrb_state *mrb, mrb_value val, enum mrb_vtype type, const char *tname, const char *method) { @@ -505,25 +492,22 @@ mrb_obj_is_kind_of(mrb_state *mrb, mrb_value obj, struct RClass *c) return FALSE; } -static mrb_value -mrb_to_integer(mrb_state *mrb, mrb_value val, const char *method) -{ - mrb_value v; - - if (mrb_fixnum_p(val)) return val; - v = convert_type(mrb, val, "Integer", method, TRUE); - if (!mrb_obj_is_kind_of(mrb, v, mrb->fixnum_class)) { - mrb_value type = inspect_type(mrb, val); - mrb_raisef(mrb, E_TYPE_ERROR, "can't convert %S to Integer (%S#%S gives %S)", - type, type, mrb_str_new_cstr(mrb, method), inspect_type(mrb, v)); - } - return v; -} - MRB_API mrb_value mrb_to_int(mrb_state *mrb, mrb_value val) { - return mrb_to_integer(mrb, val, "to_int"); + + if (!mrb_fixnum_p(val)) { + mrb_value type; + +#ifndef MRB_WITHOUT_FLOAT + if (mrb_float_p(val)) { + return mrb_flo_to_fixnum(mrb, val); + } +#endif + type = inspect_type(mrb, val); + mrb_raisef(mrb, E_TYPE_ERROR, "can't convert %S to Integer", type); + } + return val; } MRB_API mrb_value @@ -533,18 +517,12 @@ mrb_convert_to_integer(mrb_state *mrb, mrb_value val, mrb_int base) if (mrb_nil_p(val)) { if (base != 0) goto arg_error; - mrb_raise(mrb, E_TYPE_ERROR, "can't convert nil into Integer"); + mrb_raise(mrb, E_TYPE_ERROR, "can't convert nil into Integer"); } switch (mrb_type(val)) { #ifndef MRB_WITHOUT_FLOAT case MRB_TT_FLOAT: if (base != 0) goto arg_error; - else { - mrb_float f = mrb_float(val); - if (FIXABLE_FLOAT(f)) { - break; - } - } return mrb_flo_to_fixnum(mrb, val); #endif @@ -568,11 +546,8 @@ mrb_convert_to_integer(mrb_state *mrb, mrb_value val, mrb_int base) arg_error: mrb_raise(mrb, E_ARGUMENT_ERROR, "base specified for non string value"); } - tmp = convert_type(mrb, val, "Integer", "to_int", FALSE); - if (mrb_nil_p(tmp) || !mrb_fixnum_p(tmp)) { - tmp = mrb_to_integer(mrb, val, "to_i"); - } - return tmp; + /* to raise TypeError */ + return mrb_to_int(mrb, val); } MRB_API mrb_value -- cgit v1.2.3 From e690314525d3ebfa23eda9f2cacfff37bd53482a Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Mon, 17 Dec 2018 15:52:04 +0900 Subject: Recover `#to_int`; ref #4177 We have removed implicit conversion to strings using `to_int`. But some users still using `to_int` as a typical integer method, i.e. they do string check by code like: `obj.respond_to?(:to_int)`. So we have recovered the method. --- src/numeric.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'src/numeric.c') diff --git a/src/numeric.c b/src/numeric.c index 3624831cc..077ae30aa 100644 --- a/src/numeric.c +++ b/src/numeric.c @@ -1511,6 +1511,7 @@ mrb_init_numeric(mrb_state *mrb) MRB_SET_INSTANCE_TT(integer, MRB_TT_FIXNUM); mrb_undef_class_method(mrb, integer, "new"); mrb_define_method(mrb, integer, "to_i", int_to_i, MRB_ARGS_NONE()); /* 15.2.8.3.24 */ + mrb_define_method(mrb, integer, "to_int", int_to_i, MRB_ARGS_NONE()); #ifndef MRB_WITHOUT_FLOAT mrb_define_method(mrb, integer, "ceil", int_to_i, MRB_ARGS_REQ(1)); /* 15.2.8.3.8 (x) */ mrb_define_method(mrb, integer, "floor", int_to_i, MRB_ARGS_REQ(1)); /* 15.2.8.3.10 (x) */ @@ -1562,6 +1563,7 @@ mrb_init_numeric(mrb_state *mrb) mrb_define_method(mrb, fl, "round", flo_round, MRB_ARGS_OPT(1)); /* 15.2.9.3.12 */ mrb_define_method(mrb, fl, "to_f", flo_to_f, MRB_ARGS_NONE()); /* 15.2.9.3.13 */ mrb_define_method(mrb, fl, "to_i", flo_truncate, MRB_ARGS_NONE()); /* 15.2.9.3.14 */ + mrb_define_method(mrb, fl, "to_int", flo_truncate, MRB_ARGS_NONE()); mrb_define_method(mrb, fl, "truncate", flo_truncate, MRB_ARGS_NONE()); /* 15.2.9.3.15 */ mrb_define_method(mrb, fl, "divmod", flo_divmod, MRB_ARGS_REQ(1)); mrb_define_method(mrb, fl, "eql?", flo_eql, MRB_ARGS_REQ(1)); /* 15.2.8.3.16 */ -- cgit v1.2.3 From b30ca87bd07a29a2dddc4960ce80f767ff9552ca Mon Sep 17 00:00:00 2001 From: KOBAYASHI Shuji Date: Fri, 4 Jan 2019 20:31:05 +0900 Subject: Integrate mrblib/float.rb into src/numeric.c - Avoid hack for `MRB_WITHOUT_FLOAT` in build scripts - Avoid runtime dispatch for `MRB_WITHOUT_FLOAT` --- mrblib/float.rb | 9 --------- mrblib/mrblib.rake | 3 --- src/numeric.c | 7 +++++-- 3 files changed, 5 insertions(+), 14 deletions(-) delete mode 100644 mrblib/float.rb (limited to 'src/numeric.c') diff --git a/mrblib/float.rb b/mrblib/float.rb deleted file mode 100644 index 421b8d851..000000000 --- a/mrblib/float.rb +++ /dev/null @@ -1,9 +0,0 @@ -## -# Float -# -# ISO 15.2.9 -class Float - # mruby special - since mruby integers may be upgraded to floats, - # floats should be compatible to integers. - include Integral -end if Object.const_defined?(:Float) diff --git a/mrblib/mrblib.rake b/mrblib/mrblib.rake index 6895d4252..e96decb27 100644 --- a/mrblib/mrblib.rake +++ b/mrblib/mrblib.rake @@ -8,9 +8,6 @@ MRuby.each_target do file objfile("#{current_build_dir}/mrblib") => "#{current_build_dir}/mrblib.c" file "#{current_build_dir}/mrblib.c" => [mrbcfile, __FILE__] + Dir.glob("#{current_dir}/*.rb").sort do |t| _, _, *rbfiles = t.prerequisites - if self.cc.defines.flatten.include?("MRB_WITHOUT_FLOAT") - rbfiles.delete("#{current_dir}/float.rb") - end FileUtils.mkdir_p File.dirname(t.name) open(t.name, 'w') do |f| _pp "GEN", "*.rb", "#{t.name.relative_path}" diff --git a/src/numeric.c b/src/numeric.c index 077ae30aa..311bb4a38 100644 --- a/src/numeric.c +++ b/src/numeric.c @@ -1487,11 +1487,13 @@ flo_plus(mrb_state *mrb, mrb_value x) void mrb_init_numeric(mrb_state *mrb) { - struct RClass *numeric, *integer, *fixnum; + struct RClass *numeric, *integer, *fixnum, *integral; #ifndef MRB_WITHOUT_FLOAT struct RClass *fl; #endif + integral = mrb_define_module(mrb, "Integral"); + /* Numeric Class */ numeric = mrb_define_class(mrb, "Numeric", mrb->object_class); /* 15.2.7 */ @@ -1578,6 +1580,7 @@ mrb_init_numeric(mrb_state *mrb) #ifdef NAN mrb_define_const(mrb, fl, "NAN", mrb_float_value(mrb, NAN)); #endif + + mrb_include_module(mrb, fl, integral); #endif - mrb_define_module(mrb, "Integral"); } -- cgit v1.2.3 From 856b8d961015d67eb7b4958eb974bbfabbc1066a Mon Sep 17 00:00:00 2001 From: KOBAYASHI Shuji Date: Thu, 10 Jan 2019 23:22:23 +0900 Subject: Remove duplicate code in numeric.c --- src/numeric.c | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) (limited to 'src/numeric.c') diff --git a/src/numeric.c b/src/numeric.c index 311bb4a38..089cc744d 100644 --- a/src/numeric.c +++ b/src/numeric.c @@ -1150,7 +1150,7 @@ fix_to_f(mrb_state *mrb, mrb_value num) * (in particular infinite or NaN) * to numerical classes which don't support them. * - * Float::INFINITY.to_r + * Float::INFINITY.to_i * * raises the exception: * @@ -1169,12 +1169,7 @@ mrb_flo_to_fixnum(mrb_state *mrb, mrb_value x) else { mrb_float d = mrb_float(x); - if (isinf(d)) { - mrb_raise(mrb, E_FLOATDOMAIN_ERROR, d < 0 ? "-Infinity" : "Infinity"); - } - if (isnan(d)) { - mrb_raise(mrb, E_FLOATDOMAIN_ERROR, "NaN"); - } + mrb_check_num_exact(mrb, d); if (FIXABLE_FLOAT(d)) { z = (mrb_int)d; } -- cgit v1.2.3 From 9f081183d2351195c821fbe1520975ba000cafb5 Mon Sep 17 00:00:00 2001 From: KOBAYASHI Shuji Date: Sun, 13 Jan 2019 19:59:22 +0900 Subject: Improve compatibility to CRuby for `Float#to_s` Bfore: Float::INFINITY.to_s #=> "inf" 50.0.to_s #=> "50" 1e20.to_s #=> "1e+20" After / CRuby: Float::INFINITY.to_s #=> "Infinity" 50.0.to_s #=> "50.0" 1e20.to_s #=> "1.0e+20" --- src/numeric.c | 48 ++++++++++++++++++++++++++++++++++++++++++++---- test/t/float.rb | 33 +++++++++++++++++++++++++++++++++ 2 files changed, 77 insertions(+), 4 deletions(-) (limited to 'src/numeric.c') diff --git a/src/numeric.c b/src/numeric.c index 089cc744d..fc8460300 100644 --- a/src/numeric.c +++ b/src/numeric.c @@ -10,6 +10,7 @@ #endif #include #include +#include #include #include @@ -23,9 +24,9 @@ #define floor(f) floorf(f) #define ceil(f) ceilf(f) #define fmod(x,y) fmodf(x,y) -#define MRB_FLO_TO_STR_FMT "%.8g" +#define FLO_TO_STR_PREC 8 #else -#define MRB_FLO_TO_STR_FMT "%.16g" +#define FLO_TO_STR_PREC 16 #endif #endif @@ -177,10 +178,49 @@ num_div(mrb_state *mrb, mrb_value x) static mrb_value flo_to_s(mrb_state *mrb, mrb_value flt) { - if (isnan(mrb_float(flt))) { + mrb_float f = mrb_float(flt); + + if (isinf(f)) { + return f < 0 ? mrb_str_new_lit(mrb, "-Infinity") + : mrb_str_new_lit(mrb, "Infinity"); + } + else if (isnan(f)) { return mrb_str_new_lit(mrb, "NaN"); } - return mrb_float_to_str(mrb, flt, MRB_FLO_TO_STR_FMT); + else { + char fmt[] = "%." MRB_STRINGIZE(FLO_TO_STR_PREC) "g"; + mrb_value str = mrb_float_to_str(mrb, flt, fmt); + mrb_int len; + char *begp; + + insert_dot_zero: + begp = RSTRING_PTR(str); + len = RSTRING_LEN(str); + for (char *p = begp, *endp = p + len; p < endp; ++p) { + if (*p == '.') { + return str; + } + else if (*p == 'e') { + ptrdiff_t e_pos = p - begp; + mrb_str_cat(mrb, str, ".0", 2); + p = RSTRING_PTR(str) + e_pos; + memmove(p + 2, p, len - e_pos); + memcpy(p, ".0", 2); + return str; + } + } + + if (FLO_TO_STR_PREC + (begp[0] == '-') <= len) { + --fmt[sizeof(fmt) - 3]; /* %.16g(%.8g) -> %.15g(%.7g) */ + str = mrb_float_to_str(mrb, flt, fmt); + goto insert_dot_zero; + } + else { + mrb_str_cat(mrb, str, ".0", 2); + } + + return str; + } } /* 15.2.9.3.2 */ diff --git a/test/t/float.rb b/test/t/float.rb index 68fd31b9a..eac5c5792 100644 --- a/test/t/float.rb +++ b/test/t/float.rb @@ -206,4 +206,37 @@ assert('Float#>>') do assert_equal(-1, -23.0 >> 128) end +assert('Float#to_s') do + uses_float = 4e38.infinite? # enable MRB_USE_FLOAT? + + assert_equal("Infinity", Float::INFINITY.to_s) + assert_equal("-Infinity", (-Float::INFINITY).to_s) + assert_equal("NaN", Float::NAN.to_s) + assert_equal("0.0", 0.0.to_s) + assert_equal("-0.0", -0.0.to_s) + assert_equal("-3.21", -3.21.to_s) + assert_equal("50.0", 50.0.to_s) + assert_equal("0.00021", 0.00021.to_s) + assert_equal("-0.00021", -0.00021.to_s) + assert_equal("2.1e-05", 0.000021.to_s) + assert_equal("-2.1e-05", -0.000021.to_s) + assert_equal("1.0e+20", 1e20.to_s) + assert_equal("-1.0e+20", -1e20.to_s) + assert_equal("1.0e+16", 10000000000000000.0.to_s) + assert_equal("-1.0e+16", -10000000000000000.0.to_s) + assert_equal("100000.0", 100000.0.to_s) + assert_equal("-100000.0", -100000.0.to_s) + if uses_float + assert_equal("1.0e+08", 100000000.0.to_s) + assert_equal("-1.0e+08", -100000000.0.to_s) + assert_equal("1.0e+07", 10000000.0.to_s) + assert_equal("-1.0e+07", -10000000.0.to_s) + else + assert_equal("1.0e+15", 1000000000000000.0.to_s) + assert_equal("-1.0e+15", -1000000000000000.0.to_s) + assert_equal("100000000000000.0", 100000000000000.0.to_s) + assert_equal("-100000000000000.0", -100000000000000.0.to_s) + end +end + end # const_defined?(:Float) -- cgit v1.2.3 From 8969edf03b2f4ff8537974c2bd30e9abe2002da6 Mon Sep 17 00:00:00 2001 From: KOBAYASHI Shuji Date: Wed, 16 Jan 2019 19:32:29 +0900 Subject: Avoid runtime evaluation for `MRB_WITHOUT_FLOAT` --- mrblib/numeric.rb | 9 +-------- src/numeric.c | 17 +++++++++++++++++ 2 files changed, 18 insertions(+), 8 deletions(-) (limited to 'src/numeric.c') diff --git a/mrblib/numeric.rb b/mrblib/numeric.rb index dfdaf9da8..5a3c5eb58 100644 --- a/mrblib/numeric.rb +++ b/mrblib/numeric.rb @@ -104,14 +104,7 @@ module Integral raise ArgumentError, "step can't be 0" if step == 0 return to_enum(:step, num, step) unless block - i = self - if Object.const_defined?(:Float) && - (kind_of?(Float) || num.kind_of?(Float) || step.kind_of?(Float)) - i = i.to_f - num = num.to_f unless num == nil - step = step.to_f - end - + i = __coerce_step_counter(num, step) if num == nil while true block.call(i) diff --git a/src/numeric.c b/src/numeric.c index fc8460300..fa9daf8a7 100644 --- a/src/numeric.c +++ b/src/numeric.c @@ -154,6 +154,22 @@ num_div(mrb_state *mrb, mrb_value x) #endif } +static mrb_value +num_coerce_step_counter(mrb_state *mrb, mrb_value self) +{ + mrb_value counter = self, num, step; + + mrb_get_args(mrb, "oo", &num, &step); + +#ifndef MRB_WITHOUT_FLOAT + if (mrb_float_p(self) || mrb_float_p(num) || mrb_float_p(step)) { + counter = mrb_funcall(mrb, counter, "to_f", 0); + } +#endif + + return counter; +} + #ifndef MRB_WITHOUT_FLOAT /******************************************************************** * @@ -1542,6 +1558,7 @@ mrb_init_numeric(mrb_state *mrb) mrb_define_method(mrb, numeric, ">=", num_ge, MRB_ARGS_REQ(1)); mrb_define_method(mrb, numeric, "finite?", num_finite_p, MRB_ARGS_NONE()); mrb_define_method(mrb, numeric, "infinite?",num_infinite_p, MRB_ARGS_NONE()); + mrb_define_method(mrb, numeric, "__coerce_step_counter", num_coerce_step_counter, MRB_ARGS_REQ(2)); /* Integer Class */ integer = mrb_define_class(mrb, "Integer", numeric); /* 15.2.8 */ -- cgit v1.2.3 From a41b02ab918d7fb976234e1b07e2e60eff4d9f96 Mon Sep 17 00:00:00 2001 From: KOBAYASHI Shuji Date: Thu, 21 Mar 2019 21:36:54 +0900 Subject: Fix `Float#eql?` --- src/numeric.c | 2 +- test/t/float.rb | 6 ++++++ 2 files changed, 7 insertions(+), 1 deletion(-) (limited to 'src/numeric.c') diff --git a/src/numeric.c b/src/numeric.c index fa9daf8a7..4128ea3a6 100644 --- a/src/numeric.c +++ b/src/numeric.c @@ -369,7 +369,7 @@ flo_eql(mrb_state *mrb, mrb_value x) mrb_get_args(mrb, "o", &y); if (!mrb_float_p(y)) return mrb_false_value(); - return mrb_bool_value(mrb_float(x) == (mrb_float)mrb_fixnum(y)); + return mrb_bool_value(mrb_float(x) == mrb_float(y)); } /* 15.2.9.3.7 */ diff --git a/test/t/float.rb b/test/t/float.rb index c137698d3..910d7b1d5 100644 --- a/test/t/float.rb +++ b/test/t/float.rb @@ -239,4 +239,10 @@ assert('Float#to_s') do end end +assert('Float#eql?') do + assert_true(5.0.eql?(5.0)) + assert_false(5.0.eql?(5)) + assert_false(5.0.eql?("5.0")) +end + end # const_defined?(:Float) -- cgit v1.2.3 From 6cec0c9f62c176e9bd926d12551b384315e98388 Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Mon, 8 Apr 2019 19:02:45 +0900 Subject: Fix C99 style inline declaration; fix #4365 --- src/numeric.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/numeric.c') diff --git a/src/numeric.c b/src/numeric.c index 4128ea3a6..742df7b76 100644 --- a/src/numeric.c +++ b/src/numeric.c @@ -207,12 +207,12 @@ flo_to_s(mrb_state *mrb, mrb_value flt) char fmt[] = "%." MRB_STRINGIZE(FLO_TO_STR_PREC) "g"; mrb_value str = mrb_float_to_str(mrb, flt, fmt); mrb_int len; - char *begp; + char *begp, *p, *endp; insert_dot_zero: begp = RSTRING_PTR(str); len = RSTRING_LEN(str); - for (char *p = begp, *endp = p + len; p < endp; ++p) { + for (p = begp, endp = p + len; p < endp; ++p) { if (*p == '.') { return str; } -- cgit v1.2.3 From 6b8d3c70702948e630536e7c42400e928ed9d773 Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Mon, 15 Apr 2019 07:13:19 +0900 Subject: Fixed wrong function names; fix #4380 --- src/numeric.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'src/numeric.c') diff --git a/src/numeric.c b/src/numeric.c index 742df7b76..8205e41f6 100644 --- a/src/numeric.c +++ b/src/numeric.c @@ -510,7 +510,7 @@ flo_shift(mrb_state *mrb, mrb_value x, mrb_int width) } static mrb_value -flo_lshift(mrb_state *mrb, mrb_value x) +flo_rshift(mrb_state *mrb, mrb_value x) { mrb_int width; @@ -519,7 +519,7 @@ flo_lshift(mrb_state *mrb, mrb_value x) } static mrb_value -flo_rshift(mrb_state *mrb, mrb_value x) +flo_lshift(mrb_state *mrb, mrb_value x) { mrb_int width; @@ -1608,8 +1608,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, ">>", flo_rshift, MRB_ARGS_REQ(1)); + mrb_define_method(mrb, fl, "<<", flo_lshift, 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 95a92d35c89ec9c39c97c5f948255389a129029e Mon Sep 17 00:00:00 2001 From: KOBAYASHI Shuji Date: Thu, 2 May 2019 20:45:31 +0900 Subject: Unify overflow error class for conversion to integer to `RangeError` --- src/numeric.c | 2 +- src/string.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'src/numeric.c') diff --git a/src/numeric.c b/src/numeric.c index 8205e41f6..101b338de 100644 --- a/src/numeric.c +++ b/src/numeric.c @@ -1230,7 +1230,7 @@ mrb_flo_to_fixnum(mrb_state *mrb, mrb_value x) z = (mrb_int)d; } else { - mrb_raisef(mrb, E_ARGUMENT_ERROR, "number (%S) too big for integer", x); + mrb_raisef(mrb, E_RANGE_ERROR, "number (%S) too big for integer", x); } } return mrb_fixnum_value(z); diff --git a/src/string.c b/src/string.c index 89ab59d4b..955ad57ce 100644 --- a/src/string.c +++ b/src/string.c @@ -2115,7 +2115,7 @@ mrb_str_len_to_inum(mrb_state *mrb, const char *str, mrb_int len, mrb_int base, else #endif { - mrb_raisef(mrb, E_ARGUMENT_ERROR, "string (%S) too big for integer", + mrb_raisef(mrb, E_RANGE_ERROR, "string (%S) too big for integer", mrb_str_new(mrb, str, pend-str)); } } -- cgit v1.2.3 From 752edf413f09fb3e78d79ca7d752ae5dc2e25c02 Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Thu, 16 May 2019 09:51:27 +0900 Subject: Terminate float right shift if shift value is too big. --- src/numeric.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'src/numeric.c') diff --git a/src/numeric.c b/src/numeric.c index 101b338de..5dbf9df22 100644 --- a/src/numeric.c +++ b/src/numeric.c @@ -484,6 +484,10 @@ flo_shift(mrb_state *mrb, mrb_value x, mrb_int width) if (width < 0) { while (width++) { val /= 2; + if (val < 1.0) { + val = 0; + break; + } } #if defined(_ISOC99_SOURCE) val = trunc(val); -- cgit v1.2.3 From 80c789b3941160312ac7ffed202abe8c23bc0628 Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Fri, 17 May 2019 10:40:19 +0900 Subject: Use `int64_t` instead of `mrb_int` in `int64_value`. --- src/numeric.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/numeric.c') diff --git a/src/numeric.c b/src/numeric.c index 5dbf9df22..113413502 100644 --- a/src/numeric.c +++ b/src/numeric.c @@ -421,7 +421,7 @@ value_int64(mrb_state *mrb, mrb_value x) static mrb_value int64_value(mrb_state *mrb, int64_t v) { - if (FIXABLE(v)) { + if (TYPED_FIXABLE(v,int64_t)) { return mrb_fixnum_value((mrb_int)v); } return mrb_float_value(mrb, (mrb_float)v); -- cgit v1.2.3 From 8a9f984eb8771a3d4956783116f972d4f5f70dfd Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Fri, 17 May 2019 10:42:16 +0900 Subject: Add a new function `mrb_int_value`. This function returns `Fixnum` if the value fits in `mrb_int`, otherwise it returns `Float` value (mruby behavior of handling integers). --- src/numeric.c | 29 +++++++++++++---------------- 1 file changed, 13 insertions(+), 16 deletions(-) (limited to 'src/numeric.c') diff --git a/src/numeric.c b/src/numeric.c index 113413502..30b6b230e 100644 --- a/src/numeric.c +++ b/src/numeric.c @@ -44,6 +44,15 @@ mrb_to_flo(mrb_state *mrb, mrb_value val) } return mrb_float(val); } + +static mrb_value +mrb_int_value(mrb_state *mrb, mrb_float f) +{ + if (FIXABLE_FLOAT(f)) { + return mrb_fixnum_value((mrb_int)f); + } + return mrb_float_value(mrb, f); +} #endif /* @@ -507,10 +516,7 @@ flo_shift(mrb_state *mrb, mrb_value x, mrb_int width) val *= 2; } } - if (FIXABLE_FLOAT(val)) { - return mrb_fixnum_value((mrb_int)val); - } - return mrb_float_value(mrb, val); + return mrb_int_value(mrb, val); } static mrb_value @@ -616,10 +622,7 @@ flo_floor(mrb_state *mrb, mrb_value num) mrb_float f = floor(mrb_float(num)); mrb_check_num_exact(mrb, f); - if (!FIXABLE_FLOAT(f)) { - return mrb_float_value(mrb, f); - } - return mrb_fixnum_value((mrb_int)f); + return mrb_int_value(mrb, f); } /* 15.2.9.3.8 */ @@ -642,10 +645,7 @@ flo_ceil(mrb_state *mrb, mrb_value num) mrb_float f = ceil(mrb_float(num)); mrb_check_num_exact(mrb, f); - if (!FIXABLE_FLOAT(f)) { - return mrb_float_value(mrb, f); - } - return mrb_fixnum_value((mrb_int)f); + return mrb_int_value(mrb, f); } /* 15.2.9.3.12 */ @@ -748,10 +748,7 @@ flo_truncate(mrb_state *mrb, mrb_value num) if (f < 0.0) f = ceil(f); mrb_check_num_exact(mrb, f); - if (!FIXABLE_FLOAT(f)) { - return mrb_float_value(mrb, f); - } - return mrb_fixnum_value((mrb_int)f); + return mrb_int_value(mrb, f); } static mrb_value -- cgit v1.2.3 From bc18060149fae9121fe744544521ca58989010ae Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Fri, 17 May 2019 10:44:56 +0900 Subject: Change the `num.divmod(float)` to return `[int,num]`. --- src/numeric.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/numeric.c') diff --git a/src/numeric.c b/src/numeric.c index 30b6b230e..ab8771e1a 100644 --- a/src/numeric.c +++ b/src/numeric.c @@ -934,7 +934,7 @@ fix_divmod(mrb_state *mrb, mrb_value x) mrb_value a, b; flodivmod(mrb, (mrb_float)mrb_fixnum(x), mrb_to_flo(mrb, y), &div, &mod); - a = mrb_float_value(mrb, div); + a = mrb_int_value(mrb, div); b = mrb_float_value(mrb, mod); return mrb_assoc_new(mrb, a, b); } @@ -952,7 +952,7 @@ flo_divmod(mrb_state *mrb, mrb_value x) mrb_get_args(mrb, "o", &y); flodivmod(mrb, mrb_float(x), mrb_to_flo(mrb, y), &div, &mod); - a = mrb_float_value(mrb, div); + a = mrb_int_value(mrb, div); b = mrb_float_value(mrb, mod); return mrb_assoc_new(mrb, a, b); } -- cgit v1.2.3 From 3734c53eb8e5fd34f572b62e2f85ed43b4f6d921 Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Fri, 17 May 2019 11:13:12 +0900 Subject: Make `flo_rount` to return `Integeral`. --- src/numeric.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/numeric.c') diff --git a/src/numeric.c b/src/numeric.c index ab8771e1a..954e91019 100644 --- a/src/numeric.c +++ b/src/numeric.c @@ -726,7 +726,7 @@ flo_round(mrb_state *mrb, mrb_value num) if (!isfinite(number)) return num; return mrb_float_value(mrb, number); } - return mrb_fixnum_value((mrb_int)number); + return mrb_int_value(mrb, number); } /* 15.2.9.3.14 */ -- cgit v1.2.3 From 223defd62ae511786a2b50c68ed97b73bfc05d59 Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Fri, 17 May 2019 11:26:16 +0900 Subject: Move `Numeric#div` to the core. --- mrbgems/mruby-numeric-ext/mrblib/numeric_ext.rb | 4 ---- src/numeric.c | 20 ++++++++++++++++++++ 2 files changed, 20 insertions(+), 4 deletions(-) (limited to 'src/numeric.c') diff --git a/mrbgems/mruby-numeric-ext/mrblib/numeric_ext.rb b/mrbgems/mruby-numeric-ext/mrblib/numeric_ext.rb index f250538fe..e86e8b283 100644 --- a/mrbgems/mruby-numeric-ext/mrblib/numeric_ext.rb +++ b/mrbgems/mruby-numeric-ext/mrblib/numeric_ext.rb @@ -1,8 +1,4 @@ module Integral - def div(other) - self.divmod(other)[0] - end - def zero? self == 0 end diff --git a/src/numeric.c b/src/numeric.c index 954e91019..8c17635a2 100644 --- a/src/numeric.c +++ b/src/numeric.c @@ -136,6 +136,25 @@ mrb_num_div(mrb_state *mrb, mrb_value x, mrb_value y) #endif } +static mrb_value +num_idiv(mrb_state *mrb, mrb_value x) +{ +#ifdef MRB_WITHOUT_FLOAT + mrb_value y; + + mrb_get_args(mrb, "o", &y); + if (!mrb_fixnum_p(y)) { + mrb_raise(mrb, E_TYPE_ERROR, "non fixnum value"); + } + return mrb_fixnum_value(mrb_fixnum(x) / mrb_fixnum(y)); +#else + mrb_float y; + + mrb_get_args(mrb, "f", &y); + return mrb_int_value(mrb, mrb_to_flo(mrb, x) / y); +#endif +} + /* 15.2.9.3.19(x) */ /* * call-seq: @@ -1552,6 +1571,7 @@ mrb_init_numeric(mrb_state *mrb) mrb_define_method(mrb, numeric, "**", num_pow, MRB_ARGS_REQ(1)); mrb_define_method(mrb, numeric, "/", num_div, MRB_ARGS_REQ(1)); /* 15.2.8.3.4 */ mrb_define_method(mrb, numeric, "quo", num_div, MRB_ARGS_REQ(1)); /* 15.2.7.4.5 (x) */ + mrb_define_method(mrb, numeric, "div", num_idiv, MRB_ARGS_REQ(1)); mrb_define_method(mrb, numeric, "<=>", num_cmp, MRB_ARGS_REQ(1)); /* 15.2.9.3.6 */ mrb_define_method(mrb, numeric, "<", num_lt, MRB_ARGS_REQ(1)); mrb_define_method(mrb, numeric, "<=", num_le, MRB_ARGS_REQ(1)); -- cgit v1.2.3 From 0c91da257bf64769d85a709852cfa2da313a4185 Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Fri, 17 May 2019 11:27:21 +0900 Subject: Remove unused `mrb_num_div()` function. --- include/mruby/numeric.h | 1 - src/numeric.c | 35 +++++++++++------------------------ 2 files changed, 11 insertions(+), 25 deletions(-) (limited to 'src/numeric.c') diff --git a/include/mruby/numeric.h b/include/mruby/numeric.h index 9a04631d6..2fae3142d 100644 --- a/include/mruby/numeric.h +++ b/include/mruby/numeric.h @@ -39,7 +39,6 @@ MRB_API mrb_float mrb_to_flo(mrb_state *mrb, mrb_value x); mrb_value mrb_fixnum_plus(mrb_state *mrb, mrb_value x, mrb_value y); mrb_value mrb_fixnum_minus(mrb_state *mrb, mrb_value x, mrb_value y); mrb_value mrb_fixnum_mul(mrb_state *mrb, mrb_value x, mrb_value y); -mrb_value mrb_num_div(mrb_state *mrb, mrb_value x, mrb_value y); #ifndef __has_builtin #define __has_builtin(x) 0 diff --git a/src/numeric.c b/src/numeric.c index 8c17635a2..8e5fefa04 100644 --- a/src/numeric.c +++ b/src/numeric.c @@ -112,30 +112,6 @@ num_pow(mrb_state *mrb, mrb_value x) #endif } -/* 15.2.8.3.4 */ -/* 15.2.9.3.4 */ -/* - * call-seq: - * num / other -> num - * - * Performs division: the class of the resulting object depends on - * the class of num and on the magnitude of the - * result. - */ - -mrb_value -mrb_num_div(mrb_state *mrb, mrb_value x, mrb_value y) -{ -#ifdef MRB_WITHOUT_FLOAT - if (!mrb_fixnum_p(y)) { - mrb_raise(mrb, E_TYPE_ERROR, "non fixnum value"); - } - return mrb_fixnum_value(mrb_fixnum(x) / mrb_fixnum(y)); -#else - return mrb_float_value(mrb, mrb_to_flo(mrb, x) / mrb_to_flo(mrb, y)); -#endif -} - static mrb_value num_idiv(mrb_state *mrb, mrb_value x) { @@ -155,6 +131,17 @@ num_idiv(mrb_state *mrb, mrb_value x) #endif } +/* 15.2.8.3.4 */ +/* 15.2.9.3.4 */ +/* + * call-seq: + * num / other -> num + * + * Performs division: the class of the resulting object depends on + * the class of num and on the magnitude of the + * result. + */ + /* 15.2.9.3.19(x) */ /* * call-seq: -- cgit v1.2.3 From 237a57bbe831c57d3ebb0f9cc69768dbc8dda589 Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Fri, 17 May 2019 11:30:38 +0900 Subject: Make unused functions private. * mrb_fixnum_plus() * mrb_fixnum_minus() * mrb_fixnum_mul() --- include/mruby/numeric.h | 4 ---- src/numeric.c | 6 +++--- 2 files changed, 3 insertions(+), 7 deletions(-) (limited to 'src/numeric.c') diff --git a/include/mruby/numeric.h b/include/mruby/numeric.h index 2fae3142d..9d87ca5c4 100644 --- a/include/mruby/numeric.h +++ b/include/mruby/numeric.h @@ -36,10 +36,6 @@ MRB_API mrb_value mrb_float_to_str(mrb_state *mrb, mrb_value x, const char *fmt) MRB_API mrb_float mrb_to_flo(mrb_state *mrb, mrb_value x); #endif -mrb_value mrb_fixnum_plus(mrb_state *mrb, mrb_value x, mrb_value y); -mrb_value mrb_fixnum_minus(mrb_state *mrb, mrb_value x, mrb_value y); -mrb_value mrb_fixnum_mul(mrb_state *mrb, mrb_value x, mrb_value y); - #ifndef __has_builtin #define __has_builtin(x) 0 #endif diff --git a/src/numeric.c b/src/numeric.c index 8e5fefa04..6622a46e9 100644 --- a/src/numeric.c +++ b/src/numeric.c @@ -787,7 +787,7 @@ int_to_i(mrb_state *mrb, mrb_value num) return num; } -mrb_value +static mrb_value mrb_fixnum_mul(mrb_state *mrb, mrb_value x, mrb_value y) { mrb_int a; @@ -1244,7 +1244,7 @@ mrb_flo_to_fixnum(mrb_state *mrb, mrb_value x) } #endif -mrb_value +static mrb_value mrb_fixnum_plus(mrb_state *mrb, mrb_value x, mrb_value y) { mrb_int a; @@ -1287,7 +1287,7 @@ fix_plus(mrb_state *mrb, mrb_value self) return mrb_fixnum_plus(mrb, self, other); } -mrb_value +static mrb_value mrb_fixnum_minus(mrb_state *mrb, mrb_value x, mrb_value y) { mrb_int a; -- cgit v1.2.3 From 4f71e9eebe2a4dc17092768aeabf75af0bbae1ce Mon Sep 17 00:00:00 2001 From: KOBAYASHI Shuji Date: Sat, 18 May 2019 18:22:56 +0900 Subject: Move `Numeric#__coerce_step_counter` to `Integral` This method is only used in `Integral#step` --- src/numeric.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/numeric.c') diff --git a/src/numeric.c b/src/numeric.c index 6622a46e9..e73bdaca2 100644 --- a/src/numeric.c +++ b/src/numeric.c @@ -170,7 +170,7 @@ num_div(mrb_state *mrb, mrb_value x) } static mrb_value -num_coerce_step_counter(mrb_state *mrb, mrb_value self) +integral_coerce_step_counter(mrb_state *mrb, mrb_value self) { mrb_value counter = self, num, step; @@ -1551,6 +1551,7 @@ mrb_init_numeric(mrb_state *mrb) #endif integral = mrb_define_module(mrb, "Integral"); + mrb_define_method(mrb, integral, "__coerce_step_counter", integral_coerce_step_counter, MRB_ARGS_REQ(2)); /* Numeric Class */ numeric = mrb_define_class(mrb, "Numeric", mrb->object_class); /* 15.2.7 */ @@ -1566,7 +1567,6 @@ mrb_init_numeric(mrb_state *mrb) mrb_define_method(mrb, numeric, ">=", num_ge, MRB_ARGS_REQ(1)); mrb_define_method(mrb, numeric, "finite?", num_finite_p, MRB_ARGS_NONE()); mrb_define_method(mrb, numeric, "infinite?",num_infinite_p, MRB_ARGS_NONE()); - mrb_define_method(mrb, numeric, "__coerce_step_counter", num_coerce_step_counter, MRB_ARGS_REQ(2)); /* Integer Class */ integer = mrb_define_class(mrb, "Integer", numeric); /* 15.2.8 */ -- cgit v1.2.3 From 8b8bf9f3f696f28836138b8106147d9d3e6071a2 Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Mon, 20 May 2019 14:59:25 +0900 Subject: Add new functions for numerical operation; ref 237a57b New functions: * mrb_num_plus(mrb, x, y) * mrb_num_minus(mrb, x, y) * num_num_mul(mrb, x, y) --- include/mruby/numeric.h | 4 ++++ src/numeric.c | 54 +++++++++++++++++++++++++++++++++++++++++++------ 2 files changed, 52 insertions(+), 6 deletions(-) (limited to 'src/numeric.c') diff --git a/include/mruby/numeric.h b/include/mruby/numeric.h index 9d87ca5c4..d670504c2 100644 --- a/include/mruby/numeric.h +++ b/include/mruby/numeric.h @@ -36,6 +36,10 @@ MRB_API mrb_value mrb_float_to_str(mrb_state *mrb, mrb_value x, const char *fmt) MRB_API mrb_float mrb_to_flo(mrb_state *mrb, mrb_value x); #endif +MRB_API mrb_value mrb_num_plus(mrb_state *mrb, mrb_value x, mrb_value y); +MRB_API mrb_value mrb_num_minus(mrb_state *mrb, mrb_value x, mrb_value y); +MRB_API mrb_value mrb_num_mul(mrb_state *mrb, mrb_value x, mrb_value y); + #ifndef __has_builtin #define __has_builtin(x) 0 #endif diff --git a/src/numeric.c b/src/numeric.c index e73bdaca2..3ad5721ef 100644 --- a/src/numeric.c +++ b/src/numeric.c @@ -788,7 +788,7 @@ int_to_i(mrb_state *mrb, mrb_value num) } static mrb_value -mrb_fixnum_mul(mrb_state *mrb, mrb_value x, mrb_value y) +fixnum_mul(mrb_state *mrb, mrb_value x, mrb_value y) { mrb_int a; @@ -812,6 +812,20 @@ mrb_fixnum_mul(mrb_state *mrb, mrb_value x, mrb_value y) #endif } +MRB_API mrb_value +mrb_num_mul(mrb_state *mrb, mrb_value x, mrb_value y) +{ + if (mrb_fixnum_p(x)) { + return fixnum_mul(mrb, x, y); + } +#ifndef MRB_WITHOUT_FLOAT + if (mrb_float_p(x)) { + return mrb_float_value(mrb, mrb_float(x) * mrb_to_flo(mrb, y)); + } +#endif + mrb_raise(mrb, E_TYPE_ERROR, "no number multiply"); +} + /* 15.2.8.3.3 */ /* * call-seq: @@ -828,7 +842,7 @@ fix_mul(mrb_state *mrb, mrb_value x) mrb_value y; mrb_get_args(mrb, "o", &y); - return mrb_fixnum_mul(mrb, x, y); + return fixnum_mul(mrb, x, y); } static void @@ -1245,7 +1259,7 @@ mrb_flo_to_fixnum(mrb_state *mrb, mrb_value x) #endif static mrb_value -mrb_fixnum_plus(mrb_state *mrb, mrb_value x, mrb_value y) +fixnum_plus(mrb_state *mrb, mrb_value x, mrb_value y) { mrb_int a; @@ -1269,6 +1283,20 @@ mrb_fixnum_plus(mrb_state *mrb, mrb_value x, mrb_value y) #endif } +MRB_API mrb_value +mrb_num_plus(mrb_state *mrb, mrb_value x, mrb_value y) +{ + if (mrb_fixnum_p(x)) { + return fixnum_plus(mrb, x, y); + } +#ifndef MRB_WITHOUT_FLOAT + if (mrb_float_p(x)) { + return mrb_float_value(mrb, mrb_float(x) + mrb_to_flo(mrb, y)); + } +#endif + mrb_raise(mrb, E_TYPE_ERROR, "no number addition"); +} + /* 15.2.8.3.1 */ /* * call-seq: @@ -1284,11 +1312,11 @@ fix_plus(mrb_state *mrb, mrb_value self) mrb_value other; mrb_get_args(mrb, "o", &other); - return mrb_fixnum_plus(mrb, self, other); + return fixnum_plus(mrb, self, other); } static mrb_value -mrb_fixnum_minus(mrb_state *mrb, mrb_value x, mrb_value y) +fixnum_minus(mrb_state *mrb, mrb_value x, mrb_value y) { mrb_int a; @@ -1311,6 +1339,20 @@ mrb_fixnum_minus(mrb_state *mrb, mrb_value x, mrb_value y) #endif } +MRB_API mrb_value +mrb_num_minus(mrb_state *mrb, mrb_value x, mrb_value y) +{ + if (mrb_fixnum_p(x)) { + return fixnum_minus(mrb, x, y); + } +#ifdef MRB_WITHOUT_FLOAT + if (mrb_float_p(x)) { + return mrb_float_value(mrb, mrb_float(x) - mrb_to_flo(mrb, y)); + } +#endif + mrb_raise(mrb, E_TYPE_ERROR, "no number subtraction"); +} + /* 15.2.8.3.2 */ /* 15.2.8.3.16 */ /* @@ -1327,7 +1369,7 @@ fix_minus(mrb_state *mrb, mrb_value self) mrb_value other; mrb_get_args(mrb, "o", &other); - return mrb_fixnum_minus(mrb, self, other); + return fixnum_minus(mrb, self, other); } -- cgit v1.2.3 From 3b46831da83b4d5d5355c60261fb3ebe2a885513 Mon Sep 17 00:00:00 2001 From: KOBAYASHI Shuji Date: Tue, 21 May 2019 20:26:53 +0900 Subject: Move `**`,`/`,`quo`,`div` and comparison methods to Integral from Numeric Having these methods in Numeric can get in the way of creating subclasses of Numeric because they only support Fixnum and Float. --- mrbgems/mruby-rational/mrblib/rational.rb | 3 --- src/numeric.c | 37 +++++++++++++++---------------- 2 files changed, 18 insertions(+), 22 deletions(-) (limited to 'src/numeric.c') diff --git a/mrbgems/mruby-rational/mrblib/rational.rb b/mrbgems/mruby-rational/mrblib/rational.rb index 28c96c69f..cecede48a 100644 --- a/mrbgems/mruby-rational/mrblib/rational.rb +++ b/mrbgems/mruby-rational/mrblib/rational.rb @@ -1,7 +1,4 @@ class Rational < Numeric - # Override #<, #<=, #>, #>= in Numeric - prepend Comparable - def inspect "(#{to_s})" end diff --git a/src/numeric.c b/src/numeric.c index 3ad5721ef..c740a32e3 100644 --- a/src/numeric.c +++ b/src/numeric.c @@ -65,7 +65,7 @@ mrb_int_value(mrb_state *mrb, mrb_float f) * 2.0**3 #=> 8.0 */ static mrb_value -num_pow(mrb_state *mrb, mrb_value x) +integral_pow(mrb_state *mrb, mrb_value x) { mrb_value y; #ifndef MRB_WITHOUT_FLOAT @@ -113,7 +113,7 @@ num_pow(mrb_state *mrb, mrb_value x) } static mrb_value -num_idiv(mrb_state *mrb, mrb_value x) +integral_idiv(mrb_state *mrb, mrb_value x) { #ifdef MRB_WITHOUT_FLOAT mrb_value y; @@ -151,7 +151,7 @@ num_idiv(mrb_state *mrb, mrb_value x) */ static mrb_value -num_div(mrb_state *mrb, mrb_value x) +integral_div(mrb_state *mrb, mrb_value x) { #ifdef MRB_WITHOUT_FLOAT mrb_value y; @@ -1479,7 +1479,7 @@ cmpnum(mrb_state *mrb, mrb_value v1, mrb_value v2) * basis for the tests in Comparable. */ static mrb_value -num_cmp(mrb_state *mrb, mrb_value self) +integral_cmp(mrb_state *mrb, mrb_value self) { mrb_value other; mrb_int n; @@ -1499,7 +1499,7 @@ cmperr(mrb_state *mrb, mrb_value v1, mrb_value v2) } static mrb_value -num_lt(mrb_state *mrb, mrb_value self) +integral_lt(mrb_state *mrb, mrb_value self) { mrb_value other; mrb_int n; @@ -1512,7 +1512,7 @@ num_lt(mrb_state *mrb, mrb_value self) } static mrb_value -num_le(mrb_state *mrb, mrb_value self) +integral_le(mrb_state *mrb, mrb_value self) { mrb_value other; mrb_int n; @@ -1525,7 +1525,7 @@ num_le(mrb_state *mrb, mrb_value self) } static mrb_value -num_gt(mrb_state *mrb, mrb_value self) +integral_gt(mrb_state *mrb, mrb_value self) { mrb_value other; mrb_int n; @@ -1538,7 +1538,7 @@ num_gt(mrb_state *mrb, mrb_value self) } static mrb_value -num_ge(mrb_state *mrb, mrb_value self) +integral_ge(mrb_state *mrb, mrb_value self) { mrb_value other; mrb_int n; @@ -1593,20 +1593,19 @@ mrb_init_numeric(mrb_state *mrb) #endif integral = mrb_define_module(mrb, "Integral"); - mrb_define_method(mrb, integral, "__coerce_step_counter", integral_coerce_step_counter, MRB_ARGS_REQ(2)); + mrb_define_method(mrb, integral,"**", integral_pow, MRB_ARGS_REQ(1)); + mrb_define_method(mrb, integral,"/", integral_div, MRB_ARGS_REQ(1)); /* 15.2.8.3.4 */ + mrb_define_method(mrb, integral,"quo", integral_div, MRB_ARGS_REQ(1)); /* 15.2.7.4.5 (x) */ + mrb_define_method(mrb, integral,"div", integral_idiv, MRB_ARGS_REQ(1)); + mrb_define_method(mrb, integral,"<=>", integral_cmp, MRB_ARGS_REQ(1)); /* 15.2.9.3.6 */ + mrb_define_method(mrb, integral,"<", integral_lt, MRB_ARGS_REQ(1)); + mrb_define_method(mrb, integral,"<=", integral_le, MRB_ARGS_REQ(1)); + mrb_define_method(mrb, integral,">", integral_gt, MRB_ARGS_REQ(1)); + mrb_define_method(mrb, integral,">=", integral_ge, MRB_ARGS_REQ(1)); + mrb_define_method(mrb, integral,"__coerce_step_counter", integral_coerce_step_counter, MRB_ARGS_REQ(2)); /* Numeric Class */ numeric = mrb_define_class(mrb, "Numeric", mrb->object_class); /* 15.2.7 */ - - mrb_define_method(mrb, numeric, "**", num_pow, MRB_ARGS_REQ(1)); - mrb_define_method(mrb, numeric, "/", num_div, MRB_ARGS_REQ(1)); /* 15.2.8.3.4 */ - mrb_define_method(mrb, numeric, "quo", num_div, MRB_ARGS_REQ(1)); /* 15.2.7.4.5 (x) */ - mrb_define_method(mrb, numeric, "div", num_idiv, MRB_ARGS_REQ(1)); - mrb_define_method(mrb, numeric, "<=>", num_cmp, MRB_ARGS_REQ(1)); /* 15.2.9.3.6 */ - mrb_define_method(mrb, numeric, "<", num_lt, MRB_ARGS_REQ(1)); - mrb_define_method(mrb, numeric, "<=", num_le, MRB_ARGS_REQ(1)); - mrb_define_method(mrb, numeric, ">", num_gt, MRB_ARGS_REQ(1)); - mrb_define_method(mrb, numeric, ">=", num_ge, MRB_ARGS_REQ(1)); mrb_define_method(mrb, numeric, "finite?", num_finite_p, MRB_ARGS_NONE()); mrb_define_method(mrb, numeric, "infinite?",num_infinite_p, MRB_ARGS_NONE()); -- cgit v1.2.3 From 5d30309e9826fe1a392fa7a7a33e11ad58857b3f Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Mon, 20 May 2019 16:32:00 +0900 Subject: Silence the return value warnings from gcc; ref 237a57b --- src/numeric.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'src/numeric.c') diff --git a/src/numeric.c b/src/numeric.c index c740a32e3..140cd0101 100644 --- a/src/numeric.c +++ b/src/numeric.c @@ -824,6 +824,7 @@ mrb_num_mul(mrb_state *mrb, mrb_value x, mrb_value y) } #endif mrb_raise(mrb, E_TYPE_ERROR, "no number multiply"); + return mrb_nil_value(); /* not reached */ } /* 15.2.8.3.3 */ @@ -1295,6 +1296,7 @@ mrb_num_plus(mrb_state *mrb, mrb_value x, mrb_value y) } #endif mrb_raise(mrb, E_TYPE_ERROR, "no number addition"); + return mrb_nil_value(); /* not reached */ } /* 15.2.8.3.1 */ @@ -1351,6 +1353,7 @@ mrb_num_minus(mrb_state *mrb, mrb_value x, mrb_value y) } #endif mrb_raise(mrb, E_TYPE_ERROR, "no number subtraction"); + return mrb_nil_value(); /* not reached */ } /* 15.2.8.3.2 */ -- cgit v1.2.3 From e941cf06a3e0351107d36d49d540562fdf49f9b4 Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Tue, 21 May 2019 16:08:02 +0900 Subject: Export `mrb_int_value` that converts `mrb_float` to `Fixnum`. Or `Float` if `mrb_float` value is too big (or too small) to fit in `mrb_int`. The `_int_` in `mrb_int_value` means `Integral` module, which represents integer-like values in mruby. --- include/mruby/numeric.h | 1 + src/numeric.c | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) (limited to 'src/numeric.c') diff --git a/include/mruby/numeric.h b/include/mruby/numeric.h index d670504c2..34707e441 100644 --- a/include/mruby/numeric.h +++ b/include/mruby/numeric.h @@ -34,6 +34,7 @@ MRB_API mrb_value mrb_fixnum_to_str(mrb_state *mrb, mrb_value x, mrb_int base); #ifndef MRB_WITHOUT_FLOAT MRB_API mrb_value mrb_float_to_str(mrb_state *mrb, mrb_value x, const char *fmt); MRB_API mrb_float mrb_to_flo(mrb_state *mrb, mrb_value x); +MRB_API mrb_value mrb_int_value(mrb_state *mrb, mrb_float f); #endif MRB_API mrb_value mrb_num_plus(mrb_state *mrb, mrb_value x, mrb_value y); diff --git a/src/numeric.c b/src/numeric.c index 140cd0101..e15b7f671 100644 --- a/src/numeric.c +++ b/src/numeric.c @@ -45,7 +45,7 @@ mrb_to_flo(mrb_state *mrb, mrb_value val) return mrb_float(val); } -static mrb_value +MRB_API mrb_value mrb_int_value(mrb_state *mrb, mrb_float f) { if (FIXABLE_FLOAT(f)) { -- cgit v1.2.3 From 38f8edbdd7463ee5e3331d09b2d031d55f2fd05e Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Tue, 21 May 2019 21:12:33 +0900 Subject: Update ISO section number for some Numeric methods. --- src/numeric.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/numeric.c') diff --git a/src/numeric.c b/src/numeric.c index e15b7f671..608b4f289 100644 --- a/src/numeric.c +++ b/src/numeric.c @@ -1597,10 +1597,10 @@ mrb_init_numeric(mrb_state *mrb) integral = mrb_define_module(mrb, "Integral"); mrb_define_method(mrb, integral,"**", integral_pow, MRB_ARGS_REQ(1)); - mrb_define_method(mrb, integral,"/", integral_div, MRB_ARGS_REQ(1)); /* 15.2.8.3.4 */ + mrb_define_method(mrb, integral,"/", integral_div, MRB_ARGS_REQ(1)); /* 15.2.{8,9}.3.6 */ mrb_define_method(mrb, integral,"quo", integral_div, MRB_ARGS_REQ(1)); /* 15.2.7.4.5 (x) */ mrb_define_method(mrb, integral,"div", integral_idiv, MRB_ARGS_REQ(1)); - mrb_define_method(mrb, integral,"<=>", integral_cmp, MRB_ARGS_REQ(1)); /* 15.2.9.3.6 */ + mrb_define_method(mrb, integral,"<=>", integral_cmp, MRB_ARGS_REQ(1)); /* 15.2.{8,9}.3.1 */ mrb_define_method(mrb, integral,"<", integral_lt, MRB_ARGS_REQ(1)); mrb_define_method(mrb, integral,"<=", integral_le, MRB_ARGS_REQ(1)); mrb_define_method(mrb, integral,">", integral_gt, MRB_ARGS_REQ(1)); -- cgit v1.2.3 From 729931a06c0eebb8c1eaa471f2a1d16192deca9f Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Thu, 30 May 2019 12:33:41 +0900 Subject: Fix inverted compilation condition; fix #4478 --- src/numeric.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/numeric.c') diff --git a/src/numeric.c b/src/numeric.c index 608b4f289..0d1c23589 100644 --- a/src/numeric.c +++ b/src/numeric.c @@ -1347,7 +1347,7 @@ mrb_num_minus(mrb_state *mrb, mrb_value x, mrb_value y) if (mrb_fixnum_p(x)) { return fixnum_minus(mrb, x, y); } -#ifdef MRB_WITHOUT_FLOAT +#ifndef MRB_WITHOUT_FLOAT if (mrb_float_p(x)) { return mrb_float_value(mrb, mrb_float(x) - mrb_to_flo(mrb, y)); } -- cgit v1.2.3 From 6b1cc6e2fe4eab30e265d8209a208e0bf942c54d Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Mon, 8 Jul 2019 18:40:13 +0900 Subject: Avoid `mrb_funcall()` if possible using `mrb_Float()`; ref #4555 --- src/numeric.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'src/numeric.c') diff --git a/src/numeric.c b/src/numeric.c index 0d1c23589..4288df44a 100644 --- a/src/numeric.c +++ b/src/numeric.c @@ -172,17 +172,17 @@ integral_div(mrb_state *mrb, mrb_value x) static mrb_value integral_coerce_step_counter(mrb_state *mrb, mrb_value self) { - mrb_value counter = self, num, step; + mrb_value num, step; mrb_get_args(mrb, "oo", &num, &step); #ifndef MRB_WITHOUT_FLOAT if (mrb_float_p(self) || mrb_float_p(num) || mrb_float_p(step)) { - counter = mrb_funcall(mrb, counter, "to_f", 0); + return mrb_Float(mrb, self); } #endif - return counter; + return self; } #ifndef MRB_WITHOUT_FLOAT -- cgit v1.2.3