diff options
| -rw-r--r-- | mrbgems/mruby-complex/mrbgem.rake | 2 | ||||
| -rw-r--r-- | mrbgems/mruby-complex/mrblib/complex.rb | 17 | ||||
| -rw-r--r-- | mrbgems/mruby-complex/src/complex.c | 131 | ||||
| -rw-r--r-- | src/gc.c | 13 | ||||
| -rw-r--r-- | src/numeric.c | 111 |
5 files changed, 170 insertions, 104 deletions
diff --git a/mrbgems/mruby-complex/mrbgem.rake b/mrbgems/mruby-complex/mrbgem.rake index 8f782ae18..6c4b629ca 100644 --- a/mrbgems/mruby-complex/mrbgem.rake +++ b/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 diff --git a/mrbgems/mruby-complex/mrblib/complex.rb b/mrbgems/mruby-complex/mrblib/complex.rb index f54151c7b..0b5fc8f73 100644 --- a/mrbgems/mruby-complex/mrblib/complex.rb +++ b/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) diff --git a/mrbgems/mruby-complex/src/complex.c b/mrbgems/mruby-complex/src/complex.c index e4143a762..8960c0573 100644 --- a/mrbgems/mruby-complex/src/complex.c +++ b/mrbgems/mruby-complex/src/complex.c @@ -8,64 +8,58 @@ # 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 @@ -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: diff --git a/src/numeric.c b/src/numeric.c index 3eba71b78..c5c862a37 100644 --- a/src/numeric.c +++ b/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 */ |
