diff options
| -rw-r--r-- | mrbgems/mruby-complex/src/complex.c | 52 | ||||
| -rw-r--r-- | mrbgems/mruby-complex/test/complex.rb | 12 | ||||
| -rw-r--r-- | mrbgems/mruby-rational/mrbgem.rake | 1 | ||||
| -rw-r--r-- | mrbgems/mruby-rational/src/rational.c | 60 | ||||
| -rw-r--r-- | mrbgems/mruby-rational/test/rational.rb | 3 | ||||
| -rw-r--r-- | src/numeric.c | 16 | ||||
| -rw-r--r-- | src/vm.c | 8 |
7 files changed, 84 insertions, 68 deletions
diff --git a/mrbgems/mruby-complex/src/complex.c b/mrbgems/mruby-complex/src/complex.c index 086ada7ad..0bf5377ed 100644 --- a/mrbgems/mruby-complex/src/complex.c +++ b/mrbgems/mruby-complex/src/complex.c @@ -236,8 +236,7 @@ complex_mul(mrb_state *mrb, mrb_value x) } #ifndef MRB_NO_FLOAT -mrb_float mrb_num_div_flo(mrb_state*, mrb_float, mrb_float); -#define div_flo(x,y) mrb_num_div_flo(NULL, x, y) +mrb_float mrb_div_flo(mrb_float, mrb_float); #endif /* Arithmetic on (significand, exponent) pairs avoids premature overflow in @@ -276,7 +275,7 @@ static void div_pair(struct float_pair *q, struct float_pair const *a, struct float_pair const *b) { - q->s = div_flo(a->s, b->s); + q->s = mrb_div_flo(a->s, b->s); q->x = a->x - b->x; } @@ -289,7 +288,7 @@ complex_div(mrb_state *mrb, mrb_value self) a = complex_ptr(mrb, self); if (mrb_type(rhs) != MRB_TT_COMPLEX) { mrb_float f = mrb_to_flo(mrb, rhs); - return complex_new(mrb, div_flo(a->real, f), div_flo(a->imaginary, f)); + return complex_new(mrb, mrb_div_flo(a->real, f), mrb_div_flo(a->imaginary, f)); } struct float_pair ar, ai, br, bi; @@ -332,29 +331,34 @@ complex_div(mrb_state *mrb, mrb_value self) return complex_new(mrb, F(ldexp)(zr.s, zr.x), F(ldexp)(zi.s, zi.x)); } -#ifndef MRB_USE_RATIONAL -mrb_int mrb_num_div_int(mrb_state *mrb, mrb_int x, mrb_int y); +mrb_int mrb_div_int(mrb_state *mrb, mrb_int x, mrb_int y); +mrb_value mrb_rational_new(mrb_state *mrb, mrb_int n, mrb_int d); +mrb_value mrb_rational_div(mrb_state *mrb, mrb_value x); /* 15.2.8.3.4 */ /* * redefine Integer#/ */ static mrb_value -int_div(mrb_state *mrb, mrb_value x) +cpx_int_div(mrb_state *mrb, mrb_value x) { mrb_value y = mrb_get_arg1(mrb); mrb_int a = mrb_integer(x); if (mrb_integer_p(y)) { - mrb_int div = mrb_num_div_int(mrb, a, mrb_integer(y)); + mrb_int div = mrb_div_int(mrb, a, mrb_integer(y)); return mrb_int_value(mrb, div); } switch (mrb_type(y)) { +#ifdef MRB_USE_RATIONAL + case MRB_TT_RATIONAL: + return mrb_rational_div(mrb, mrb_rational_new(mrb, a, 1)); +#endif case MRB_TT_COMPLEX: x = complex_new(mrb, (mrb_float)a, 0); - return mrb_funcall_id(mrb, x, MRB_OPSYM(div), 1, y); + return complex_div(mrb, x); default: - return mrb_float_value(mrb, div_flo((mrb_float)a, mrb_to_flo(mrb, y))); + return mrb_float_value(mrb, mrb_div_flo((mrb_float)a, mrb_to_flo(mrb, y))); } } @@ -364,23 +368,27 @@ int_div(mrb_state *mrb, mrb_value x) */ static mrb_value -int_quo(mrb_state *mrb, mrb_value x) +cpx_int_quo(mrb_state *mrb, mrb_value x) { mrb_value y = mrb_get_arg1(mrb); mrb_int a = mrb_integer(x); switch (mrb_type(y)) { +#ifdef MRB_USE_RATIONAL + case MRB_TT_RATIONAL: + x = mrb_rational_new(mrb, a, 1); + return mrb_funcall_id(mrb, x, MRB_OPSYM(div), 1, y); +#endif case MRB_TT_COMPLEX: x = complex_new(mrb, (mrb_float)a, 0); - return mrb_funcall_id(mrb, x, MRB_OPSYM(div), 1, y); + return complex_div(mrb, x); default: - return mrb_float_value(mrb, div_flo((mrb_float)a, mrb_to_flo(mrb, y))); + return mrb_float_value(mrb, mrb_div_flo((mrb_float)a, mrb_to_flo(mrb, y))); } } -#endif static mrb_value -flo_div(mrb_state *mrb, mrb_value x) +cpx_flo_div(mrb_state *mrb, mrb_value x) { mrb_float a = mrb_float(x); mrb_value y = mrb_get_arg1(mrb); @@ -389,10 +397,10 @@ flo_div(mrb_state *mrb, mrb_value x) case MRB_TT_COMPLEX: return complex_div(mrb, complex_new(mrb, a, 0)); case MRB_TT_FLOAT: - a = div_flo(a, mrb_float(y)); + a = mrb_div_flo(a, mrb_float(y)); return mrb_float_value(mrb, a); default: - a = div_flo(a, mrb_to_flo(mrb, y)); + a = mrb_div_flo(a, mrb_to_flo(mrb, y)); return mrb_float_value(mrb, a); } } @@ -423,12 +431,10 @@ void mrb_mruby_complex_gem_init(mrb_state *mrb) mrb_define_method(mrb, comp, "/", complex_div, MRB_ARGS_REQ(1)); mrb_define_method(mrb, comp, "quo", complex_div, MRB_ARGS_REQ(1)); mrb_define_method(mrb, comp, "==", complex_eq, MRB_ARGS_REQ(1)); -#ifndef MRB_USE_RATIONAL - mrb_define_method(mrb, mrb->integer_class, "/", int_div, MRB_ARGS_REQ(1)); /* overrride */ - mrb_define_method(mrb, mrb->integer_class, "quo", int_quo, MRB_ARGS_REQ(1)); /* overrride */ -#endif - mrb_define_method(mrb, mrb->float_class, "/", flo_div, MRB_ARGS_REQ(1)); /* overrride */ - mrb_define_method(mrb, mrb->float_class, "quo", flo_div, MRB_ARGS_REQ(1)); /* overrride */ + mrb_define_method(mrb, mrb->integer_class, "/", cpx_int_div, MRB_ARGS_REQ(1)); /* overrride */ + mrb_define_method(mrb, mrb->integer_class, "quo", cpx_int_quo, MRB_ARGS_REQ(1)); /* overrride */ + mrb_define_method(mrb, mrb->float_class, "/", cpx_flo_div, MRB_ARGS_REQ(1)); /* overrride */ + mrb_define_method(mrb, mrb->float_class, "quo", cpx_flo_div, MRB_ARGS_REQ(1)); /* overrride */ } void diff --git a/mrbgems/mruby-complex/test/complex.rb b/mrbgems/mruby-complex/test/complex.rb index 8f9634048..85ee6e998 100644 --- a/mrbgems/mruby-complex/test/complex.rb +++ b/mrbgems/mruby-complex/test/complex.rb @@ -31,6 +31,8 @@ assert 'Complex#*' do assert_complex Complex(-2, 9) * Complex(-9, 2), (0 - 85i) assert_complex Complex(9, 8) * 4, (36 + 32i) assert_complex Complex(20, 9) * 9.8, (196.0 + 88.2i) + assert_complex 4 * Complex(9, 8), (36 + 32i) + assert_complex 9.8 * Complex(20, 9), (196.0 + 88.2i) end assert 'Complex#+' do @@ -39,6 +41,8 @@ assert 'Complex#+' do assert_complex Complex(-2, 9) + Complex(-9, 2), (-11 + 11i) assert_complex Complex(9, 8) + 4 , (13 + 8i) assert_complex Complex(20, 9) + 9.8 , (29.8 + 9i) + assert_complex 4 + Complex(9, 8) , (13 + 8i) + assert_complex 9.8 + Complex(20, 9) , (29.8 + 9i) end assert 'Complex#-' do @@ -47,10 +51,12 @@ assert 'Complex#-' do assert_complex Complex(-2, 9) - Complex(-9, 2), (7 + 7i) assert_complex Complex(9, 8) - 4 , (5 + 8i) assert_complex Complex(20, 9) - 9.8 , (10.2 + 9i) + assert_complex 4 - Complex(9, 8) , (-5 - 8i) + assert_complex 10.5 - Complex(20, 9) , (-9.5 - 9i) end assert 'Complex#-@' do - assert_complex(-Complex(1, 2), (-1 - 2i)) + assert_complex((-1 - 2i), -Complex(1, 2)) end assert 'Complex#/' do @@ -59,6 +65,8 @@ assert 'Complex#/' do assert_complex Complex(-2, 9) / Complex(-9, 2), ((36.0 / 85) - (77i / 85)) assert_complex Complex(9, 8) / 4 , ((9.0 / 4) + 2i) assert_complex Complex(20, 9) / 9.8 , (2.0408163265306123 + 0.9183673469387754i) + assert_complex 4 / Complex(9, 8) , (0.2482758620689655 - 0.2206896551724138i) + assert_complex 9.8 / Complex(20, 9) , (0.4074844074844075 - 0.1833679833679834i) if 1e39.infinite? then # MRB_USE_FLOAT32 in effect ten = 1e21 @@ -74,6 +82,8 @@ assert 'Complex#==' do assert_true Complex(2, 3) == Complex(2, 3) assert_true Complex(5) == 5 assert_true Complex(0) == 0.0 + assert_true 5 == Complex(5) + assert_true 0.0 == Complex(0) end assert 'Complex#abs' do diff --git a/mrbgems/mruby-rational/mrbgem.rake b/mrbgems/mruby-rational/mrbgem.rake index ab5dc5fd1..534114862 100644 --- a/mrbgems/mruby-rational/mrbgem.rake +++ b/mrbgems/mruby-rational/mrbgem.rake @@ -3,4 +3,5 @@ MRuby::Gem::Specification.new('mruby-rational') do |spec| spec.author = 'mruby developers' spec.summary = 'Rational class' spec.build.defines << "MRB_USE_RATIONAL" + spec.add_test_dependency('mruby-complex') end diff --git a/mrbgems/mruby-rational/src/rational.c b/mrbgems/mruby-rational/src/rational.c index f6ba296ae..1d53afb5c 100644 --- a/mrbgems/mruby-rational/src/rational.c +++ b/mrbgems/mruby-rational/src/rational.c @@ -75,8 +75,8 @@ rat_zerodiv(mrb_state *mrb) mrb_raise(mrb, E_ZERODIV_ERROR, "divided by 0 in rational"); } -static mrb_value -rational_new(mrb_state *mrb, mrb_int numerator, mrb_int denominator) +mrb_value +mrb_rational_new(mrb_state *mrb, mrb_int numerator, mrb_int denominator) { struct RClass *c = mrb_class_get_id(mrb, MRB_SYM(Rational)); struct mrb_rational *p; @@ -99,6 +99,8 @@ rational_new(mrb_state *mrb, mrb_int numerator, mrb_int denominator) return mrb_obj_value(rat); } +#define rational_new(mrb,n,d) mrb_rational_new(mrb, n, d) + inline static mrb_int i_gcd(mrb_int x, mrb_int y) { @@ -482,7 +484,7 @@ rational_minus(mrb_state *mrb, mrb_value x) } #ifndef MRB_NO_FLOAT -mrb_float mrb_num_div_flo(mrb_state*, mrb_float, mrb_float); +mrb_float mrb_div_flo(mrb_float, mrb_float); #endif static mrb_value @@ -515,7 +517,7 @@ rational_add(mrb_state *mrb, mrb_value x) case MRB_TT_FLOAT: { mrb_float z = p1->numerator + mrb_float(y) * p1->denominator; - return mrb_float_value(mrb, mrb_num_div_flo(mrb, z, (mrb_float)p1->denominator)); + return mrb_float_value(mrb, mrb_div_flo(z, (mrb_float)p1->denominator)); } #endif @@ -561,7 +563,7 @@ rational_sub(mrb_state *mrb, mrb_value x) default: { mrb_float z = p1->numerator - mrb_to_flo(mrb, y) * p1->denominator; - return mrb_float_value(mrb, mrb_num_div_flo(mrb, z, (mrb_float)p1->denominator)); + return mrb_float_value(mrb, mrb_div_flo(z, (mrb_float)p1->denominator)); } #else default: @@ -597,7 +599,7 @@ rational_mul(mrb_state *mrb, mrb_value x) case MRB_TT_FLOAT: { mrb_float z = p1->numerator * mrb_float(y); - return mrb_float_value(mrb, mrb_num_div_flo(mrb, z, (mrb_float)p1->denominator)); + return mrb_float_value(mrb, mrb_div_flo(z, (mrb_float)p1->denominator)); } #endif @@ -606,10 +608,8 @@ rational_mul(mrb_state *mrb, mrb_value x) } } -mrb_int mrb_num_div_int(mrb_state *, mrb_int, mrb_int); - -static mrb_value -rational_div(mrb_state *mrb, mrb_value x) +mrb_value +mrb_rational_div(mrb_state *mrb, mrb_value x) { struct mrb_rational *p1 = rational_ptr(mrb, x); mrb_value y = mrb_get_arg1(mrb); @@ -641,8 +641,8 @@ rational_div(mrb_state *mrb, mrb_value x) #ifndef MRB_NO_FLOAT case MRB_TT_FLOAT: { - mrb_float z = mrb_num_div_flo(mrb, p1->numerator, mrb_to_flo(mrb, y)); - return mrb_float_value(mrb, mrb_num_div_flo(mrb, z, (mrb_float)p1->denominator)); + mrb_float z = mrb_div_flo(p1->numerator, mrb_to_flo(mrb, y)); + return mrb_float_value(mrb, mrb_div_flo(z, (mrb_float)p1->denominator)); } #else mrb_raise(mrb, E_TYPE_ERROR, "non integer division"); @@ -650,35 +650,33 @@ rational_div(mrb_state *mrb, mrb_value x) } } +#define rational_div mrb_rational_div +mrb_int mrb_div_int(mrb_state *, mrb_int, mrb_int); + +#ifndef MRB_USE_COMPLEX /* 15.2.8.3.4 */ /* * redefine Integer#/ */ static mrb_value -int_div(mrb_state *mrb, mrb_value x) +rat_int_div(mrb_state *mrb, mrb_value x) { mrb_value y = mrb_get_arg1(mrb); mrb_int a = mrb_integer(x); if (mrb_integer_p(y)) { - mrb_int div = mrb_num_div_int(mrb, a, mrb_integer(y)); + mrb_int div = mrb_div_int(mrb, a, mrb_integer(y)); return mrb_int_value(mrb, div); } switch (mrb_type(y)) { case MRB_TT_RATIONAL: - x = rational_new(mrb, a, 1); - return mrb_funcall_id(mrb, x, MRB_OPSYM(div), 1, y); -#if defined(MRB_USE_COMPLEX) - case MRB_TT_COMPLEX: - x = mrb_complex_new(mrb, (mrb_float)a, 0); - return mrb_funcall_id(mrb, x, MRB_OPSYM(div), 1, y); -#endif - case MRB_TT_FLOAT: + return rational_div(mrb, rational_new(mrb, a, 1)); default: #ifdef MRB_NO_FLOAT + case MRB_TT_FLOAT: mrb_raise(mrb, E_TYPE_ERROR, "non integer multiplication"); #else - return mrb_float_value(mrb, mrb_num_div_flo(mrb, (mrb_float)a, mrb_to_flo(mrb, y))); + return mrb_float_value(mrb, mrb_div_flo((mrb_float)a, mrb_to_flo(mrb, y))); #endif } } @@ -689,7 +687,7 @@ int_div(mrb_state *mrb, mrb_value x) */ static mrb_value -int_quo(mrb_state *mrb, mrb_value x) +rat_int_quo(mrb_state *mrb, mrb_value x) { mrb_value y = mrb_get_arg1(mrb); mrb_int a = mrb_integer(x); @@ -701,19 +699,15 @@ int_quo(mrb_state *mrb, mrb_value x) case MRB_TT_RATIONAL: x = rational_new(mrb, a, 1); return mrb_funcall_id(mrb, x, MRB_OPSYM(div), 1, y); -#if defined(MRB_USE_COMPLEX) - case MRB_TT_COMPLEX: - x = mrb_complex_new(mrb, (mrb_float)a, 0); - return mrb_funcall_id(mrb, x, MRB_OPSYM(div), 1, y); -#endif default: #ifdef MRB_NO_FLOAT mrb_raise(mrb, E_TYPE_ERROR, "non integer multiplication"); #else - return mrb_float_value(mrb, mrb_num_div_flo(mrb, (mrb_float)a, mrb_to_flo(mrb, y))); + return mrb_float_value(mrb, mrb_div_flo((mrb_float)a, mrb_to_flo(mrb, y))); #endif } } +#endif /* !MRB_USE_COMPLEX */ void mrb_mruby_rational_gem_init(mrb_state *mrb) { @@ -740,8 +734,10 @@ void mrb_mruby_rational_gem_init(mrb_state *mrb) mrb_define_method(mrb, rat, "/", rational_div, MRB_ARGS_REQ(1)); mrb_define_method(mrb, rat, "quo", rational_div, MRB_ARGS_REQ(1)); mrb_define_method(mrb, mrb->integer_class, "to_r", fix_to_r, MRB_ARGS_NONE()); - mrb_define_method(mrb, mrb->integer_class, "/", int_div, MRB_ARGS_REQ(1)); /* overrride */ - mrb_define_method(mrb, mrb->integer_class, "quo", int_quo, MRB_ARGS_REQ(1)); /* overrride */ +#ifndef MRB_USE_COMPLEX + mrb_define_method(mrb, mrb->integer_class, "/", rat_int_div, MRB_ARGS_REQ(1)); /* overrride */ + mrb_define_method(mrb, mrb->integer_class, "quo", rat_int_quo, MRB_ARGS_REQ(1)); /* overrride */ +#endif mrb_define_method(mrb, mrb->kernel_module, "Rational", rational_m, MRB_ARGS_ARG(1,1)); } diff --git a/mrbgems/mruby-rational/test/rational.rb b/mrbgems/mruby-rational/test/rational.rb index 4a619a646..b807ef83f 100644 --- a/mrbgems/mruby-rational/test/rational.rb +++ b/mrbgems/mruby-rational/test/rational.rb @@ -24,6 +24,7 @@ end def assert_rational(exp, real) assert "assert_rational" do + assert_kind_of Rational, real assert_float exp.numerator, real.numerator assert_float exp.denominator, real.denominator end @@ -135,7 +136,7 @@ assert 'Rational#/' do assert_rational(Rational(32, 9), 4 / Rational(9, 8)) assert_float( 0.22675736961451246, Rational(20, 9) / 9.8) assert_float( 4.41, 9.8 / Rational(20, 9)) - assert_complex(1.92, 1.44) {Rational(24,2)/(4.0+3i)} + assert_complex(1.92, 1.44) {Rational(24,2)/(4.0-3i)} assert_complex(0.25, 0.25) {(3.0+3i)/Rational(24,2)} end diff --git a/src/numeric.c b/src/numeric.c index c5c862a37..edb5d28b2 100644 --- a/src/numeric.c +++ b/src/numeric.c @@ -119,7 +119,7 @@ int_pow(mrb_state *mrb, mrb_value x) } mrb_int -mrb_num_div_int(mrb_state *mrb, mrb_int x, mrb_int y) +mrb_div_int(mrb_state *mrb, mrb_int x, mrb_int y) { if (y == 0) { int_zerodiv(mrb); @@ -139,6 +139,8 @@ mrb_num_div_int(mrb_state *mrb, mrb_int x, mrb_int y) return 0; } +mrb_float mrb_div_flo(mrb_float x, mrb_float y); + /* 15.2.8.3.4 */ /* 15.2.9.3.4 */ /* @@ -156,13 +158,13 @@ int_div(mrb_state *mrb, mrb_value x) mrb_int a = mrb_integer(x); if (mrb_integer_p(y)) { - mrb_int div = mrb_num_div_int(mrb, a, mrb_integer(y)); + mrb_int div = mrb_div_int(mrb, a, mrb_integer(y)); return mrb_int_value(mrb, div); } #ifdef MRB_NO_FLOAT mrb_raise(mrb, E_TYPE_ERROR, "non integer division"); #else - return mrb_float_value(mrb, (mrb_float)a / mrb_to_flo(mrb, y)); + return mrb_float_value(mrb, mrb_div_flo((mrb_float)a, mrb_to_flo(mrb, y))); #endif } @@ -248,12 +250,12 @@ flo_idiv(mrb_state *mrb, mrb_value xv) mrb_int y, div; mrb_get_args(mrb, "i", &y); - div = mrb_num_div_int(mrb, (mrb_int)mrb_float(xv), y); + div = mrb_div_int(mrb, (mrb_int)mrb_float(xv), y); return mrb_int_value(mrb, (mrb_int)div); } mrb_float -mrb_num_div_flo(mrb_state *mrb, mrb_float x, mrb_float y) +mrb_div_flo(mrb_float x, mrb_float y) { if (y != 0.0) { return x / y; @@ -273,10 +275,10 @@ flo_div(mrb_state *mrb, mrb_value x) mrb_float a = mrb_float(x); if (mrb_float_p(y)) { - a = mrb_num_div_flo(mrb, a, mrb_float(y)); + a = mrb_div_flo(a, mrb_float(y)); } else { - a = mrb_num_div_flo(mrb, a, mrb_to_flo(mrb, y)); + a = mrb_div_flo(a, mrb_to_flo(mrb, y)); } return mrb_float_value(mrb, a); } @@ -1085,6 +1085,8 @@ check_target_class(mrb_state *mrb) } void mrb_hash_check_kdict(mrb_state *mrb, mrb_value self); +mrb_int mrb_div_int(mrb_state *mrb, mrb_int x, mrb_int y); +mrb_float mrb_div_flo(mrb_float x, mrb_float y); MRB_API mrb_value mrb_vm_exec(mrb_state *mrb, const struct RProc *proc, const mrb_code *pc) @@ -2381,9 +2383,7 @@ RETRY_TRY_BLOCK: } CASE(OP_DIV, B) { - mrb_int mrb_num_div_int(mrb_state *mrb, mrb_int x, mrb_int y); #ifndef MRB_NO_FLOAT - mrb_float mrb_num_div_flo(mrb_state *mrb, mrb_float x, mrb_float y); mrb_float x, y, f; #endif @@ -2393,7 +2393,7 @@ RETRY_TRY_BLOCK: { mrb_int x = mrb_integer(regs[a]); mrb_int y = mrb_integer(regs[a+1]); - mrb_int div = mrb_num_div_int(mrb, x, y); + mrb_int div = mrb_div_int(mrb, x, y); SET_INT_VALUE(mrb, regs[a], div); } NEXT; @@ -2418,7 +2418,7 @@ RETRY_TRY_BLOCK: } #ifndef MRB_NO_FLOAT - f = mrb_num_div_flo(mrb, x, y); + f = mrb_div_flo(x, y); SET_FLOAT_VALUE(mrb, regs[a], f); #endif NEXT; |
