summaryrefslogtreecommitdiffhomepage
path: root/mrbgems/mruby-complex
diff options
context:
space:
mode:
authorYukihiro "Matz" Matsumoto <[email protected]>2021-03-19 10:30:16 +0900
committerYukihiro "Matz" Matsumoto <[email protected]>2021-03-19 10:37:10 +0900
commitd3184e4a6d8b85a22dd46f4e2909492a0a08cab1 (patch)
treeb45f9be65a970d80d4b60401e44d053f3b78b394 /mrbgems/mruby-complex
parent08f9d5bab5092fe1193dd100765079e3e4d746b9 (diff)
downloadmruby-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.rake2
-rw-r--r--mrbgems/mruby-complex/mrblib/complex.rb17
-rw-r--r--mrbgems/mruby-complex/src/complex.c131
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