Implements part of Complex class in C.

This commit is contained in:
Yukihiro "Matz" Matsumoto
2019-05-21 16:11:25 +09:00
parent e941cf06a3
commit fccec8964a
3 changed files with 127 additions and 41 deletions
+10 -40
View File
@@ -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)
+116
View File
@@ -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)
{
}
+1 -1
View File
@@ -37,7 +37,7 @@ rational_new(mrb_state *mrb, mrb_int numerator, mrb_int denominator)
struct mrb_rational *p = rational_ptr(rat);
p->numerator = numerator;
p->denominator = denominator;
return mrb_obj_value(s);
return rat;
}
static mrb_value