complex.c: overhaul complex operators.
define `MRB_TT_COMPLEX`
change object structure (`struct RComplex`)
add memory management for `MRB_TT_COMPLEX`
avoid operator overloading as much as possible
as a result, performance improved a log
should work with and without `Rational` defined
MODIFY
mrbgems/mruby-complex/mrbgem.rake
mrbgems/mruby-complex/mrbgem.rake
@@ -2,6 +2,6 @@ MRuby::Gem::Specification.new('mruby-complex') do |spec|
spec.license = 'MIT'
spec.author = 'mruby developers'
spec.summary = 'Complex class'
-
+ spec.build.cc.defines << "MRB_USE_COMPLEX"
spec.add_dependency 'mruby-math', core: 'mruby-math'
end

MODIFY
mrbgems/mruby-complex/mrblib/complex.rb
mrbgems/mruby-complex/mrblib/complex.rb
@@ -81,7 +81,7 @@ class Complex < Numeric
alias_method :conj, :conjugate
def fdiv(numeric)
- Complex(real.to_f / numeric, imaginary.to_f / numeric)
+ Complex(real / numeric, imaginary / numeric)
end
def polar
@@ -108,21 +108,6 @@ class Complex < Numeric
alias_method :imag, :imaginary
- [Integer, Float].each do |cls|
- cls.class_eval do
- [:+, :-, :*, :/, :==].each do |op|
- original_operator_name = :"__original_operator_#{op}_complex"
- alias_method original_operator_name, op
- define_method op do |rhs|
- if rhs.is_a? Complex
- Complex(self).__send__(op, rhs)
- else
- __send__(original_operator_name, rhs)
- end
- end
- end
- end
- end
Numeric.class_eval do
def i
Complex(0, self)

MODIFY
mrbgems/mruby-complex/src/complex.c
mrbgems/mruby-complex/src/complex.c
# error Complex conflicts with 'MRB_NO_FLOAT' configuration
#endif
-struct mrb_complex {
- mrb_float real;
- mrb_float imaginary;
-};
-
#ifdef MRB_USE_FLOAT32
#define F(x) x##f
#else
#define F(x) x
#endif
-#if defined(MRB_64BIT) || defined(MRB_USE_FLOAT32)
+struct mrb_complex {
+ mrb_float real;
+ mrb_float imaginary;
+};
-#define COMPLEX_USE_ISTRUCT
-/* use TT_ISTRUCT */
#include <mruby/istruct.h>
-#define complex_ptr(mrb, v) (struct mrb_complex*)mrb_istruct_ptr(v)
+#if defined(MRB_32BIT) && !defined(MRB_USE_FLOAT32)
-static struct RBasic*
-complex_alloc(mrb_state *mrb, struct RClass *c, struct mrb_complex **p)
-{
- struct RIStruct *s;
+struct RComplex {
+ MRB_OBJECT_HEADER;
+ struct mrb_complex *p;
+};
- s = (struct RIStruct*)mrb_obj_alloc(mrb, MRB_TT_ISTRUCT, c);
- *p = (struct mrb_complex*)s->inline_data;
+static struct mrb_complex*
+complex_ptr(mrb_state *mrb, mrb_value v)
+{
+ struct RComplex *r = (struct RComplex*)mrb_obj_ptr(v);
- return (struct RBasic*)s;
+ if (!r->p) {
+ mrb_raise(mrb, E_ARGUMENT_ERROR, "uninitialized complex");
+ }
+ return r->p;
}
#else
-/* use TT_DATA */
-#include <mruby/data.h>
-
-static const struct mrb_data_type mrb_complex_type = {"Complex", mrb_free};
+#define COMPLEX_INLINE
+struct RComplex {
+ MRB_OBJECT_HEADER;
+ struct mrb_complex r;
+};
+#define complex_ptr(mrb, v) (&((struct RComplex*)mrb_obj_ptr(v))->r)
+#endif
static struct RBasic*
complex_alloc(mrb_state *mrb, struct RClass *c, struct mrb_complex **p)
{
- struct RData *d;
-
- Data_Make_Struct(mrb, c, struct mrb_complex, &mrb_complex_type, *p, d);
-
- return (struct RBasic*)d;
-}
-
-static struct mrb_complex*
-complex_ptr(mrb_state *mrb, mrb_value v)
-{
- struct mrb_complex *p;
-
- p = DATA_GET_PTR(mrb, v, &mrb_complex_type, struct mrb_complex);
- if (!p) {
- mrb_raise(mrb, E_ARGUMENT_ERROR, "uninitialized complex");
- }
- return p;
-}
+ struct RComplex *s;
+ s = (struct RComplex*)mrb_obj_alloc(mrb, MRB_TT_COMPLEX, c);
+#ifdef COMPLEX_INLINE
+ *p = &s->r;
+#else
+ *p = s->p = (struct mrb_complex*)mrb_malloc(mrb, sizeof(struct mrb_complex));
#endif
+ return (struct RBasic*)s;
+}
void
mrb_complex_get(mrb_state *mrb, mrb_value cpx, mrb_float *r, mrb_float *i)
@@ -229,19 +223,62 @@ complex_div(mrb_state *mrb, mrb_value self)
return complex_new(mrb, F(ldexp)(zr.s, zr.x), F(ldexp)(zi.s, zi.x));
}
+#ifndef MRB_USE_RATIONAL
+mrb_int mrb_num_div_int(mrb_state *mrb, mrb_int x, mrb_int y);
+
+/* 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_COMPLEX:
+ return mrb_funcall_id(mrb, x, MRB_OPSYM(div), 1, y);
+ default:
+ return mrb_float_value(mrb, (mrb_float)a * mrb_to_flo(mrb, y));
+ }
+}
+
+/* 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);
+
+ switch (mrb_type(y)) {
+ case MRB_TT_COMPLEX:
+ return mrb_funcall_id(mrb, x, MRB_OPSYM(div), 1, y);
+ default:
+ return mrb_float_value(mrb, (mrb_float)a * mrb_to_flo(mrb, y));
+ }
+}
+#endif
+
void mrb_mruby_complex_gem_init(mrb_state *mrb)
{
struct RClass *comp;
-#ifdef COMPLEX_USE_ISTRUCT
- mrb_assert(sizeof(struct mrb_complex) < ISTRUCT_DATA_SIZE);
+#ifdef COMPLEX_INLINE
+ mrb_assert(sizeof(struct mrb_complex) < sizeof(void*)*3);
#endif
+
comp = mrb_define_class_id(mrb, MRB_SYM(Complex), mrb_class_get_id(mrb, MRB_SYM(Numeric)));
-#ifdef COMPLEX_USE_ISTRUCT
- MRB_SET_INSTANCE_TT(comp, MRB_TT_ISTRUCT);
-#else
- MRB_SET_INSTANCE_TT(comp, MRB_TT_DATA);
-#endif
+ MRB_SET_INSTANCE_TT(comp, MRB_TT_COMPLEX);
+
mrb_undef_class_method(mrb, comp, "new");
mrb_define_class_method(mrb, comp, "rectangular", complex_s_rect, MRB_ARGS_REQ(1)|MRB_ARGS_OPT(1));
mrb_define_class_method(mrb, comp, "rect", complex_s_rect, MRB_ARGS_REQ(1)|MRB_ARGS_OPT(1));
@@ -252,6 +289,10 @@ void mrb_mruby_complex_gem_init(mrb_state *mrb)
mrb_define_method(mrb, comp, "to_i", complex_to_i, MRB_ARGS_NONE());
mrb_define_method(mrb, comp, "to_c", complex_to_c, MRB_ARGS_NONE());
mrb_define_method(mrb, comp, "__div__", complex_div, MRB_ARGS_REQ(1));
+#ifndef MRB_USE_RATIONAL
+ 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 */
+#endif
}
void

MODIFY
src/gc.c
src/gc.c
@@ -903,15 +903,22 @@ obj_free(mrb_state *mrb, struct RBasic *obj, int end)
}
break;
-#if defined(MRB_INT64) && defined(MRB_32BIT)
-#ifdef MRB_USE_RATIONAL
+#if defined(MRB_USE_RATIONAL) && defined(MRB_INT64) && defined(MRB_32BIT)
case MRB_TT_RATIONAL:
{
struct RData *o = (struct RData*)obj;
- mrb_free(mrb, obj->iv_tbl);
+ mrb_free(mrb, o->iv);
}
break;
#endif
+
+#if defined(MRB_USE_COMPLEX) && defined(MRB_32BIT) && !defined(MRB_USE_FLOAT32)
+ case MRB_TT_COMPLEX:
+ {
+ struct RData *o = (struct RData*)obj;
+ mrb_free(mrb, o->iv);
+ }
+ break;
#endif
default:

MODIFY
src/numeric.c
src/numeric.c
@@ -267,14 +267,18 @@ mrb_num_div_flo(mrb_state *mrb, mrb_float x, mrb_float y)
}
static mrb_value
-flo_div(mrb_state *mrb, mrb_value xv)
+flo_div(mrb_state *mrb, mrb_value x)
{
- mrb_float x, y;
+ mrb_value y = mrb_get_arg1(mrb);
+ mrb_float a = mrb_float(x);
- x = mrb_float(xv);
- mrb_get_args(mrb, "f", &y);
- x = mrb_num_div_flo(mrb, x, y);
- return mrb_float_value(mrb, x);
+ if (mrb_float_p(y)) {
+ a = mrb_num_div_flo(mrb, a, mrb_float(y));
+ }
+ else {
+ a = mrb_num_div_flo(mrb, a, mrb_to_flo(mrb, y));
+ }
+ return mrb_float_value(mrb, a);
}
/* 15.2.9.3.16(x) */
@@ -348,6 +352,32 @@ flo_to_s(mrb_state *mrb, mrb_value flt)
return str;
}
+/* 15.2.9.3.1 */
+/*
+ * call-seq:
+ * float + other -> float
+ *
+ * Returns a new float which is the sum of <code>float</code>
+ * and <code>other</code>.
+ */
+static mrb_value
+flo_add(mrb_state *mrb, mrb_value x)
+{
+ mrb_value y = mrb_get_arg1(mrb);
+ mrb_float a = mrb_float(x);
+
+ switch (mrb_type(y)) {
+ case MRB_TT_FLOAT:
+ return mrb_float_value(mrb, a + mrb_float(y));
+#if defined(MRB_USE_COMPLEX)
+ case MRB_TT_COMPLEX:
+ return mrb_funcall_id(mrb, y, MRB_OPSYM(add), 1, x);
+#endif
+ default:
+ return mrb_float_value(mrb, a + mrb_to_flo(mrb, y));
+ }
+}
+
/* 15.2.9.3.2 */
/*
* call-seq:
@@ -358,11 +388,22 @@ flo_to_s(mrb_state *mrb, mrb_value flt)
*/
static mrb_value
-flo_minus(mrb_state *mrb, mrb_value x)
+flo_sub(mrb_state *mrb, mrb_value x)
{
mrb_value y = mrb_get_arg1(mrb);
+ mrb_float a = mrb_float(x);
- return mrb_float_value(mrb, mrb_float(x) - mrb_to_flo(mrb, y));
+ switch (mrb_type(y)) {
+ case MRB_TT_FLOAT:
+ return mrb_float_value(mrb, a - mrb_float(y));
+#if defined(MRB_USE_COMPLEX)
+ 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:
+ return mrb_float_value(mrb, a - mrb_to_flo(mrb, y));
+ }
}
/* 15.2.9.3.3 */
@@ -378,8 +419,18 @@ static mrb_value
flo_mul(mrb_state *mrb, mrb_value x)
{
mrb_value y = mrb_get_arg1(mrb);
+ mrb_float a = mrb_float(x);
- return mrb_float_value(mrb, mrb_float(x) * mrb_to_flo(mrb, y));
+ switch (mrb_type(y)) {
+ case MRB_TT_FLOAT:
+ return mrb_float_value(mrb, a * mrb_float(y));
+#if defined(MRB_USE_COMPLEX)
+ case MRB_TT_COMPLEX:
+ return mrb_funcall_id(mrb, y, MRB_OPSYM(mul), 1, x);
+#endif
+ default:
+ return mrb_float_value(mrb, a * mrb_to_flo(mrb, y));
+ }
}
static void
@@ -1328,7 +1379,7 @@ mrb_flo_to_fixnum(mrb_state *mrb, mrb_value x)
#endif
static mrb_value
-fixnum_plus(mrb_state *mrb, mrb_value x, mrb_value y)
+int_plus(mrb_state *mrb, mrb_value x, mrb_value y)
{
mrb_int a;
@@ -1362,7 +1413,7 @@ MRB_API mrb_value
mrb_num_plus(mrb_state *mrb, mrb_value x, mrb_value y)
{
if (mrb_integer_p(x)) {
- return fixnum_plus(mrb, x, y);
+ return int_plus(mrb, x, y);
}
#ifndef MRB_NO_FLOAT
if (mrb_float_p(x)) {
@@ -1392,15 +1443,15 @@ mrb_num_plus(mrb_state *mrb, mrb_value x, mrb_value y)
* result.
*/
static mrb_value
-int_plus(mrb_state *mrb, mrb_value self)
+int_add(mrb_state *mrb, mrb_value self)
{
mrb_value other = mrb_get_arg1(mrb);
- return fixnum_plus(mrb, self, other);
+ return int_plus(mrb, self, other);
}
static mrb_value
-fixnum_minus(mrb_state *mrb, mrb_value x, mrb_value y)
+int_minus(mrb_state *mrb, mrb_value x, mrb_value y)
{
mrb_int a;
@@ -1434,7 +1485,7 @@ MRB_API mrb_value
mrb_num_minus(mrb_state *mrb, mrb_value x, mrb_value y)
{
if (mrb_integer_p(x)) {
- return fixnum_minus(mrb, x, y);
+ return int_minus(mrb, x, y);
}
#ifndef MRB_NO_FLOAT
if (mrb_float_p(x)) {
@@ -1465,11 +1516,11 @@ mrb_num_minus(mrb_state *mrb, mrb_value x, mrb_value y)
* result.
*/
static mrb_value
-int_minus(mrb_state *mrb, mrb_value self)
+int_sub(mrb_state *mrb, mrb_value self)
{
mrb_value other = mrb_get_arg1(mrb);
- return fixnum_minus(mrb, self, other);
+ return int_minus(mrb, self, other);
}
@@ -1685,24 +1736,6 @@ num_infinite_p(mrb_state *mrb, mrb_value self)
return mrb_false_value();
}
-/* 15.2.9.3.1 */
-/*
- * call-seq:
- * float + other -> float
- *
- * Returns a new float which is the sum of <code>float</code>
- * and <code>other</code>.
- */
-#ifndef MRB_NO_FLOAT
-static mrb_value
-flo_plus(mrb_state *mrb, mrb_value x)
-{
- mrb_value y = mrb_get_arg1(mrb);
-
- return mrb_float_value(mrb, mrb_float(x) + mrb_to_flo(mrb, y));
-}
-#endif
-
/* ------------------------------------------------------------------------*/
void
mrb_init_numeric(mrb_state *mrb)
@@ -1737,8 +1770,8 @@ mrb_init_numeric(mrb_state *mrb)
mrb_define_method(mrb, integer, "truncate", int_to_i, MRB_ARGS_NONE()); /* 15.2.8.3.26 */
#endif
- mrb_define_method(mrb, integer, "+", int_plus, MRB_ARGS_REQ(1)); /* 15.2.8.3.1 */
- mrb_define_method(mrb, integer, "-", int_minus, MRB_ARGS_REQ(1)); /* 15.2.8.3.2 */
+ mrb_define_method(mrb, integer, "+", int_add, MRB_ARGS_REQ(1)); /* 15.2.8.3.1 */
+ mrb_define_method(mrb, integer, "-", int_sub, 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 */
@@ -1772,8 +1805,8 @@ mrb_init_numeric(mrb_state *mrb)
mrb_define_method(mrb, fl, "/", flo_div, MRB_ARGS_REQ(1)); /* 15.2.9.3.6 */
mrb_define_method(mrb, fl, "quo", flo_div, MRB_ARGS_REQ(1)); /* 15.2.7.4.5 (x) */
mrb_define_method(mrb, fl, "div", flo_idiv, MRB_ARGS_REQ(1));
- mrb_define_method(mrb, fl, "+", flo_plus, MRB_ARGS_REQ(1)); /* 15.2.9.3.3 */
- mrb_define_method(mrb, fl, "-", flo_minus, MRB_ARGS_REQ(1)); /* 15.2.9.3.4 */
+ mrb_define_method(mrb, fl, "+", flo_add, MRB_ARGS_REQ(1)); /* 15.2.9.3.3 */
+ mrb_define_method(mrb, fl, "-", flo_sub, MRB_ARGS_REQ(1)); /* 15.2.9.3.4 */
mrb_define_method(mrb, fl, "*", flo_mul, MRB_ARGS_REQ(1)); /* 15.2.9.3.5 */
mrb_define_method(mrb, fl, "%", flo_mod, MRB_ARGS_REQ(1)); /* 15.2.9.3.7 */
mrb_define_method(mrb, fl, "<=>", num_cmp, MRB_ARGS_REQ(1)); /* 15.2.9.3.1 */

complex.c: overhaul complex operators.

- define `MRB_TT_COMPLEX`
- change object structure (`struct RComplex`)
- add memory management for `MRB_TT_COMPLEX`
- avoid operator overloading as much as possible
- as a result, performance improved a log
- should work with and without `Rational` defined