source: EcnlProtoTool/trunk/mruby-2.1.1/mrbgems/mruby-rational/src/rational.c@ 439

Last change on this file since 439 was 439, checked in by coas-nagasima, 4 years ago

mrubyを2.1.1に更新

  • Property svn:eol-style set to native
  • Property svn:mime-type set to text/x-csrc;charset=UTF-8
File size: 5.0 KB
Line 
1#include <mruby.h>
2#include <mruby/class.h>
3#include <mruby/string.h>
4#include <mruby/numeric.h>
5
6struct mrb_rational {
7 mrb_int numerator;
8 mrb_int denominator;
9};
10
11#if MRB_INT_MAX <= INTPTR_MAX
12
13#define RATIONAL_USE_ISTRUCT
14/* use TT_ISTRUCT */
15#include <mruby/istruct.h>
16
17#define rational_ptr(mrb, v) (struct mrb_rational*)mrb_istruct_ptr(v)
18
19static struct RBasic*
20rational_alloc(mrb_state *mrb, struct RClass *c, struct mrb_rational **p)
21{
22 struct RIStruct *s;
23
24 s = (struct RIStruct*)mrb_obj_alloc(mrb, MRB_TT_ISTRUCT, c);
25 *p = (struct mrb_rational*)s->inline_data;
26
27 return (struct RBasic*)s;
28}
29
30#else
31/* use TT_DATA */
32#include <mruby/data.h>
33
34static const struct mrb_data_type mrb_rational_type = {"Rational", mrb_free};
35
36static struct RBasic*
37rational_alloc(mrb_state *mrb, struct RClass *c, struct mrb_rational **p)
38{
39 struct RData *d;
40
41 Data_Make_Struct(mrb, c, struct mrb_rational, &mrb_rational_type, *p, d);
42
43 return (struct RBasic*)d;
44}
45
46static struct mrb_rational*
47rational_ptr(mrb_state *mrb, mrb_value v)
48{
49 struct mrb_rational *p;
50
51 p = DATA_GET_PTR(mrb, v, &mrb_rational_type, struct mrb_rational);
52 if (!p) {
53 mrb_raise(mrb, E_ARGUMENT_ERROR, "uninitialized rational");
54 }
55 return p;
56}
57#endif
58
59static mrb_value
60rational_numerator(mrb_state *mrb, mrb_value self)
61{
62 struct mrb_rational *p = rational_ptr(mrb, self);
63 return mrb_fixnum_value(p->numerator);
64}
65
66static mrb_value
67rational_denominator(mrb_state *mrb, mrb_value self)
68{
69 struct mrb_rational *p = rational_ptr(mrb, self);
70 return mrb_fixnum_value(p->denominator);
71}
72
73static mrb_value
74rational_new(mrb_state *mrb, mrb_int numerator, mrb_int denominator)
75{
76 struct RClass *c = mrb_class_get(mrb, "Rational");
77 struct mrb_rational *p;
78 struct RBasic *rat = rational_alloc(mrb, c, &p);
79 p->numerator = numerator;
80 p->denominator = denominator;
81 MRB_SET_FROZEN_FLAG(rat);
82 return mrb_obj_value(rat);
83}
84
85static mrb_value
86rational_s_new(mrb_state *mrb, mrb_value self)
87{
88 mrb_int numerator, denominator;
89
90#ifdef MRB_WITHOUT_FLOAT
91 mrb_get_args(mrb, "ii", &numerator, &denominator);
92#else
93
94#define DROP_PRECISION(cond, num, denom) \
95 do { \
96 while (cond) { \
97 num /= 2; \
98 denom /= 2; \
99 } \
100 } while (0)
101
102 mrb_value numv, denomv;
103
104 mrb_get_args(mrb, "oo", &numv, &denomv);
105 if (mrb_fixnum_p(numv)) {
106 numerator = mrb_fixnum(numv);
107
108 if (mrb_fixnum_p(denomv)) {
109 denominator = mrb_fixnum(denomv);
110 }
111 else {
112 mrb_float denomf = mrb_to_flo(mrb, denomv);
113
114 DROP_PRECISION(denomf < MRB_INT_MIN || denomf > MRB_INT_MAX, numerator, denomf);
115 denominator = denomf;
116 }
117 }
118 else {
119 mrb_float numf = mrb_to_flo(mrb, numv);
120
121 if (mrb_fixnum_p(denomv)) {
122 denominator = mrb_fixnum(denomv);
123 }
124 else {
125 mrb_float denomf = mrb_to_flo(mrb, denomv);
126
127 DROP_PRECISION(denomf < MRB_INT_MIN || denomf > MRB_INT_MAX, numf, denomf);
128 denominator = denomf;
129 }
130
131 DROP_PRECISION(numf < MRB_INT_MIN || numf > MRB_INT_MAX, numf, denominator);
132 numerator = numf;
133 }
134#endif
135
136 return rational_new(mrb, numerator, denominator);
137}
138
139#ifndef MRB_WITHOUT_FLOAT
140static mrb_value
141rational_to_f(mrb_state *mrb, mrb_value self)
142{
143 struct mrb_rational *p = rational_ptr(mrb, self);
144 mrb_float f = (mrb_float)p->numerator / (mrb_float)p->denominator;
145
146 return mrb_float_value(mrb, f);
147}
148#endif
149
150static mrb_value
151rational_to_i(mrb_state *mrb, mrb_value self)
152{
153 struct mrb_rational *p = rational_ptr(mrb, self);
154 if (p->denominator == 0) {
155 mrb_raise(mrb, mrb_exc_get(mrb, "StandardError"), "divided by 0");
156 }
157 return mrb_fixnum_value(p->numerator / p->denominator);
158}
159
160static mrb_value
161rational_to_r(mrb_state *mrb, mrb_value self)
162{
163 return self;
164}
165
166static mrb_value
167rational_negative_p(mrb_state *mrb, mrb_value self)
168{
169 struct mrb_rational *p = rational_ptr(mrb, self);
170 if (p->numerator < 0) {
171 return mrb_true_value();
172 }
173 return mrb_false_value();
174}
175
176static mrb_value
177fix_to_r(mrb_state *mrb, mrb_value self)
178{
179 return rational_new(mrb, mrb_fixnum(self), 1);
180}
181
182void mrb_mruby_rational_gem_init(mrb_state *mrb)
183{
184 struct RClass *rat;
185
186 rat = mrb_define_class(mrb, "Rational", mrb_class_get(mrb, "Numeric"));
187#ifdef RATIONAL_USE_ISTRUCT
188 MRB_SET_INSTANCE_TT(rat, MRB_TT_ISTRUCT);
189 mrb_assert(sizeof(struct mrb_rational) < ISTRUCT_DATA_SIZE);
190#else
191 MRB_SET_INSTANCE_TT(rat, MRB_TT_DATA);
192#endif
193 mrb_undef_class_method(mrb, rat, "new");
194 mrb_define_class_method(mrb, rat, "_new", rational_s_new, MRB_ARGS_REQ(2));
195 mrb_define_method(mrb, rat, "numerator", rational_numerator, MRB_ARGS_NONE());
196 mrb_define_method(mrb, rat, "denominator", rational_denominator, MRB_ARGS_NONE());
197#ifndef MRB_WITHOUT_FLOAT
198 mrb_define_method(mrb, rat, "to_f", rational_to_f, MRB_ARGS_NONE());
199#endif
200 mrb_define_method(mrb, rat, "to_i", rational_to_i, MRB_ARGS_NONE());
201 mrb_define_method(mrb, rat, "to_r", rational_to_r, MRB_ARGS_NONE());
202 mrb_define_method(mrb, rat, "negative?", rational_negative_p, MRB_ARGS_NONE());
203 mrb_define_method(mrb, mrb->fixnum_class, "to_r", fix_to_r, MRB_ARGS_NONE());
204}
205
206void
207mrb_mruby_rational_gem_final(mrb_state* mrb)
208{
209}
Note: See TracBrowser for help on using the repository browser.