summaryrefslogtreecommitdiffhomepage
path: root/mrbgems/mruby-complex/src/complex.c
blob: 5de0ae9a47d10ba77c52a3cb74169755652ca5d0 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
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)
{
}