mirror of
https://github.com/mruby/mruby
synced 2026-06-08 16:11:16 +00:00
rational.c: implement Rational#<=> in C.
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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));
|
||||
|
||||
Reference in New Issue
Block a user