mruby-rational: define <=> method in Ruby, not in C

This commit is contained in:
Yukihiro "Matz" Matsumoto
2024-06-16 15:02:35 +09:00
parent 36eff3ec59
commit 3b9aec90dd
2 changed files with 7 additions and 57 deletions
@@ -6,6 +6,13 @@ class Rational < Numeric
def to_s
"#{numerator}/#{denominator}"
end
def <=>(other)
return nil unless other.kind_of?(Numeric)
self.to_f <=> other.to_f
rescue
nil
end
end
class Numeric
-57
View File
@@ -387,62 +387,6 @@ rational_eq(mrb_state *mrb, mrb_value x)
return mrb_bool_value(result);
}
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_float(p1), b = mrb_as_float(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
default:
x = mrb_funcall_argv(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)
{
@@ -733,7 +677,6 @@ void mrb_mruby_rational_gem_init(mrb_state *mrb)
mrb_define_method_id(mrb, rat, MRB_SYM(to_r), mrb_obj_itself, MRB_ARGS_NONE());
mrb_define_method_id(mrb, rat, MRB_SYM_Q(negative), rational_negative_p, MRB_ARGS_NONE());
mrb_define_method_id(mrb, rat, MRB_OPSYM(eq), rational_eq, MRB_ARGS_REQ(1));
mrb_define_method_id(mrb, rat, MRB_OPSYM(cmp), rational_cmp, MRB_ARGS_REQ(1));
mrb_define_method_id(mrb, rat, MRB_OPSYM(minus), rational_minus, MRB_ARGS_NONE());
mrb_define_method_id(mrb, rat, MRB_OPSYM(add), rational_add, MRB_ARGS_REQ(1));
mrb_define_method_id(mrb, rat, MRB_OPSYM(sub), rational_sub, MRB_ARGS_REQ(1));