diff options
| author | Yukihiro "Matz" Matsumoto <[email protected]> | 2021-03-24 19:01:58 +0900 |
|---|---|---|
| committer | Yukihiro "Matz" Matsumoto <[email protected]> | 2021-03-24 19:01:58 +0900 |
| commit | 9d058342a5ab370698616069f760789a47cbbfd0 (patch) | |
| tree | 6e270f6fed159330cce5dcd1255f833f90f5e6d6 /mrbgems | |
| parent | 7a35b64251b8a8b97db9e35df5eb6a2b4aa607e8 (diff) | |
| download | mruby-9d058342a5ab370698616069f760789a47cbbfd0.tar.gz mruby-9d058342a5ab370698616069f760789a47cbbfd0.zip | |
rational.c: implement `Rational#-` in C.
Diffstat (limited to 'mrbgems')
| -rw-r--r-- | mrbgems/mruby-rational/mrblib/rational.rb | 10 | ||||
| -rw-r--r-- | mrbgems/mruby-rational/src/rational.c | 54 |
2 files changed, 52 insertions, 12 deletions
diff --git a/mrbgems/mruby-rational/mrblib/rational.rb b/mrbgems/mruby-rational/mrblib/rational.rb index 090928d6d..8b851077e 100644 --- a/mrbgems/mruby-rational/mrblib/rational.rb +++ b/mrbgems/mruby-rational/mrblib/rational.rb @@ -17,16 +17,6 @@ class Rational < Numeric end end - def -(rhs) - if rhs.is_a? Rational - Rational(numerator * rhs.denominator - rhs.numerator * denominator, denominator * rhs.denominator) - elsif rhs.is_a? Integer - Rational(numerator - rhs * denominator, denominator) - elsif rhs.is_a? Numeric - (numerator - rhs * denominator) / denominator - end - end - def /(rhs) if rhs.is_a? Rational Rational(numerator * rhs.denominator, denominator * rhs.numerator) diff --git a/mrbgems/mruby-rational/src/rational.c b/mrbgems/mruby-rational/src/rational.c index 1b2cfcbec..c11a93576 100644 --- a/mrbgems/mruby-rational/src/rational.c +++ b/mrbgems/mruby-rational/src/rational.c @@ -457,8 +457,57 @@ rational_add(mrb_state *mrb, mrb_value x) } } -mrb_int mrb_num_div_int(mrb_state*, mrb_int, mrb_int); -mrb_value mrb_complex_new(mrb_state*, mrb_float, mrb_float); +#ifndef MRB_NO_FLOAT +mrb_value mrb_complex_new(mrb_state *, mrb_float, mrb_float); +#endif + +static mrb_value +rational_sub(mrb_state *mrb, mrb_value x) +{ + struct mrb_rational *p1 = rational_ptr(mrb, x); + mrb_value y = mrb_get_arg1(mrb); + + switch (mrb_type(y)) { + case MRB_TT_INTEGER: + { + mrb_int z = mrb_integer(y); + if (mrb_int_mul_overflow(z, p1->denominator, &z)) rat_overflow(mrb); + if (mrb_int_sub_overflow(p1->numerator, z, &z)) rat_overflow(mrb); + return rational_new_i(mrb, z, p1->denominator); + } + case MRB_TT_RATIONAL: + { + struct mrb_rational *p2 = rational_ptr(mrb, y); + mrb_int a, b; + + if (mrb_int_mul_overflow(p1->numerator, p2->denominator, &a)) rat_overflow(mrb); + if (mrb_int_mul_overflow(p2->numerator, p1->denominator, &b)) rat_overflow(mrb); + if (mrb_int_sub_overflow(a, b, &a)) rat_overflow(mrb); + if (mrb_int_mul_overflow(p1->denominator, p2->denominator, &b)) rat_overflow(mrb); + return rational_new_i(mrb, a, b); + } + +#if defined(MRB_USE_COMPLEX) + case MRB_TT_COMPLEX: + x = mrb_complex_new(mrb, rat_to_flo(p1), 0); + return mrb_funcall_id(mrb, x, MRB_OPSYM(sub), 1, y); +#endif + +#ifndef MRB_NO_FLOAT + case MRB_TT_FLOAT: + 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)); + } +#else + default: + mrb_raise(mrb, E_TYPE_ERROR, "non integer subtraction"); +#endif + } +} + +mrb_int mrb_num_div_int(mrb_state *, mrb_int, mrb_int); /* 15.2.8.3.4 */ /* @@ -544,6 +593,7 @@ void mrb_mruby_rational_gem_init(mrb_state *mrb) mrb_define_method(mrb, rat, "==", rational_eq, MRB_ARGS_REQ(1)); mrb_define_method(mrb, rat, "-@", rational_minus, MRB_ARGS_NONE()); mrb_define_method(mrb, rat, "+", rational_add, MRB_ARGS_REQ(1)); + mrb_define_method(mrb, rat, "-", rational_sub, 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 */ |
