mirror of
https://github.com/mruby/mruby
synced 2026-06-08 16:11:16 +00:00
rational.c: overhaul rational operators.
- define `MRB_TT_RATIONAL` - change object structure (`struct RRational`) - add memory management for `MRB_TT_RATIONAL` - avoid operator overloading as much as possible - implement division overloading in C - as a result, performance improved a lot
This commit is contained in:
@@ -129,6 +129,8 @@ enum mrb_vtype {
|
||||
MRB_TT_FIBER,
|
||||
MRB_TT_ISTRUCT,
|
||||
MRB_TT_BREAK,
|
||||
MRB_TT_COMPLEX,
|
||||
MRB_TT_RATIONAL,
|
||||
MRB_TT_MAXDEFINE
|
||||
};
|
||||
|
||||
|
||||
@@ -2,4 +2,5 @@ MRuby::Gem::Specification.new('mruby-rational') do |spec|
|
||||
spec.license = 'MIT'
|
||||
spec.author = 'mruby developers'
|
||||
spec.summary = 'Rational class'
|
||||
spec.build.cc.defines << "MRB_USE_RATIONAL"
|
||||
end
|
||||
|
||||
@@ -64,17 +64,6 @@ class Rational < Numeric
|
||||
nil
|
||||
end
|
||||
end
|
||||
|
||||
def ==(rhs)
|
||||
return true if self.equal?(rhs)
|
||||
case rhs
|
||||
when Integer, Float
|
||||
return numerator == rhs if denominator == 1
|
||||
when Rational
|
||||
return numerator * rhs.denominator == denominator * rhs.numerator
|
||||
end
|
||||
rhs == self
|
||||
end
|
||||
end
|
||||
|
||||
class Numeric
|
||||
@@ -82,28 +71,3 @@ class Numeric
|
||||
Rational(self, 1)
|
||||
end
|
||||
end
|
||||
|
||||
module Kernel
|
||||
[:+, :-, :*, :/, :<=>, :==, :<, :<=, :>, :>=].each do |op|
|
||||
original_operator_name = :"__original_operator_#{op}_rational"
|
||||
Integer.instance_eval do
|
||||
alias_method original_operator_name, op
|
||||
define_method op do |rhs|
|
||||
if rhs.is_a? Rational
|
||||
Rational(self).__send__(op, rhs)
|
||||
else
|
||||
__send__(original_operator_name, rhs)
|
||||
end
|
||||
end
|
||||
end
|
||||
Float.instance_eval do
|
||||
alias_method original_operator_name, op
|
||||
define_method op do |rhs|
|
||||
if rhs.is_a? Rational
|
||||
rhs = rhs.to_f
|
||||
end
|
||||
__send__(original_operator_name, rhs)
|
||||
end
|
||||
end if Object.const_defined?(:Float)
|
||||
end
|
||||
end
|
||||
|
||||
@@ -9,54 +9,46 @@ struct mrb_rational {
|
||||
mrb_int denominator;
|
||||
};
|
||||
|
||||
#if MRB_INT_MAX <= INTPTR_MAX
|
||||
|
||||
#define RATIONAL_USE_ISTRUCT
|
||||
/* use TT_ISTRUCT */
|
||||
#include <mruby/istruct.h>
|
||||
|
||||
#define rational_ptr(mrb, v) (struct mrb_rational*)mrb_istruct_ptr(v)
|
||||
|
||||
static struct RBasic*
|
||||
rational_alloc(mrb_state *mrb, struct RClass *c, struct mrb_rational **p)
|
||||
{
|
||||
struct RIStruct *s;
|
||||
|
||||
s = (struct RIStruct*)mrb_obj_alloc(mrb, MRB_TT_ISTRUCT, c);
|
||||
*p = (struct mrb_rational*)s->inline_data;
|
||||
|
||||
return (struct RBasic*)s;
|
||||
}
|
||||
|
||||
#else
|
||||
/* use TT_DATA */
|
||||
#include <mruby/data.h>
|
||||
|
||||
static const struct mrb_data_type mrb_rational_type = {"Rational", mrb_free};
|
||||
|
||||
static struct RBasic*
|
||||
rational_alloc(mrb_state *mrb, struct RClass *c, struct mrb_rational **p)
|
||||
{
|
||||
struct RData *d;
|
||||
|
||||
Data_Make_Struct(mrb, c, struct mrb_rational, &mrb_rational_type, *p, d);
|
||||
|
||||
return (struct RBasic*)d;
|
||||
}
|
||||
#if defined(MRB_INT64) && defined(MRB_32BIT)
|
||||
struct RRational {
|
||||
MRB_OBJECT_HEADER;
|
||||
struct mrb_rational *p;
|
||||
};
|
||||
|
||||
static struct mrb_rational*
|
||||
rational_ptr(mrb_state *mrb, mrb_value v)
|
||||
{
|
||||
struct mrb_rational *p;
|
||||
struct RRational *r = (struct RRational*)mrb_obj_ptr(v);
|
||||
|
||||
p = DATA_GET_PTR(mrb, v, &mrb_rational_type, struct mrb_rational);
|
||||
if (!p) {
|
||||
if (!r->p) {
|
||||
mrb_raise(mrb, E_ARGUMENT_ERROR, "uninitialized rational");
|
||||
}
|
||||
return p;
|
||||
return r->p;
|
||||
}
|
||||
#else
|
||||
#define RATIONAL_INLINE
|
||||
struct RRational {
|
||||
MRB_OBJECT_HEADER;
|
||||
struct mrb_rational r;
|
||||
};
|
||||
#define rational_ptr(mrb, v) (&((struct RRational*)mrb_obj_ptr(v))->r)
|
||||
#endif
|
||||
|
||||
static struct RBasic*
|
||||
rational_alloc(mrb_state *mrb, struct RClass *c, struct mrb_rational **p)
|
||||
{
|
||||
struct RRational *s;
|
||||
s = (struct RRational*)mrb_obj_alloc(mrb, MRB_TT_RATIONAL, c);
|
||||
#ifdef RATIONAL_INLINE
|
||||
*p = &s->r;
|
||||
#else
|
||||
*p = s->p = (struct mrb_rational*)mrb_malloc(mrb, sizeof(struct mrb_rational));
|
||||
#endif
|
||||
return (struct RBasic*)s;
|
||||
}
|
||||
|
||||
static mrb_value
|
||||
rational_numerator(mrb_state *mrb, mrb_value self)
|
||||
{
|
||||
@@ -356,17 +348,134 @@ rational_m(mrb_state *mrb, mrb_value self)
|
||||
#endif
|
||||
}
|
||||
|
||||
mrb_bool
|
||||
mrb_rational_eq(mrb_state *mrb, mrb_value x, mrb_value y)
|
||||
{
|
||||
struct mrb_rational *p1 = rational_ptr(mrb, x);
|
||||
|
||||
switch (mrb_type(y)) {
|
||||
case MRB_TT_INTEGER:
|
||||
if (p1->denominator != 1) return FALSE;
|
||||
return p1->numerator == mrb_integer(y);
|
||||
#ifndef MRB_NO_FLOAT
|
||||
case MRB_TT_FLOAT:
|
||||
return ((double)p1->numerator/p1->denominator) == mrb_float(y);
|
||||
#endif
|
||||
case MRB_TT_RATIONAL:
|
||||
{
|
||||
struct mrb_rational *p2 = rational_ptr(mrb, y);
|
||||
mrb_int a, b;
|
||||
|
||||
if (p1->numerator == p2->numerator && p1->denominator == p2->denominator) {
|
||||
return TRUE;
|
||||
}
|
||||
if (mrb_int_mul_overflow(p1->numerator, p2->denominator, &a) ||
|
||||
mrb_int_mul_overflow(p2->numerator, p1->denominator, &b)) {
|
||||
#ifdef MRB_NO_FLOAT
|
||||
rat_overflow(mrb);
|
||||
#else
|
||||
return (double)p1->numerator*p2->denominator == (double)p2->numerator*p2->denominator;
|
||||
#endif
|
||||
}
|
||||
return a == b;
|
||||
}
|
||||
#ifdef MRB_USE_COMPLEX
|
||||
case MRB_TT_RATIONAL:
|
||||
{
|
||||
mrb_bool mrb_complex_eq(mrb_state *mrb, mrb_value, mrb_value);
|
||||
return mrb_complex_eq(mrb, y, x);
|
||||
}
|
||||
#endif
|
||||
default:
|
||||
return mrb_equal(mrb, y, x);
|
||||
}
|
||||
}
|
||||
|
||||
static mrb_value
|
||||
rational_eq(mrb_state *mrb, mrb_value x)
|
||||
{
|
||||
mrb_value y = mrb_get_arg1(mrb);
|
||||
return mrb_bool_value(mrb_rational_eq(mrb, x, y));
|
||||
}
|
||||
|
||||
static mrb_value
|
||||
rational_minus(mrb_state *mrb, mrb_value x)
|
||||
{
|
||||
struct mrb_rational *p = rational_ptr(mrb, x);
|
||||
return rational_new(mrb, -p->numerator, p->denominator);
|
||||
}
|
||||
|
||||
mrb_int mrb_num_div_int(mrb_state *, mrb_int, mrb_int);
|
||||
|
||||
/* 15.2.8.3.4 */
|
||||
/*
|
||||
* redefine Integer#/
|
||||
*/
|
||||
static mrb_value
|
||||
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));
|
||||
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:
|
||||
return mrb_funcall_id(mrb, x, MRB_OPSYM(div), 1, y);
|
||||
#endif
|
||||
case MRB_TT_FLOAT:
|
||||
default:
|
||||
#ifdef MRB_NO_FLOAT
|
||||
mrb_raise(mrb, E_TYPE_ERROR, "non integer multiplication");
|
||||
#else
|
||||
return mrb_float_value(mrb, (mrb_float)a * mrb_to_flo(mrb, y));
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
/* 15.2.9.3.19(x) */
|
||||
/*
|
||||
* redefine Integer#quo
|
||||
*/
|
||||
|
||||
static mrb_value
|
||||
int_quo(mrb_state *mrb, mrb_value x)
|
||||
{
|
||||
mrb_value y = mrb_get_arg1(mrb);
|
||||
mrb_int a = mrb_integer(x);
|
||||
|
||||
if (mrb_integer_p(y)) {
|
||||
return rational_new(mrb, a, mrb_integer(y));
|
||||
}
|
||||
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:
|
||||
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_float)a * mrb_to_flo(mrb, y));
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
void mrb_mruby_rational_gem_init(mrb_state *mrb)
|
||||
{
|
||||
struct RClass *rat;
|
||||
|
||||
rat = mrb_define_class_id(mrb, MRB_SYM(Rational), mrb_class_get_id(mrb, MRB_SYM(Numeric)));
|
||||
#ifdef RATIONAL_USE_ISTRUCT
|
||||
MRB_SET_INSTANCE_TT(rat, MRB_TT_ISTRUCT);
|
||||
mrb_assert(sizeof(struct mrb_rational) < ISTRUCT_DATA_SIZE);
|
||||
#else
|
||||
MRB_SET_INSTANCE_TT(rat, MRB_TT_DATA);
|
||||
#endif
|
||||
MRB_SET_INSTANCE_TT(rat, MRB_TT_RATIONAL);
|
||||
mrb_undef_class_method(mrb, rat, "new");
|
||||
mrb_define_class_method(mrb, rat, "_new", rational_s_new, MRB_ARGS_REQ(2));
|
||||
mrb_define_method(mrb, rat, "numerator", rational_numerator, MRB_ARGS_NONE());
|
||||
@@ -377,7 +486,11 @@ void mrb_mruby_rational_gem_init(mrb_state *mrb)
|
||||
mrb_define_method(mrb, rat, "to_i", rational_to_i, MRB_ARGS_NONE());
|
||||
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_minus, MRB_ARGS_NONE());
|
||||
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 */
|
||||
mrb_define_method(mrb, mrb->kernel_module, "Rational", rational_m, MRB_ARGS_ARG(1,1));
|
||||
}
|
||||
|
||||
|
||||
@@ -903,6 +903,17 @@ obj_free(mrb_state *mrb, struct RBasic *obj, int end)
|
||||
}
|
||||
break;
|
||||
|
||||
#if defined(MRB_INT64) && defined(MRB_32BIT)
|
||||
#ifdef MRB_USE_RATIONAL
|
||||
case MRB_TT_RATIONAL:
|
||||
{
|
||||
struct RData *o = (struct RData*)obj;
|
||||
mrb_free(mrb, obj->iv_tbl);
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
+119
-28
@@ -118,7 +118,6 @@ int_pow(mrb_state *mrb, mrb_value x)
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
mrb_int
|
||||
mrb_num_div_int(mrb_state *mrb, mrb_int x, mrb_int y)
|
||||
{
|
||||
@@ -144,20 +143,27 @@ mrb_num_div_int(mrb_state *mrb, mrb_int x, mrb_int y)
|
||||
/* 15.2.9.3.4 */
|
||||
/*
|
||||
* call-seq:
|
||||
* int / other -> int
|
||||
* int / other -> num
|
||||
*
|
||||
* Performs division: the class of the resulting object depends on
|
||||
* the class of <code>num</code> and on the magnitude of the
|
||||
* result.
|
||||
*/
|
||||
static mrb_value
|
||||
int_div(mrb_state *mrb, mrb_value xv)
|
||||
int_div(mrb_state *mrb, mrb_value x)
|
||||
{
|
||||
mrb_int y, div;
|
||||
mrb_value y = mrb_get_arg1(mrb);
|
||||
mrb_int a = mrb_integer(x);
|
||||
|
||||
mrb_get_args(mrb, "i", &y);
|
||||
div = mrb_num_div_int(mrb, mrb_integer(xv), y);
|
||||
return mrb_int_value(mrb, div);
|
||||
if (mrb_integer_p(y)) {
|
||||
mrb_int div = mrb_num_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));
|
||||
#endif
|
||||
}
|
||||
|
||||
/* 15.2.9.3.19(x) */
|
||||
@@ -168,17 +174,29 @@ int_div(mrb_state *mrb, mrb_value xv)
|
||||
* Returns most exact division.
|
||||
*/
|
||||
|
||||
/*
|
||||
* call-seq:
|
||||
* int.div(other) -> int
|
||||
*
|
||||
* Performs division: resulting integer.
|
||||
*/
|
||||
static mrb_value
|
||||
int_quo(mrb_state *mrb, mrb_value xv)
|
||||
int_idiv(mrb_state *mrb, mrb_value x)
|
||||
{
|
||||
#ifdef MRB_NO_FLOAT
|
||||
mrb_int y;
|
||||
|
||||
mrb_get_args(mrb, "i", &y);
|
||||
if (y == 0) {
|
||||
int_zerodiv(mrb);
|
||||
}
|
||||
return mrb_fixnum_value(mrb_integer(xv) / y);
|
||||
return mrb_fixnum_value(mrb_integer(x) / y);
|
||||
}
|
||||
|
||||
static mrb_value
|
||||
int_quo(mrb_state *mrb, mrb_value xv)
|
||||
{
|
||||
#ifdef MRB_NO_FLOAT
|
||||
return int_idiv(mrb, xv);
|
||||
#else
|
||||
mrb_float y;
|
||||
|
||||
@@ -478,6 +496,14 @@ flo_eq(mrb_state *mrb, mrb_value x)
|
||||
return mrb_bool_value(mrb_float(x) == (mrb_float)mrb_integer(y));
|
||||
case MRB_TT_FLOAT:
|
||||
return mrb_bool_value(mrb_float(x) == mrb_float(y));
|
||||
#ifdef MRB_USE_RATIONAL
|
||||
case MRB_TT_RATIONAL:
|
||||
return mrb_bool_value(mrb_float(x) == mrb_to_flo(mrb, y));
|
||||
#endif
|
||||
#ifdef MRB_USE_COMPLEX
|
||||
case MRB_TT_COMPLEX:
|
||||
return mrb_bool_value(mrb_equal(mrb, y, x));
|
||||
#endif
|
||||
default:
|
||||
return mrb_false_value();
|
||||
}
|
||||
@@ -876,13 +902,21 @@ fixnum_mul(mrb_state *mrb, mrb_value x, mrb_value y)
|
||||
if (mrb_int_mul_overflow(a, b, &c)) {
|
||||
int_overflow(mrb, "multiplication");
|
||||
}
|
||||
return mrb_fixnum_value(c);
|
||||
return mrb_int_value(mrb, c);
|
||||
}
|
||||
#ifdef MRB_NO_FLOAT
|
||||
mrb_raise(mrb, E_TYPE_ERROR, "non fixnum value");
|
||||
#else
|
||||
return mrb_float_value(mrb, (mrb_float)a * mrb_to_flo(mrb, y));
|
||||
switch (mrb_type(y)) {
|
||||
#if defined(MRB_USE_RATIONAL) || defined(MRB_USE_COMPLEX)
|
||||
case MRB_TT_RATIONAL:
|
||||
case MRB_TT_COMPLEX:
|
||||
return mrb_funcall_id(mrb, y, MRB_OPSYM(mul), 1, x);
|
||||
#endif
|
||||
default:
|
||||
#ifdef MRB_NO_FLOAT
|
||||
mrb_raise(mrb, E_TYPE_ERROR, "non integer multiplication");
|
||||
#else
|
||||
return mrb_float_value(mrb, (mrb_float)a * mrb_to_flo(mrb, y));
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
MRB_API mrb_value
|
||||
@@ -895,6 +929,15 @@ mrb_num_mul(mrb_state *mrb, mrb_value x, mrb_value y)
|
||||
if (mrb_float_p(x)) {
|
||||
return mrb_float_value(mrb, mrb_float(x) * mrb_to_flo(mrb, y));
|
||||
}
|
||||
#endif
|
||||
#if defined(MRB_USE_RATIONAL) || defined(MRB_USE_COMPLEX)
|
||||
switch (mrb_type(x)) {
|
||||
case MRB_TT_RATIONAL:
|
||||
case MRB_TT_COMPLEX:
|
||||
return mrb_funcall_id(mrb, x, MRB_OPSYM(mul), 1, y);
|
||||
default:
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
mrb_raise(mrb, E_TYPE_ERROR, "no number multiply");
|
||||
return mrb_nil_value(); /* not reached */
|
||||
@@ -964,7 +1007,7 @@ int_mod(mrb_state *mrb, mrb_value x)
|
||||
return mrb_fixnum_value(mod);
|
||||
}
|
||||
#ifdef MRB_NO_FLOAT
|
||||
mrb_raise(mrb, E_TYPE_ERROR, "non fixnum value");
|
||||
mrb_raise(mrb, E_TYPE_ERROR, "non integer modulo");
|
||||
#else
|
||||
else {
|
||||
mrb_float mod;
|
||||
@@ -993,7 +1036,7 @@ int_divmod(mrb_state *mrb, mrb_value x)
|
||||
return mrb_assoc_new(mrb, mrb_int_value(mrb, div), mrb_int_value(mrb, mod));
|
||||
}
|
||||
#ifdef MRB_NO_FLOAT
|
||||
mrb_raise(mrb, E_TYPE_ERROR, "non fixnum value");
|
||||
mrb_raise(mrb, E_TYPE_ERROR, "non integer divmod");
|
||||
#else
|
||||
else {
|
||||
mrb_float div, mod;
|
||||
@@ -1048,6 +1091,14 @@ int_equal(mrb_state *mrb, mrb_value x)
|
||||
#ifndef MRB_NO_FLOAT
|
||||
case MRB_TT_FLOAT:
|
||||
return mrb_bool_value((mrb_float)mrb_integer(x) == mrb_float(y));
|
||||
#endif
|
||||
#ifdef MRB_USE_RATIONAL
|
||||
case MRB_TT_RATIONAL:
|
||||
return mrb_bool_value(mrb_equal(mrb, y, x));
|
||||
#endif
|
||||
#ifdef MRB_USE_COMPLEX
|
||||
case MRB_TT_COMPLEX:
|
||||
return mrb_bool_value(mrb_equal(mrb, y, x));
|
||||
#endif
|
||||
default:
|
||||
return mrb_false_value();
|
||||
@@ -1292,11 +1343,19 @@ fixnum_plus(mrb_state *mrb, mrb_value x, mrb_value y)
|
||||
}
|
||||
return mrb_int_value(mrb, c);
|
||||
}
|
||||
#ifdef MRB_NO_FLOAT
|
||||
mrb_raise(mrb, E_TYPE_ERROR, "non fixnum value");
|
||||
#else
|
||||
return mrb_float_value(mrb, (mrb_float)a + mrb_to_flo(mrb, y));
|
||||
switch (mrb_type(y)) {
|
||||
#if defined(MRB_USE_RATIONAL) || defined(MRB_USE_COMPLEX)
|
||||
case MRB_TT_RATIONAL:
|
||||
case MRB_TT_COMPLEX:
|
||||
return mrb_funcall_id(mrb, y, MRB_OPSYM(add), 1, x);
|
||||
#endif
|
||||
default:
|
||||
#ifdef MRB_NO_FLOAT
|
||||
mrb_raise(mrb, E_TYPE_ERROR, "non integer addition");
|
||||
#else
|
||||
return mrb_float_value(mrb, (mrb_float)a + mrb_to_flo(mrb, y));
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
MRB_API mrb_value
|
||||
@@ -1309,6 +1368,15 @@ mrb_num_plus(mrb_state *mrb, mrb_value x, mrb_value y)
|
||||
if (mrb_float_p(x)) {
|
||||
return mrb_float_value(mrb, mrb_float(x) + mrb_to_flo(mrb, y));
|
||||
}
|
||||
#endif
|
||||
#if defined(MRB_USE_RATIONAL) || defined(MRB_USE_COMPLEX)
|
||||
switch (mrb_type(x)) {
|
||||
case MRB_TT_RATIONAL:
|
||||
case MRB_TT_COMPLEX:
|
||||
return mrb_funcall_id(mrb, x, MRB_OPSYM(add), 1, y);
|
||||
default:
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
mrb_raise(mrb, E_TYPE_ERROR, "no number addition");
|
||||
return mrb_nil_value(); /* not reached */
|
||||
@@ -1346,11 +1414,20 @@ fixnum_minus(mrb_state *mrb, mrb_value x, mrb_value y)
|
||||
}
|
||||
return mrb_int_value(mrb, c);
|
||||
}
|
||||
#ifdef MRB_NO_FLOAT
|
||||
mrb_raise(mrb, E_TYPE_ERROR, "non fixnum value");
|
||||
#else
|
||||
return mrb_float_value(mrb, (mrb_float)a - mrb_to_flo(mrb, y));
|
||||
switch (mrb_type(y)) {
|
||||
#if defined(MRB_USE_RATIONAL) || defined(MRB_USE_COMPLEX)
|
||||
case MRB_TT_RATIONAL:
|
||||
case MRB_TT_COMPLEX:
|
||||
x = mrb_funcall_id(mrb, y, MRB_OPSYM(sub), 1, x);
|
||||
return mrb_funcall_id(mrb, x, MRB_OPSYM(minus), 0);
|
||||
#endif
|
||||
default:
|
||||
#ifdef MRB_NO_FLOAT
|
||||
mrb_raise(mrb, E_TYPE_ERROR, "non integer subtraction");
|
||||
#else
|
||||
return mrb_float_value(mrb, (mrb_float)a - mrb_to_flo(mrb, y));
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
MRB_API mrb_value
|
||||
@@ -1363,6 +1440,15 @@ mrb_num_minus(mrb_state *mrb, mrb_value x, mrb_value y)
|
||||
if (mrb_float_p(x)) {
|
||||
return mrb_float_value(mrb, mrb_float(x) - mrb_to_flo(mrb, y));
|
||||
}
|
||||
#endif
|
||||
#if defined(MRB_USE_RATIONAL) || defined(MRB_USE_COMPLEX)
|
||||
switch (mrb_type(x)) {
|
||||
case MRB_TT_RATIONAL:
|
||||
case MRB_TT_COMPLEX:
|
||||
return mrb_funcall_id(mrb, x, MRB_OPSYM(sub), 1, y);
|
||||
default:
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
mrb_raise(mrb, E_TYPE_ERROR, "no number subtraction");
|
||||
return mrb_nil_value(); /* not reached */
|
||||
@@ -1471,6 +1557,11 @@ cmpnum(mrb_state *mrb, mrb_value v1, mrb_value v2)
|
||||
case MRB_TT_FLOAT:
|
||||
y = mrb_float(v2);
|
||||
break;
|
||||
#endif
|
||||
#ifdef MRB_USE_RATIONAL
|
||||
case MRB_TT_RATIONAL:
|
||||
y = mrb_to_flo(mrb, v2);
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
return -2;
|
||||
@@ -1631,9 +1722,6 @@ mrb_init_numeric(mrb_state *mrb)
|
||||
MRB_SET_INSTANCE_TT(integer, MRB_TT_INTEGER);
|
||||
mrb_undef_class_method(mrb, integer, "new");
|
||||
mrb_define_method(mrb, integer, "**", int_pow, MRB_ARGS_REQ(1));
|
||||
mrb_define_method(mrb, integer, "/", int_div, MRB_ARGS_REQ(1)); /* 15.2.8.3.6 */
|
||||
mrb_define_method(mrb, integer, "quo", int_quo, MRB_ARGS_REQ(1)); /* 15.2.7.4.5 (x) */
|
||||
mrb_define_method(mrb, integer, "div", int_div, MRB_ARGS_REQ(1));
|
||||
mrb_define_method(mrb, integer, "<=>", num_cmp, MRB_ARGS_REQ(1)); /* 15.2.8.3.1 */
|
||||
mrb_define_method(mrb, integer, "<", num_lt, MRB_ARGS_REQ(1));
|
||||
mrb_define_method(mrb, integer, "<=", num_le, MRB_ARGS_REQ(1));
|
||||
@@ -1653,6 +1741,9 @@ mrb_init_numeric(mrb_state *mrb)
|
||||
mrb_define_method(mrb, integer, "-", int_minus, MRB_ARGS_REQ(1)); /* 15.2.8.3.2 */
|
||||
mrb_define_method(mrb, integer, "*", int_mul, MRB_ARGS_REQ(1)); /* 15.2.8.3.3 */
|
||||
mrb_define_method(mrb, integer, "%", int_mod, MRB_ARGS_REQ(1)); /* 15.2.8.3.5 */
|
||||
mrb_define_method(mrb, integer, "/", int_div, MRB_ARGS_REQ(1)); /* 15.2.8.3.6 */
|
||||
mrb_define_method(mrb, integer, "quo", int_quo, MRB_ARGS_REQ(1)); /* 15.2.7.4.5 (x) */
|
||||
mrb_define_method(mrb, integer, "div", int_idiv, MRB_ARGS_REQ(1));
|
||||
mrb_define_method(mrb, integer, "==", int_equal, MRB_ARGS_REQ(1)); /* 15.2.8.3.7 */
|
||||
mrb_define_method(mrb, integer, "~", int_rev, MRB_ARGS_NONE()); /* 15.2.8.3.8 */
|
||||
mrb_define_method(mrb, integer, "&", int_and, MRB_ARGS_REQ(1)); /* 15.2.8.3.9 */
|
||||
|
||||
+4
-1
@@ -516,7 +516,10 @@ mrb_to_int(mrb_state *mrb, mrb_value val)
|
||||
return mrb_flo_to_fixnum(mrb, val);
|
||||
}
|
||||
#endif
|
||||
mrb_raisef(mrb, E_TYPE_ERROR, "can't convert %Y to Integer", val);
|
||||
if (mrb_string_p(val)) {
|
||||
mrb_raise(mrb, E_TYPE_ERROR, "can't convert String to Integer");
|
||||
}
|
||||
return mrb_type_convert(mrb, val, MRB_TT_INTEGER, MRB_SYM(to_i));
|
||||
}
|
||||
return val;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user