diff options
| author | Yukihiro "Matz" Matsumoto <[email protected]> | 2021-03-19 10:30:16 +0900 |
|---|---|---|
| committer | Yukihiro "Matz" Matsumoto <[email protected]> | 2021-03-19 10:37:10 +0900 |
| commit | d3184e4a6d8b85a22dd46f4e2909492a0a08cab1 (patch) | |
| tree | b45f9be65a970d80d4b60401e44d053f3b78b394 /mrbgems/mruby-complex | |
| parent | 08f9d5bab5092fe1193dd100765079e3e4d746b9 (diff) | |
| download | mruby-d3184e4a6d8b85a22dd46f4e2909492a0a08cab1.tar.gz mruby-d3184e4a6d8b85a22dd46f4e2909492a0a08cab1.zip | |
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
Diffstat (limited to 'mrbgems/mruby-complex')
| -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 |
3 files changed, 88 insertions, 62 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 |
