diff options
| author | Yukihiro "Matz" Matsumoto <[email protected]> | 2021-03-24 19:49:20 +0900 |
|---|---|---|
| committer | Yukihiro "Matz" Matsumoto <[email protected]> | 2021-03-24 19:49:20 +0900 |
| commit | 4a0c14e3bdb1706b66edb95338fd6e3d7dbabb45 (patch) | |
| tree | bfb7cdd60dd86d3ebd76a8b2b7286177c0379cd9 /mrbgems | |
| parent | 3a2075343c60f0b05b0a378a8dfef4425cf64de7 (diff) | |
| download | mruby-4a0c14e3bdb1706b66edb95338fd6e3d7dbabb45.tar.gz mruby-4a0c14e3bdb1706b66edb95338fd6e3d7dbabb45.zip | |
rational.c: implement `Rational#<=>` in C.
Diffstat (limited to 'mrbgems')
| -rw-r--r-- | mrbgems/mruby-rational/mrblib/rational.rb | 16 | ||||
| -rw-r--r-- | mrbgems/mruby-rational/src/rational.c | 71 |
2 files changed, 67 insertions, 20 deletions
diff --git a/mrbgems/mruby-rational/mrblib/rational.rb b/mrbgems/mruby-rational/mrblib/rational.rb index 2c71f43f5..ebe6829b0 100644 --- a/mrbgems/mruby-rational/mrblib/rational.rb +++ b/mrbgems/mruby-rational/mrblib/rational.rb @@ -6,22 +6,6 @@ class Rational < Numeric def to_s "#{numerator}/#{denominator}" end - - def <=>(rhs) - case rhs - when Integer, Float - return numerator <=> rhs if denominator == 1 - rhs = Rational(rhs) - end - case rhs - when Rational - (numerator * rhs.denominator - denominator * rhs.numerator) <=> 0 - when Numeric - (rhs <=> self)&.-@ - else - nil - end - end end class Numeric diff --git a/mrbgems/mruby-rational/src/rational.c b/mrbgems/mruby-rational/src/rational.c index 71750410a..5b6bbad89 100644 --- a/mrbgems/mruby-rational/src/rational.c +++ b/mrbgems/mruby-rational/src/rational.c @@ -405,6 +405,72 @@ rational_eq(mrb_state *mrb, mrb_value x) return mrb_bool_value(mrb_rational_eq(mrb, x, y)); } + +#ifndef MRB_NO_FLOAT +mrb_value mrb_complex_new(mrb_state *, mrb_float, mrb_float); +#endif + +static mrb_value +rational_cmp(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_RATIONAL: + { + struct mrb_rational *p2 = rational_ptr(mrb, y); + mrb_int a, b; + + if (mrb_int_mul_overflow(p1->numerator, p2->denominator, &a) || + mrb_int_mul_overflow(p1->denominator, p2->numerator, &b)) { + return mrb_nil_value(); + } + if (a > b) + return mrb_fixnum_value(1); + else if (a < b) + return mrb_fixnum_value(-1); + return mrb_fixnum_value(0); + } + case MRB_TT_INTEGER: +#ifndef MRB_NO_FLOAT + case MRB_TT_FLOAT: + { + mrb_float a = rat_to_flo(p1), b = mrb_to_flo(mrb, y); + if (a > b) + return mrb_fixnum_value(1); + else if (a < b) + return mrb_fixnum_value(-1); + return mrb_fixnum_value(0); + } +#else + { + mrb_int a = p1->numerator, b; + if (mrb_int_mul_overflow(p1->denominator, mrb_integer(y), &b)) { + return mrb_nil_value(); + } + if (a > b) + return mrb_fixnum_value(1); + else if (a < b) + return mrb_fixnum_value(-1); + return mrb_fixnum_value(0); + } +#endif +#ifdef 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(cmp), 1, y); +#endif + default: + x = mrb_funcall_id(mrb, y, MRB_OPSYM(cmp), 1, x); + if (mrb_integer_p(x)) { + mrb_int z = mrb_integer(x); + return mrb_fixnum_value(-z); + } + return mrb_nil_value(); + } +} + static mrb_value rational_minus(mrb_state *mrb, mrb_value x) { @@ -457,10 +523,6 @@ rational_add(mrb_state *mrb, mrb_value x) } } -#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) { @@ -669,6 +731,7 @@ void mrb_mruby_rational_gem_init(mrb_state *mrb) mrb_define_method(mrb, rat, "to_r", rational_to_r, MRB_ARGS_NONE()); mrb_define_method(mrb, rat, "negative?", rational_negative_p, MRB_ARGS_NONE()); mrb_define_method(mrb, rat, "==", rational_eq, MRB_ARGS_REQ(1)); + mrb_define_method(mrb, rat, "<=>", rational_cmp, 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)); |
