summaryrefslogtreecommitdiffhomepage
path: root/mrbgems/mruby-complex
diff options
context:
space:
mode:
authorYukihiro "Matz" Matsumoto <[email protected]>2019-05-21 16:11:25 +0900
committerYukihiro "Matz" Matsumoto <[email protected]>2019-05-21 21:08:26 +0900
commitfccec8964a1b30cef8ff9d97e0e01f3a348e318b (patch)
tree5ab7345ece768da33547e360be58c4bfd6859c81 /mrbgems/mruby-complex
parente941cf06a3e0351107d36d49d540562fdf49f9b4 (diff)
downloadmruby-fccec8964a1b30cef8ff9d97e0e01f3a348e318b.tar.gz
mruby-fccec8964a1b30cef8ff9d97e0e01f3a348e318b.zip
Implements part of `Complex` class in C.
Diffstat (limited to 'mrbgems/mruby-complex')
-rw-r--r--mrbgems/mruby-complex/mrblib/complex.rb50
-rw-r--r--mrbgems/mruby-complex/src/complex.c116
2 files changed, 126 insertions, 40 deletions
diff --git a/mrbgems/mruby-complex/mrblib/complex.rb b/mrbgems/mruby-complex/mrblib/complex.rb
index 8ae743e77..4c0c19c70 100644
--- a/mrbgems/mruby-complex/mrblib/complex.rb
+++ b/mrbgems/mruby-complex/mrblib/complex.rb
@@ -23,43 +23,43 @@ class Complex < Numeric
end
def +@
- Complex(real, imaginary)
+ Complex._new(real, imaginary)
end
def -@
- Complex(-real, -imaginary)
+ Complex._new(-real, -imaginary)
end
def +(rhs)
if rhs.is_a? Complex
- Complex(real + rhs.real, imaginary + rhs.imaginary)
+ Complex._new(real + rhs.real, imaginary + rhs.imaginary)
elsif rhs.is_a? Numeric
- Complex(real + rhs, imaginary)
+ Complex._new(real + rhs, imaginary)
end
end
def -(rhs)
if rhs.is_a? Complex
- Complex(real - rhs.real, imaginary - rhs.imaginary)
+ Complex._new(real - rhs.real, imaginary - rhs.imaginary)
elsif rhs.is_a? Numeric
- Complex(real - rhs, imaginary)
+ Complex._new(real - rhs, imaginary)
end
end
def *(rhs)
if rhs.is_a? Complex
- Complex(real * rhs.real - imaginary * rhs.imaginary, real * rhs.imaginary + rhs.real * imaginary)
+ Complex._new(real * rhs.real - imaginary * rhs.imaginary, real * rhs.imaginary + rhs.real * imaginary)
elsif rhs.is_a? Numeric
- Complex(real * rhs, imaginary * rhs)
+ Complex._new(real * rhs, imaginary * rhs)
end
end
def /(rhs)
if rhs.is_a? Complex
div = rhs.real * rhs.real + rhs.imaginary * rhs.imaginary
- Complex((real * rhs.real + imaginary * rhs.imaginary) / div, (rhs.real * imaginary - real * rhs.imaginary) / div)
+ Complex._new((real * rhs.real + imaginary * rhs.imaginary) / div, (rhs.real * imaginary - real * rhs.imaginary) / div)
elsif rhs.is_a? Numeric
- Complex(real / rhs, imaginary / rhs)
+ Complex._new(real / rhs, imaginary / rhs)
end
end
alias_method :quo, :/
@@ -92,14 +92,6 @@ class Complex < Numeric
end
alias_method :conj, :conjugate
- def numerator
- self
- end
-
- def denominator
- 1
- end
-
def fdiv(numeric)
Complex(real.to_f / numeric, imaginary.to_f / numeric)
end
@@ -117,36 +109,14 @@ class Complex < Numeric
end
alias_method :rect, :rectangular
- def to_c
- self
- end
-
- def to_f
- raise RangeError.new "can't convert #{to_s} into Float" unless imaginary.zero?
- real.to_f
- end
-
- def to_i
- raise RangeError.new "can't convert #{to_s} into Integer" unless imaginary.zero?
- real.to_i
- end
-
def to_r
raise RangeError.new "can't convert #{to_s} into Rational" unless imaginary.zero?
Rational(real, 1)
end
- attr_reader :real, :imaginary
alias_method :imag, :imaginary
end
-class << Complex
- alias_method :_new, :new
- undef_method :new
-
- alias_method :rect, :rectangular
-end
-
module Kernel
def Complex(real, imaginary = 0)
Complex.rectangular(real, imaginary)
diff --git a/mrbgems/mruby-complex/src/complex.c b/mrbgems/mruby-complex/src/complex.c
new file mode 100644
index 000000000..5de0ae9a4
--- /dev/null
+++ b/mrbgems/mruby-complex/src/complex.c
@@ -0,0 +1,116 @@
+#include <mruby.h>
+#include <mruby/class.h>
+#include <mruby/numeric.h>
+
+struct mrb_complex {
+ mrb_float real;
+ mrb_float imaginary;
+};
+
+#include <mruby/data.h>
+
+static const struct mrb_data_type mrb_complex_type = {"Complex", mrb_free};
+
+static mrb_value
+complex_new(mrb_state *mrb, mrb_float real, mrb_float imaginary)
+{
+ struct RClass *c = mrb_class_get(mrb, "Complex");
+ struct mrb_complex *p;
+
+ p = (struct mrb_complex*)mrb_malloc(mrb, sizeof(struct mrb_complex));
+ p->real = real;
+ p->imaginary = imaginary;
+
+ return mrb_obj_value(Data_Wrap_Struct(mrb, c, &mrb_complex_type, p));
+}
+
+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;
+}
+
+static mrb_value
+complex_real(mrb_state *mrb, mrb_value self)
+{
+ struct mrb_complex *p = complex_ptr(mrb, self);
+ return mrb_float_value(mrb, p->real);
+}
+
+static mrb_value
+complex_imaginary(mrb_state *mrb, mrb_value self)
+{
+ struct mrb_complex *p = complex_ptr(mrb, self);
+ return mrb_float_value(mrb, p->imaginary);
+}
+
+static mrb_value
+complex_s_new(mrb_state *mrb, mrb_value self)
+{
+ mrb_float real, imaginary;
+
+ mrb_get_args(mrb, "ff", &real, &imaginary);
+ return complex_new(mrb, real, imaginary);
+}
+
+#ifndef MRB_WITHOUT_FLOAT
+static mrb_value
+complex_to_f(mrb_state *mrb, mrb_value self)
+{
+ struct mrb_complex *p = complex_ptr(mrb, self);
+
+ if (p->imaginary != 0) {
+ mrb_raisef(mrb, E_RANGE_ERROR, "can't convert %S into Float", self);
+ }
+
+ return mrb_float_value(mrb, p->real);
+}
+#endif
+
+static mrb_value
+complex_to_i(mrb_state *mrb, mrb_value self)
+{
+ struct mrb_complex *p = complex_ptr(mrb, self);
+
+ if (p->imaginary != 0) {
+ mrb_raisef(mrb, E_RANGE_ERROR, "can't convert %S into Float", self);
+ }
+ return mrb_int_value(mrb, p->real);
+}
+
+static mrb_value
+complex_to_c(mrb_state *mrb, mrb_value self)
+{
+ return self;
+}
+
+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);
+#endif
+ comp = mrb_define_class(mrb, "Complex", mrb_class_get(mrb, "Numeric"));
+ //MRB_SET_INSTANCE_TT(comp, MRB_TT_ISTRUCT);
+ mrb_undef_class_method(mrb, comp, "new");
+ mrb_define_class_method(mrb, comp, "_new", complex_s_new, MRB_ARGS_REQ(2));
+ mrb_define_method(mrb, comp, "real", complex_real, MRB_ARGS_NONE());
+ mrb_define_method(mrb, comp, "imaginary", complex_imaginary, MRB_ARGS_NONE());
+#ifndef MRB_WITHOUT_FLOAT
+ mrb_define_method(mrb, comp, "to_f", complex_to_f, MRB_ARGS_NONE());
+#endif
+ 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());
+}
+
+void
+mrb_mruby_complex_gem_final(mrb_state* mrb)
+{
+}