Merge pull request #1266 from kimushu/feature/word-boxing
Add MRB_WORD_BOXING mode (represent mrb_value as a word)
Yukihiro "Matz" Matsumoto
10 years ago
24 | 24 | |
25 | 25 | /* define on big endian machines; used by MRB_NAN_BOXING */ |
26 | 26 | //#define MRB_ENDIAN_BIG |
27 | ||
28 | /* represent mrb_value as a word (natural unit of data for the processor) */ | |
29 | // #define MRB_WORD_BOXING | |
27 | 30 | |
28 | 31 | /* argv max size in mrb_funcall */ |
29 | 32 | //#define MRB_FUNCALL_ARGC_MAX 16 |
7 | 7 | #define MRUBY_VALUE_H |
8 | 8 | |
9 | 9 | typedef uint8_t mrb_bool; |
10 | ||
11 | #ifndef MRB_NAN_BOXING | |
10 | struct mrb_state; | |
11 | ||
12 | #if defined(MRB_NAN_BOXING) | |
13 | ||
14 | #ifdef MRB_USE_FLOAT | |
15 | # error ---->> MRB_NAN_BOXING and MRB_USE_FLOAT conflict <<---- | |
16 | #endif | |
17 | ||
18 | enum mrb_vtype { | |
19 | MRB_TT_FALSE = 1, /* 1 */ | |
20 | MRB_TT_FREE, /* 2 */ | |
21 | MRB_TT_TRUE, /* 3 */ | |
22 | MRB_TT_FIXNUM, /* 4 */ | |
23 | MRB_TT_SYMBOL, /* 5 */ | |
24 | MRB_TT_UNDEF, /* 6 */ | |
25 | MRB_TT_FLOAT, /* 7 */ | |
26 | MRB_TT_VOIDP, /* 8 */ | |
27 | MRB_TT_OBJECT, /* 9 */ | |
28 | MRB_TT_CLASS, /* 10 */ | |
29 | MRB_TT_MODULE, /* 11 */ | |
30 | MRB_TT_ICLASS, /* 12 */ | |
31 | MRB_TT_SCLASS, /* 13 */ | |
32 | MRB_TT_PROC, /* 14 */ | |
33 | MRB_TT_ARRAY, /* 15 */ | |
34 | MRB_TT_HASH, /* 16 */ | |
35 | MRB_TT_STRING, /* 17 */ | |
36 | MRB_TT_RANGE, /* 18 */ | |
37 | MRB_TT_EXCEPTION, /* 19 */ | |
38 | MRB_TT_FILE, /* 20 */ | |
39 | MRB_TT_ENV, /* 21 */ | |
40 | MRB_TT_DATA, /* 22 */ | |
41 | MRB_TT_FIBER, /* 23 */ | |
42 | MRB_TT_MAXDEFINE /* 24 */ | |
43 | }; | |
44 | ||
45 | #define MRB_TT_HAS_BASIC MRB_TT_OBJECT | |
46 | ||
47 | #ifdef MRB_ENDIAN_BIG | |
48 | #define MRB_ENDIAN_LOHI(a,b) a b | |
49 | #else | |
50 | #define MRB_ENDIAN_LOHI(a,b) b a | |
51 | #endif | |
52 | ||
53 | typedef struct mrb_value { | |
54 | union { | |
55 | mrb_float f; | |
56 | struct { | |
57 | MRB_ENDIAN_LOHI( | |
58 | uint32_t ttt; | |
59 | ,union { | |
60 | void *p; | |
61 | mrb_int i; | |
62 | mrb_sym sym; | |
63 | } value; | |
64 | ) | |
65 | }; | |
66 | }; | |
67 | } mrb_value; | |
68 | ||
69 | #define mrb_tt(o) ((o).ttt & 0xff) | |
70 | #define mrb_mktt(tt) (0xfff00000|(tt)) | |
71 | #define mrb_type(o) ((uint32_t)0xfff00000 < (o).ttt ? mrb_tt(o) : MRB_TT_FLOAT) | |
72 | #define mrb_float(o) (o).f | |
73 | ||
74 | #define MRB_SET_VALUE(o, tt, attr, v) do {\ | |
75 | (o).ttt = mrb_mktt(tt);\ | |
76 | (o).attr = v;\ | |
77 | } while (0) | |
78 | ||
79 | static inline mrb_value | |
80 | mrb_float_value(struct mrb_state *mrb, mrb_float f) | |
81 | { | |
82 | mrb_value v; | |
83 | ||
84 | if (f != f) { | |
85 | v.ttt = 0x7ff80000; | |
86 | v.value.i = 0; | |
87 | } else { | |
88 | v.f = f; | |
89 | } | |
90 | return v; | |
91 | } | |
92 | ||
93 | #elif defined(MRB_WORD_BOXING) | |
12 | 94 | |
13 | 95 | enum mrb_vtype { |
14 | 96 | MRB_TT_FALSE = 0, /* 0 */ |
37 | 119 | MRB_TT_MAXDEFINE /* 23 */ |
38 | 120 | }; |
39 | 121 | |
122 | #define MRB_TT_HAS_BASIC MRB_TT_FLOAT | |
123 | ||
124 | enum mrb_special_consts { | |
125 | MRB_Qnil = 0, | |
126 | MRB_Qfalse = 2, | |
127 | MRB_Qtrue = 4, | |
128 | MRB_Qundef = 6, | |
129 | ||
130 | MRB_FIXNUM_FLAG = 0x01, | |
131 | MRB_FIXNUM_SHIFT = 1, | |
132 | MRB_SYMBOL_FLAG = 0x0e, | |
133 | MRB_SPECIAL_SHIFT = 8, | |
134 | }; | |
135 | ||
136 | typedef union mrb_value { | |
137 | union { | |
138 | void *p; | |
139 | struct { | |
140 | unsigned int i_flag : MRB_FIXNUM_SHIFT; | |
141 | mrb_int i : (sizeof(mrb_int) * 8 - MRB_FIXNUM_SHIFT); | |
142 | }; | |
143 | struct { | |
144 | unsigned int sym_flag : MRB_SPECIAL_SHIFT; | |
145 | int sym : (sizeof(mrb_sym) * 8); | |
146 | }; | |
147 | struct RBasic *bp; | |
148 | struct RFloat *fp; | |
149 | struct RVoidp *vp; | |
150 | } value; | |
151 | unsigned long w; | |
152 | } mrb_value; | |
153 | ||
154 | #define mrb_float(o) (o).value.fp->f | |
155 | ||
156 | #define MRB_SET_VALUE(o, ttt, attr, v) do {\ | |
157 | (o).w = 0;\ | |
158 | (o).attr = (v);\ | |
159 | switch (ttt) {\ | |
160 | case MRB_TT_FALSE: (o).w = (v) ? MRB_Qfalse : MRB_Qnil; break;\ | |
161 | case MRB_TT_TRUE: (o).w = MRB_Qtrue; break;\ | |
162 | case MRB_TT_UNDEF: (o).w = MRB_Qundef; break;\ | |
163 | case MRB_TT_FIXNUM: (o).value.i_flag = MRB_FIXNUM_FLAG; break;\ | |
164 | case MRB_TT_SYMBOL: (o).value.sym_flag = MRB_SYMBOL_FLAG; break;\ | |
165 | default: if ((o).value.bp) (o).value.bp->tt = ttt; break;\ | |
166 | }\ | |
167 | } while (0) | |
168 | ||
169 | extern mrb_value | |
170 | mrb_float_value(struct mrb_state *mrb, mrb_float f); | |
171 | ||
172 | #else /* No MRB_xxx_BOXING */ | |
173 | ||
174 | enum mrb_vtype { | |
175 | MRB_TT_FALSE = 0, /* 0 */ | |
176 | MRB_TT_FREE, /* 1 */ | |
177 | MRB_TT_TRUE, /* 2 */ | |
178 | MRB_TT_FIXNUM, /* 3 */ | |
179 | MRB_TT_SYMBOL, /* 4 */ | |
180 | MRB_TT_UNDEF, /* 5 */ | |
181 | MRB_TT_FLOAT, /* 6 */ | |
182 | MRB_TT_VOIDP, /* 7 */ | |
183 | MRB_TT_OBJECT, /* 8 */ | |
184 | MRB_TT_CLASS, /* 9 */ | |
185 | MRB_TT_MODULE, /* 10 */ | |
186 | MRB_TT_ICLASS, /* 11 */ | |
187 | MRB_TT_SCLASS, /* 12 */ | |
188 | MRB_TT_PROC, /* 13 */ | |
189 | MRB_TT_ARRAY, /* 14 */ | |
190 | MRB_TT_HASH, /* 15 */ | |
191 | MRB_TT_STRING, /* 16 */ | |
192 | MRB_TT_RANGE, /* 17 */ | |
193 | MRB_TT_EXCEPTION, /* 18 */ | |
194 | MRB_TT_FILE, /* 19 */ | |
195 | MRB_TT_ENV, /* 20 */ | |
196 | MRB_TT_DATA, /* 21 */ | |
197 | MRB_TT_FIBER, /* 22 */ | |
198 | MRB_TT_MAXDEFINE /* 23 */ | |
199 | }; | |
200 | ||
201 | #define MRB_TT_HAS_BASIC MRB_TT_OBJECT | |
202 | ||
40 | 203 | typedef struct mrb_value { |
41 | 204 | union { |
42 | 205 | mrb_float f; |
56 | 219 | } while (0) |
57 | 220 | |
58 | 221 | static inline mrb_value |
59 | mrb_float_value(mrb_float f) | |
222 | mrb_float_value(struct mrb_state *mrb, mrb_float f) | |
60 | 223 | { |
61 | 224 | mrb_value v; |
62 | 225 | |
63 | 226 | MRB_SET_VALUE(v, MRB_TT_FLOAT, value.f, f); |
64 | 227 | return v; |
65 | 228 | } |
66 | #else /* MRB_NAN_BOXING */ | |
67 | ||
68 | #ifdef MRB_USE_FLOAT | |
69 | # error ---->> MRB_NAN_BOXING and MRB_USE_FLOAT conflict <<---- | |
70 | #endif | |
71 | ||
72 | enum mrb_vtype { | |
73 | MRB_TT_FALSE = 1, /* 1 */ | |
74 | MRB_TT_FREE, /* 2 */ | |
75 | MRB_TT_TRUE, /* 3 */ | |
76 | MRB_TT_FIXNUM, /* 4 */ | |
77 | MRB_TT_SYMBOL, /* 5 */ | |
78 | MRB_TT_UNDEF, /* 6 */ | |
79 | MRB_TT_FLOAT, /* 7 */ | |
80 | MRB_TT_VOIDP, /* 8 */ | |
81 | MRB_TT_OBJECT, /* 9 */ | |
82 | MRB_TT_CLASS, /* 10 */ | |
83 | MRB_TT_MODULE, /* 11 */ | |
84 | MRB_TT_ICLASS, /* 12 */ | |
85 | MRB_TT_SCLASS, /* 13 */ | |
86 | MRB_TT_PROC, /* 14 */ | |
87 | MRB_TT_ARRAY, /* 15 */ | |
88 | MRB_TT_HASH, /* 16 */ | |
89 | MRB_TT_STRING, /* 17 */ | |
90 | MRB_TT_RANGE, /* 18 */ | |
91 | MRB_TT_EXCEPTION, /* 19 */ | |
92 | MRB_TT_FILE, /* 20 */ | |
93 | MRB_TT_ENV, /* 21 */ | |
94 | MRB_TT_DATA, /* 22 */ | |
95 | MRB_TT_FIBER, /* 23 */ | |
96 | MRB_TT_MAXDEFINE /* 24 */ | |
97 | }; | |
98 | ||
99 | #ifdef MRB_ENDIAN_BIG | |
100 | #define MRB_ENDIAN_LOHI(a,b) a b | |
229 | #endif /* no boxing */ | |
230 | ||
231 | #ifdef MRB_WORD_BOXING | |
232 | ||
233 | #define mrb_fixnum(o) (o).value.i | |
234 | #define mrb_symbol(o) (o).value.sym | |
235 | #define mrb_voidp(o) (o).value.vp->p | |
236 | #define mrb_fixnum_p(o) ((o).value.i_flag == MRB_FIXNUM_FLAG) | |
237 | #define mrb_float_p(o) (mrb_type(o) == MRB_TT_FLOAT) | |
238 | #define mrb_undef_p(o) ((o).w == MRB_Qundef) | |
239 | #define mrb_nil_p(o) ((o).w == MRB_Qnil) | |
240 | #define mrb_symbol_p(o) ((o).value.sym_flag == MRB_SYMBOL_FLAG) | |
241 | #define mrb_array_p(o) (mrb_type(o) == MRB_TT_ARRAY) | |
242 | #define mrb_string_p(o) (mrb_type(o) == MRB_TT_STRING) | |
243 | #define mrb_hash_p(o) (mrb_type(o) == MRB_TT_HASH) | |
244 | #define mrb_voidp_p(o) (mrb_type(o) == MRB_TT_VOIDP) | |
245 | #define mrb_bool(o) ((o).w != MRB_Qnil && (o).w != MRB_Qfalse) | |
246 | #define mrb_test(o) mrb_bool(o) | |
247 | ||
101 | 248 | #else |
102 | #define MRB_ENDIAN_LOHI(a,b) b a | |
103 | #endif | |
104 | ||
105 | typedef struct mrb_value { | |
106 | union { | |
107 | mrb_float f; | |
108 | struct { | |
109 | MRB_ENDIAN_LOHI( | |
110 | uint32_t ttt; | |
111 | ,union { | |
112 | void *p; | |
113 | mrb_int i; | |
114 | mrb_sym sym; | |
115 | } value; | |
116 | ) | |
117 | }; | |
118 | }; | |
119 | } mrb_value; | |
120 | ||
121 | #define mrb_tt(o) ((o).ttt & 0xff) | |
122 | #define mrb_mktt(tt) (0xfff00000|(tt)) | |
123 | #define mrb_type(o) ((uint32_t)0xfff00000 < (o).ttt ? mrb_tt(o) : MRB_TT_FLOAT) | |
124 | #define mrb_float(o) (o).f | |
125 | ||
126 | #define MRB_SET_VALUE(o, tt, attr, v) do {\ | |
127 | (o).ttt = mrb_mktt(tt);\ | |
128 | (o).attr = v;\ | |
129 | } while (0) | |
130 | ||
131 | static inline mrb_value | |
132 | mrb_float_value(mrb_float f) | |
133 | { | |
134 | mrb_value v; | |
135 | ||
136 | if (f != f) { | |
137 | v.ttt = 0x7ff80000; | |
138 | v.value.i = 0; | |
139 | } else { | |
140 | v.f = f; | |
141 | } | |
142 | return v; | |
143 | } | |
144 | #endif /* MRB_NAN_BOXING */ | |
145 | 249 | |
146 | 250 | #define mrb_fixnum(o) (o).value.i |
147 | 251 | #define mrb_symbol(o) (o).value.sym |
158 | 262 | #define mrb_bool(o) (mrb_type(o) != MRB_TT_FALSE) |
159 | 263 | #define mrb_test(o) mrb_bool(o) |
160 | 264 | |
265 | #endif /* no boxing */ | |
266 | ||
161 | 267 | #define MRB_OBJECT_HEADER \ |
162 | 268 | enum mrb_vtype tt:8;\ |
163 | 269 | uint32_t color:3;\ |
208 | 314 | struct mrb_context *cxt; |
209 | 315 | }; |
210 | 316 | |
317 | #ifdef MRB_WORD_BOXING | |
318 | struct RFloat { | |
319 | MRB_OBJECT_HEADER; | |
320 | mrb_float f; | |
321 | }; | |
322 | ||
323 | struct RVoidp { | |
324 | MRB_OBJECT_HEADER; | |
325 | void *p; | |
326 | }; | |
327 | ||
328 | static inline enum mrb_vtype | |
329 | mrb_type(mrb_value o) | |
330 | { | |
331 | switch (o.w) { | |
332 | case MRB_Qfalse: | |
333 | case MRB_Qnil: | |
334 | return MRB_TT_FALSE; | |
335 | case MRB_Qtrue: | |
336 | return MRB_TT_TRUE; | |
337 | case MRB_Qundef: | |
338 | return MRB_TT_UNDEF; | |
339 | } | |
340 | if (o.value.i_flag == MRB_FIXNUM_FLAG) { | |
341 | return MRB_TT_FIXNUM; | |
342 | } | |
343 | if (o.value.sym_flag == MRB_SYMBOL_FLAG) { | |
344 | return MRB_TT_SYMBOL; | |
345 | } | |
346 | return o.value.bp->tt; | |
347 | } | |
348 | #endif /* MRB_WORD_BOXING */ | |
349 | ||
211 | 350 | static inline mrb_value |
212 | 351 | mrb_fixnum_value(mrb_int i) |
213 | 352 | { |
236 | 375 | return v; |
237 | 376 | } |
238 | 377 | |
239 | static inline mrb_value | |
240 | mrb_voidp_value(void *p) | |
378 | #ifdef MRB_WORD_BOXING | |
379 | mrb_value | |
380 | mrb_voidp_value(struct mrb_state *mrb, void *p); | |
381 | #else | |
382 | static inline mrb_value | |
383 | mrb_voidp_value(struct mrb_state *mrb, void *p) | |
241 | 384 | { |
242 | 385 | mrb_value v; |
243 | 386 | |
244 | 387 | MRB_SET_VALUE(v, MRB_TT_VOIDP, value.p, p); |
245 | 388 | return v; |
246 | 389 | } |
390 | #endif | |
247 | 391 | |
248 | 392 | static inline mrb_value |
249 | 393 | mrb_false_value(void) |
272 | 272 | void mrb_gc_arena_restore(mrb_state*,int); |
273 | 273 | void mrb_gc_mark(mrb_state*,struct RBasic*); |
274 | 274 | #define mrb_gc_mark_value(mrb,val) do {\ |
275 | if (mrb_type(val) >= MRB_TT_OBJECT) mrb_gc_mark((mrb), mrb_basic_ptr(val));\ | |
275 | if (mrb_type(val) >= MRB_TT_HAS_BASIC) mrb_gc_mark((mrb), mrb_basic_ptr(val));\ | |
276 | 276 | } while (0) |
277 | 277 | void mrb_field_write_barrier(mrb_state *, struct RBasic*, struct RBasic*); |
278 | 278 | #define mrb_field_write_barrier_value(mrb, obj, val) do{\ |
279 | if ((val.tt >= MRB_TT_OBJECT)) mrb_field_write_barrier((mrb), (obj), mrb_basic_ptr(val));\ | |
279 | if ((val.tt >= MRB_TT_HAS_BASIC)) mrb_field_write_barrier((mrb), (obj), mrb_basic_ptr(val));\ | |
280 | 280 | } while (0) |
281 | 281 | void mrb_write_barrier(mrb_state *, struct RBasic*); |
282 | 282 |
107 | 107 | mrb_get_args(mrb, "f", &x); |
108 | 108 | x = sin(x); |
109 | 109 | |
110 | return mrb_float_value(x); | |
110 | return mrb_float_value(mrb, x); | |
111 | 111 | } |
112 | 112 | |
113 | 113 | /* |
125 | 125 | mrb_get_args(mrb, "f", &x); |
126 | 126 | x = cos(x); |
127 | 127 | |
128 | return mrb_float_value(x); | |
128 | return mrb_float_value(mrb, x); | |
129 | 129 | } |
130 | 130 | |
131 | 131 | /* |
142 | 142 | mrb_get_args(mrb, "f", &x); |
143 | 143 | x = tan(x); |
144 | 144 | |
145 | return mrb_float_value(x); | |
145 | return mrb_float_value(mrb, x); | |
146 | 146 | } |
147 | 147 | |
148 | 148 | /* |
163 | 163 | mrb_get_args(mrb, "f", &x); |
164 | 164 | x = asin(x); |
165 | 165 | |
166 | return mrb_float_value(x); | |
166 | return mrb_float_value(mrb, x); | |
167 | 167 | } |
168 | 168 | |
169 | 169 | /* |
180 | 180 | mrb_get_args(mrb, "f", &x); |
181 | 181 | x = acos(x); |
182 | 182 | |
183 | return mrb_float_value(x); | |
183 | return mrb_float_value(mrb, x); | |
184 | 184 | } |
185 | 185 | |
186 | 186 | /* |
197 | 197 | mrb_get_args(mrb, "f", &x); |
198 | 198 | x = atan(x); |
199 | 199 | |
200 | return mrb_float_value(x); | |
200 | return mrb_float_value(mrb, x); | |
201 | 201 | } |
202 | 202 | |
203 | 203 | /* |
227 | 227 | mrb_get_args(mrb, "ff", &x, &y); |
228 | 228 | x = atan2(x, y); |
229 | 229 | |
230 | return mrb_float_value(x); | |
230 | return mrb_float_value(mrb, x); | |
231 | 231 | } |
232 | 232 | |
233 | 233 | |
250 | 250 | mrb_get_args(mrb, "f", &x); |
251 | 251 | x = sinh(x); |
252 | 252 | |
253 | return mrb_float_value(x); | |
253 | return mrb_float_value(mrb, x); | |
254 | 254 | } |
255 | 255 | |
256 | 256 | /* |
267 | 267 | mrb_get_args(mrb, "f", &x); |
268 | 268 | x = cosh(x); |
269 | 269 | |
270 | return mrb_float_value(x); | |
270 | return mrb_float_value(mrb, x); | |
271 | 271 | } |
272 | 272 | |
273 | 273 | /* |
285 | 285 | mrb_get_args(mrb, "f", &x); |
286 | 286 | x = tanh(x); |
287 | 287 | |
288 | return mrb_float_value(x); | |
288 | return mrb_float_value(mrb, x); | |
289 | 289 | } |
290 | 290 | |
291 | 291 | |
308 | 308 | |
309 | 309 | x = asinh(x); |
310 | 310 | |
311 | return mrb_float_value(x); | |
311 | return mrb_float_value(mrb, x); | |
312 | 312 | } |
313 | 313 | |
314 | 314 | /* |
325 | 325 | mrb_get_args(mrb, "f", &x); |
326 | 326 | x = acosh(x); |
327 | 327 | |
328 | return mrb_float_value(x); | |
328 | return mrb_float_value(mrb, x); | |
329 | 329 | } |
330 | 330 | |
331 | 331 | /* |
342 | 342 | mrb_get_args(mrb, "f", &x); |
343 | 343 | x = atanh(x); |
344 | 344 | |
345 | return mrb_float_value(x); | |
345 | return mrb_float_value(mrb, x); | |
346 | 346 | } |
347 | 347 | |
348 | 348 | /* |
388 | 388 | mrb_get_args(mrb, "f", &x); |
389 | 389 | x = exp(x); |
390 | 390 | |
391 | return mrb_float_value(x); | |
391 | return mrb_float_value(mrb, x); | |
392 | 392 | } |
393 | 393 | |
394 | 394 | /* |
417 | 417 | if (argc == 2) { |
418 | 418 | x /= log(base); |
419 | 419 | } |
420 | return mrb_float_value(x); | |
420 | return mrb_float_value(mrb, x); | |
421 | 421 | } |
422 | 422 | |
423 | 423 | /* |
440 | 440 | mrb_get_args(mrb, "f", &x); |
441 | 441 | x = log2(x); |
442 | 442 | |
443 | return mrb_float_value(x); | |
443 | return mrb_float_value(mrb, x); | |
444 | 444 | } |
445 | 445 | |
446 | 446 | /* |
462 | 462 | mrb_get_args(mrb, "f", &x); |
463 | 463 | x = log10(x); |
464 | 464 | |
465 | return mrb_float_value(x); | |
465 | return mrb_float_value(mrb, x); | |
466 | 466 | } |
467 | 467 | |
468 | 468 | /* |
480 | 480 | mrb_get_args(mrb, "f", &x); |
481 | 481 | x = sqrt(x); |
482 | 482 | |
483 | return mrb_float_value(x); | |
483 | return mrb_float_value(mrb, x); | |
484 | 484 | } |
485 | 485 | |
486 | 486 | |
523 | 523 | mrb_get_args(mrb, "f", &x); |
524 | 524 | x = cbrt(x); |
525 | 525 | |
526 | return mrb_float_value(x); | |
526 | return mrb_float_value(mrb, x); | |
527 | 527 | } |
528 | 528 | |
529 | 529 | |
547 | 547 | mrb_get_args(mrb, "f", &x); |
548 | 548 | x = frexp(x, &exp); |
549 | 549 | |
550 | return mrb_assoc_new(mrb, mrb_float_value(x), mrb_fixnum_value(exp)); | |
550 | return mrb_assoc_new(mrb, mrb_float_value(mrb, x), mrb_fixnum_value(exp)); | |
551 | 551 | } |
552 | 552 | |
553 | 553 | /* |
568 | 568 | mrb_get_args(mrb, "fi", &x, &i); |
569 | 569 | x = ldexp(x, i); |
570 | 570 | |
571 | return mrb_float_value(x); | |
571 | return mrb_float_value(mrb, x); | |
572 | 572 | } |
573 | 573 | |
574 | 574 | /* |
588 | 588 | mrb_get_args(mrb, "ff", &x, &y); |
589 | 589 | x = hypot(x, y); |
590 | 590 | |
591 | return mrb_float_value(x); | |
591 | return mrb_float_value(mrb, x); | |
592 | 592 | } |
593 | 593 | |
594 | 594 | /* |
605 | 605 | mrb_get_args(mrb, "f", &x); |
606 | 606 | x = erf(x); |
607 | 607 | |
608 | return mrb_float_value(x); | |
608 | return mrb_float_value(mrb, x); | |
609 | 609 | } |
610 | 610 | |
611 | 611 | |
623 | 623 | mrb_get_args(mrb, "f", &x); |
624 | 624 | x = erfc(x); |
625 | 625 | |
626 | return mrb_float_value(x); | |
626 | return mrb_float_value(mrb, x); | |
627 | 627 | } |
628 | 628 | |
629 | 629 | /* ------------------------------------------------------------------------*/ |
634 | 634 | mrb_math = mrb_define_module(mrb, "Math"); |
635 | 635 | |
636 | 636 | #ifdef M_PI |
637 | mrb_define_const(mrb, mrb_math, "PI", mrb_float_value(M_PI)); | |
637 | mrb_define_const(mrb, mrb_math, "PI", mrb_float_value(mrb, M_PI)); | |
638 | 638 | #else |
639 | mrb_define_const(mrb, mrb_math, "PI", mrb_float_value(atan(1.0)*4.0)); | |
639 | mrb_define_const(mrb, mrb_math, "PI", mrb_float_value(mrb, atan(1.0)*4.0)); | |
640 | 640 | #endif |
641 | 641 | |
642 | 642 | #ifdef M_E |
643 | mrb_define_const(mrb, mrb_math, "E", mrb_float_value(M_E)); | |
643 | mrb_define_const(mrb, mrb_math, "E", mrb_float_value(mrb, M_E)); | |
644 | 644 | #else |
645 | mrb_define_const(mrb, mrb_math, "E", mrb_float_value(exp(1.0))); | |
645 | mrb_define_const(mrb, mrb_math, "E", mrb_float_value(mrb, exp(1.0))); | |
646 | 646 | #endif |
647 | 647 | |
648 | 648 | #ifdef MRB_USE_FLOAT |
649 | mrb_define_const(mrb, mrb_math, "TOLERANCE", mrb_float_value(1e-5)); | |
649 | mrb_define_const(mrb, mrb_math, "TOLERANCE", mrb_float_value(mrb, 1e-5)); | |
650 | 650 | #else |
651 | mrb_define_const(mrb, mrb_math, "TOLERANCE", mrb_float_value(1e-12)); | |
651 | mrb_define_const(mrb, mrb_math, "TOLERANCE", mrb_float_value(mrb, 1e-12)); | |
652 | 652 | #endif |
653 | 653 | |
654 | 654 | mrb_define_module_function(mrb, mrb_math, "sin", math_sin, MRB_ARGS_REQ(1)); |
65 | 65 | mrb_value value; |
66 | 66 | |
67 | 67 | if (mrb_fixnum(max) == 0) { |
68 | value = mrb_float_value(mt_g_rand_real()); | |
68 | value = mrb_float_value(mrb, mt_g_rand_real()); | |
69 | 69 | } else { |
70 | 70 | value = mrb_fixnum_value(mt_g_rand() % mrb_fixnum(max)); |
71 | 71 | } |
107 | 107 | mrb_value value; |
108 | 108 | |
109 | 109 | if (mrb_fixnum(max) == 0) { |
110 | value = mrb_float_value(mt_rand_real(t)); | |
110 | value = mrb_float_value(mrb, mt_rand_real(t)); | |
111 | 111 | } else { |
112 | 112 | value = mrb_fixnum_value(mt_rand(t) % mrb_fixnum(max)); |
113 | 113 | } |
357 | 357 | if (tm2) { |
358 | 358 | f = (mrb_float)(tm->sec - tm2->sec) |
359 | 359 | + (mrb_float)(tm->usec - tm2->usec) / 1.0e6; |
360 | return mrb_float_value(f); | |
360 | return mrb_float_value(mrb, f); | |
361 | 361 | } |
362 | 362 | else { |
363 | 363 | mrb_get_args(mrb, "f", &f); |
627 | 627 | |
628 | 628 | tm = (struct mrb_time*)mrb_data_get_ptr(mrb, self, &mrb_time_type); |
629 | 629 | if (!tm) return mrb_nil_value(); |
630 | return mrb_float_value((mrb_float)tm->sec + (mrb_float)tm->usec/1.0e6); | |
630 | return mrb_float_value(mrb, (mrb_float)tm->sec + (mrb_float)tm->usec/1.0e6); | |
631 | 631 | } |
632 | 632 | |
633 | 633 | /* 15.2.19.7.25 */ |
1900 | 1900 | i = readint_mrb_int(s, p, base, FALSE, &overflow); |
1901 | 1901 | if (overflow) { |
1902 | 1902 | double f = readint_float(s, p, base); |
1903 | int off = new_lit(s, mrb_float_value(f)); | |
1903 | int off = new_lit(s, mrb_float_value(s->mrb, f)); | |
1904 | 1904 | |
1905 | 1905 | genop(s, MKOP_ABx(OP_LOADL, cursp(), off)); |
1906 | 1906 | } |
1922 | 1922 | if (val) { |
1923 | 1923 | char *p = (char*)tree; |
1924 | 1924 | mrb_float f = str_to_mrb_float(p); |
1925 | int off = new_lit(s, mrb_float_value(f)); | |
1925 | int off = new_lit(s, mrb_float_value(s->mrb, f)); | |
1926 | 1926 | |
1927 | 1927 | genop(s, MKOP_ABx(OP_LOADL, cursp(), off)); |
1928 | 1928 | push(); |
1938 | 1938 | { |
1939 | 1939 | char *p = (char*)tree; |
1940 | 1940 | mrb_float f = str_to_mrb_float(p); |
1941 | int off = new_lit(s, mrb_float_value(-f)); | |
1941 | int off = new_lit(s, mrb_float_value(s->mrb, -f)); | |
1942 | 1942 | |
1943 | 1943 | genop(s, MKOP_ABx(OP_LOADL, cursp(), off)); |
1944 | 1944 | push(); |
1956 | 1956 | i = readint_mrb_int(s, p, base, TRUE, &overflow); |
1957 | 1957 | if (overflow) { |
1958 | 1958 | double f = readint_float(s, p, base); |
1959 | int off = new_lit(s, mrb_float_value(-f)); | |
1959 | int off = new_lit(s, mrb_float_value(s->mrb, -f)); | |
1960 | 1960 | |
1961 | 1961 | genop(s, MKOP_ABx(OP_LOADL, cursp(), off)); |
1962 | 1962 | } |
179 | 179 | } |
180 | 180 | } |
181 | 181 | |
182 | #ifdef MRB_WORD_BOXING | |
183 | mrb_value | |
184 | mrb_float_value(mrb_state *mrb, mrb_float f) | |
185 | { | |
186 | mrb_value v; | |
187 | ||
188 | v.value.p = mrb_obj_alloc(mrb, MRB_TT_FLOAT, mrb->float_class); | |
189 | v.value.fp->f = f; | |
190 | return v; | |
191 | } | |
192 | ||
193 | mrb_value | |
194 | mrb_voidp_value(mrb_state *mrb, void *p) | |
195 | { | |
196 | mrb_value v; | |
197 | ||
198 | v.value.p = mrb_obj_alloc(mrb, MRB_TT_VOIDP, mrb->object_class); | |
199 | v.value.vp->p = p; | |
200 | return v; | |
201 | } | |
202 | #endif /* MRB_WORD_BOXING */ | |
203 |
529 | 529 | case MRB_TT_TRUE: |
530 | 530 | case MRB_TT_FIXNUM: |
531 | 531 | case MRB_TT_SYMBOL: |
532 | case MRB_TT_FLOAT: | |
533 | 532 | /* cannot happen */ |
534 | 533 | return; |
534 | ||
535 | case MRB_TT_FLOAT: | |
536 | #ifdef MRB_WORD_BOXING | |
537 | break; | |
538 | #else | |
539 | return; | |
540 | #endif | |
535 | 541 | |
536 | 542 | case MRB_TT_OBJECT: |
537 | 543 | mrb_gc_free_iv(mrb, (struct RObject*)obj); |
893 | 893 | /* fall through */ |
894 | 894 | default: |
895 | 895 | exc = mrb_make_exception(mrb, argc, a); |
896 | mrb_obj_iv_set(mrb, mrb_obj_ptr(exc), mrb_intern2(mrb, "lastpc", 6), mrb_voidp_value(mrb->c->ci->pc)); | |
896 | mrb_obj_iv_set(mrb, mrb_obj_ptr(exc), mrb_intern2(mrb, "lastpc", 6), mrb_voidp_value(mrb, mrb->c->ci->pc)); | |
897 | 897 | mrb_exc_raise(mrb, exc); |
898 | 898 | break; |
899 | 899 | } |
129 | 129 | break; |
130 | 130 | |
131 | 131 | case MRB_TT_FLOAT: |
132 | irep->pool[i] = mrb_float_value(mrb_str_to_dbl(mrb, s, FALSE)); | |
132 | irep->pool[i] = mrb_float_value(mrb, mrb_str_to_dbl(mrb, s, FALSE)); | |
133 | 133 | break; |
134 | 134 | |
135 | 135 | case MRB_TT_STRING: |
64 | 64 | static mrb_value |
65 | 65 | num_uminus(mrb_state *mrb, mrb_value num) |
66 | 66 | { |
67 | return mrb_float_value((mrb_float)0 - mrb_to_flo(mrb, num)); | |
67 | return mrb_float_value(mrb, (mrb_float)0 - mrb_to_flo(mrb, num)); | |
68 | 68 | } |
69 | 69 | |
70 | 70 | static mrb_value |
94 | 94 | d = pow(mrb_to_flo(mrb, x), mrb_to_flo(mrb, y)); |
95 | 95 | if (both_int && FIXABLE(d)) |
96 | 96 | return mrb_fixnum_value((mrb_int)d); |
97 | return mrb_float_value(d); | |
97 | return mrb_float_value(mrb, d); | |
98 | 98 | } |
99 | 99 | |
100 | 100 | /* 15.2.8.3.4 */ |
111 | 111 | mrb_value |
112 | 112 | mrb_num_div(mrb_state *mrb, mrb_value x, mrb_value y) |
113 | 113 | { |
114 | return mrb_float_value(mrb_to_flo(mrb, x) / mrb_to_flo(mrb, y)); | |
114 | return mrb_float_value(mrb, mrb_to_flo(mrb, x) / mrb_to_flo(mrb, y)); | |
115 | 115 | } |
116 | 116 | |
117 | 117 | /* 15.2.9.3.19(x) */ |
128 | 128 | mrb_float y; |
129 | 129 | |
130 | 130 | mrb_get_args(mrb, "f", &y); |
131 | return mrb_float_value(mrb_to_flo(mrb, x) / y); | |
131 | return mrb_float_value(mrb, mrb_to_flo(mrb, x) / y); | |
132 | 132 | } |
133 | 133 | |
134 | 134 | /* |
296 | 296 | mrb_value y; |
297 | 297 | |
298 | 298 | mrb_get_args(mrb, "o", &y); |
299 | return mrb_float_value(mrb_float(x) - mrb_to_flo(mrb, y)); | |
299 | return mrb_float_value(mrb, mrb_float(x) - mrb_to_flo(mrb, y)); | |
300 | 300 | } |
301 | 301 | |
302 | 302 | /* 15.2.9.3.3 */ |
314 | 314 | mrb_value y; |
315 | 315 | |
316 | 316 | mrb_get_args(mrb, "o", &y); |
317 | return mrb_float_value(mrb_float(x) * mrb_to_flo(mrb, y)); | |
317 | return mrb_float_value(mrb, mrb_float(x) * mrb_to_flo(mrb, y)); | |
318 | 318 | } |
319 | 319 | |
320 | 320 | static void |
365 | 365 | |
366 | 366 | fy = mrb_to_flo(mrb, y); |
367 | 367 | flodivmod(mrb, mrb_float(x), fy, 0, &mod); |
368 | return mrb_float_value(mod); | |
368 | return mrb_float_value(mrb, mod); | |
369 | 369 | } |
370 | 370 | |
371 | 371 | /* 15.2.8.3.16 */ |
544 | 544 | mrb_float f = floor(mrb_float(num)); |
545 | 545 | |
546 | 546 | if (!FIXABLE(f)) { |
547 | return mrb_float_value(f); | |
547 | return mrb_float_value(mrb, f); | |
548 | 548 | } |
549 | 549 | return mrb_fixnum_value((mrb_int)f); |
550 | 550 | } |
569 | 569 | mrb_float f = ceil(mrb_float(num)); |
570 | 570 | |
571 | 571 | if (!FIXABLE(f)) { |
572 | return mrb_float_value(f); | |
572 | return mrb_float_value(mrb, f); | |
573 | 573 | } |
574 | 574 | return mrb_fixnum_value((mrb_int)f); |
575 | 575 | } |
641 | 641 | if (ndigits < 0) number *= f; |
642 | 642 | else number /= f; |
643 | 643 | } |
644 | if (ndigits > 0) return mrb_float_value(number); | |
644 | if (ndigits > 0) return mrb_float_value(mrb, number); | |
645 | 645 | return mrb_fixnum_value((mrb_int)number); |
646 | 646 | } |
647 | 647 | |
665 | 665 | if (f < 0.0) f = ceil(f); |
666 | 666 | |
667 | 667 | if (!FIXABLE(f)) { |
668 | return mrb_float_value(f); | |
668 | return mrb_float_value(mrb, f); | |
669 | 669 | } |
670 | 670 | return mrb_fixnum_value((mrb_int)f); |
671 | 671 | } |
749 | 749 | return mrb_fixnum_value(a*b); |
750 | 750 | c = a * b; |
751 | 751 | if (a != 0 && c/a != b) { |
752 | return mrb_float_value((mrb_float)a*(mrb_float)b); | |
752 | return mrb_float_value(mrb, (mrb_float)a*(mrb_float)b); | |
753 | 753 | } |
754 | 754 | return mrb_fixnum_value(c);; |
755 | 755 | } |
756 | return mrb_float_value((mrb_float)a * mrb_to_flo(mrb, y)); | |
756 | return mrb_float_value(mrb, (mrb_float)a * mrb_to_flo(mrb, y)); | |
757 | 757 | } |
758 | 758 | |
759 | 759 | /* 15.2.8.3.3 */ |
825 | 825 | mrb_int mod; |
826 | 826 | |
827 | 827 | if (mrb_fixnum(y) == 0) { |
828 | return mrb_float_value(str_to_mrb_float("nan")); | |
828 | return mrb_float_value(mrb, str_to_mrb_float("nan")); | |
829 | 829 | } |
830 | 830 | fixdivmod(mrb, a, mrb_fixnum(y), 0, &mod); |
831 | 831 | return mrb_fixnum_value(mod); |
834 | 834 | mrb_float mod; |
835 | 835 | |
836 | 836 | flodivmod(mrb, (mrb_float)a, mrb_to_flo(mrb, y), 0, &mod); |
837 | return mrb_float_value(mod); | |
837 | return mrb_float_value(mrb, mod); | |
838 | 838 | } |
839 | 839 | } |
840 | 840 | |
855 | 855 | mrb_int div, mod; |
856 | 856 | |
857 | 857 | if (mrb_fixnum(y) == 0) { |
858 | return mrb_assoc_new(mrb, mrb_float_value(str_to_mrb_float("inf")), | |
859 | mrb_float_value(str_to_mrb_float("nan"))); | |
858 | return mrb_assoc_new(mrb, mrb_float_value(mrb, str_to_mrb_float("inf")), | |
859 | mrb_float_value(mrb, str_to_mrb_float("nan"))); | |
860 | 860 | } |
861 | 861 | fixdivmod(mrb, mrb_fixnum(x), mrb_fixnum(y), &div, &mod); |
862 | 862 | return mrb_assoc_new(mrb, mrb_fixnum_value(div), mrb_fixnum_value(mod)); |
866 | 866 | mrb_value a, b; |
867 | 867 | |
868 | 868 | flodivmod(mrb, (mrb_float)mrb_fixnum(x), mrb_to_flo(mrb, y), &div, &mod); |
869 | a = mrb_float_value((mrb_int)div); | |
870 | b = mrb_float_value(mod); | |
869 | a = mrb_float_value(mrb, (mrb_int)div); | |
870 | b = mrb_float_value(mrb, mod); | |
871 | 871 | return mrb_assoc_new(mrb, a, b); |
872 | 872 | } |
873 | 873 | } |
1120 | 1120 | |
1121 | 1121 | val = (mrb_float)mrb_fixnum(num); |
1122 | 1122 | |
1123 | return mrb_float_value(val); | |
1123 | return mrb_float_value(mrb, val); | |
1124 | 1124 | } |
1125 | 1125 | |
1126 | 1126 | /* |
1174 | 1174 | c = a + b; |
1175 | 1175 | if (((a < 0) ^ (b < 0)) == 0 && (a < 0) != (c < 0)) { |
1176 | 1176 | /* integer overflow */ |
1177 | return mrb_float_value((mrb_float)a + (mrb_float)b); | |
1177 | return mrb_float_value(mrb, (mrb_float)a + (mrb_float)b); | |
1178 | 1178 | } |
1179 | 1179 | return mrb_fixnum_value(c); |
1180 | 1180 | } |
1181 | return mrb_float_value((mrb_float)a + mrb_to_flo(mrb, y)); | |
1181 | return mrb_float_value(mrb, (mrb_float)a + mrb_to_flo(mrb, y)); | |
1182 | 1182 | } |
1183 | 1183 | |
1184 | 1184 | /* 15.2.8.3.1 */ |
1212 | 1212 | c = a - b; |
1213 | 1213 | if (((a < 0) ^ (b < 0)) != 0 && (a < 0) != (c < 0)) { |
1214 | 1214 | /* integer overflow */ |
1215 | return mrb_float_value((mrb_float)a - (mrb_float)b); | |
1215 | return mrb_float_value(mrb, (mrb_float)a - (mrb_float)b); | |
1216 | 1216 | } |
1217 | 1217 | return mrb_fixnum_value(c); |
1218 | 1218 | } |
1219 | return mrb_float_value((mrb_float)a - mrb_to_flo(mrb, y)); | |
1219 | return mrb_float_value(mrb, (mrb_float)a - mrb_to_flo(mrb, y)); | |
1220 | 1220 | } |
1221 | 1221 | |
1222 | 1222 | /* 15.2.8.3.2 */ |
1346 | 1346 | x = mrb_float(self); |
1347 | 1347 | mrb_get_args(mrb, "f", &y); |
1348 | 1348 | |
1349 | return mrb_float_value(x + y); | |
1349 | return mrb_float_value(mrb, x + y); | |
1350 | 1350 | } |
1351 | 1351 | /* ------------------------------------------------------------------------*/ |
1352 | 1352 | void |
570 | 570 | } |
571 | 571 | switch (mrb_type(val)) { |
572 | 572 | case MRB_TT_FIXNUM: |
573 | return mrb_float_value((mrb_float)mrb_fixnum(val)); | |
573 | return mrb_float_value(mrb, (mrb_float)mrb_fixnum(val)); | |
574 | 574 | |
575 | 575 | case MRB_TT_FLOAT: |
576 | 576 | return val; |
577 | 577 | |
578 | 578 | case MRB_TT_STRING: |
579 | return mrb_float_value(mrb_str_to_dbl(mrb, val, TRUE)); | |
579 | return mrb_float_value(mrb, mrb_str_to_dbl(mrb, val, TRUE)); | |
580 | 580 | |
581 | 581 | default: |
582 | 582 | return mrb_convert_type(mrb, val, MRB_TT_FLOAT, "Float", "to_f"); |
2221 | 2221 | static mrb_value |
2222 | 2222 | mrb_str_to_f(mrb_state *mrb, mrb_value self) |
2223 | 2223 | { |
2224 | return mrb_float_value(mrb_str_to_dbl(mrb, self, 0/*Qfalse*/)); | |
2224 | return mrb_float_value(mrb, mrb_str_to_dbl(mrb, self, 0/*Qfalse*/)); | |
2225 | 2225 | } |
2226 | 2226 | |
2227 | 2227 | /* 15.2.10.5.40 */ |
38 | 38 | #define SET_SYM_VALUE(r,v) MRB_SET_VALUE(r, MRB_TT_SYMBOL, value.sym, (v)) |
39 | 39 | #define SET_OBJ_VALUE(r,v) MRB_SET_VALUE(r, (((struct RObject*)(v))->tt), value.p, (v)) |
40 | 40 | #ifdef MRB_NAN_BOXING |
41 | #define SET_FLT_VALUE(r,v) r.f = (v) | |
41 | #define SET_FLT_VALUE(mrb,r,v) r.f = (v) | |
42 | #elif defined(MRB_WORD_BOXING) | |
43 | #define SET_FLT_VALUE(mrb,r,v) r = mrb_float_value(mrb, (v)) | |
42 | 44 | #else |
43 | #define SET_FLT_VALUE(r,v) MRB_SET_VALUE(r, MRB_TT_FLOAT, value.f, (v)) | |
45 | #define SET_FLT_VALUE(mrb,r,v) MRB_SET_VALUE(r, MRB_TT_FLOAT, value.f, (v)) | |
44 | 46 | #endif |
45 | 47 | |
46 | 48 | #define STACK_INIT_SIZE 128 |
1242 | 1244 | |
1243 | 1245 | L_RAISE: |
1244 | 1246 | ci = mrb->c->ci; |
1245 | mrb_obj_iv_ifnone(mrb, mrb->exc, mrb_intern2(mrb, "lastpc", 6), mrb_voidp_value(pc)); | |
1247 | mrb_obj_iv_ifnone(mrb, mrb->exc, mrb_intern2(mrb, "lastpc", 6), mrb_voidp_value(mrb, pc)); | |
1246 | 1248 | mrb_obj_iv_ifnone(mrb, mrb->exc, mrb_intern2(mrb, "ciidx", 5), mrb_fixnum_value(ci - mrb->c->cibase)); |
1247 | 1249 | eidx = ci->eidx; |
1248 | 1250 | if (ci == mrb->c->cibase) { |
1440 | 1442 | #define attr_i value.i |
1441 | 1443 | #ifdef MRB_NAN_BOXING |
1442 | 1444 | #define attr_f f |
1445 | #elif defined(MRB_WORD_BOXING) | |
1446 | #define attr_f value.fp->f | |
1443 | 1447 | #else |
1444 | 1448 | #define attr_f value.f |
1445 | 1449 | #endif |
1463 | 1467 | x = mrb_fixnum(regs_a[0]); |
1464 | 1468 | y = mrb_fixnum(regs_a[1]); |
1465 | 1469 | z = x + y; |
1470 | #ifdef MRB_WORD_BOXING | |
1471 | z = (z << MRB_FIXNUM_SHIFT) / (1 << MRB_FIXNUM_SHIFT); | |
1472 | #endif | |
1466 | 1473 | if ((x < 0) != (z < 0) && ((x < 0) ^ (y < 0)) == 0) { |
1467 | 1474 | /* integer overflow */ |
1468 | SET_FLT_VALUE(regs_a[0], (mrb_float)x + (mrb_float)y); | |
1475 | SET_FLT_VALUE(mrb, regs_a[0], (mrb_float)x + (mrb_float)y); | |
1476 | break; | |
1469 | 1477 | } |
1470 | else { | |
1471 | regs_a[0].attr_i = z; | |
1472 | } | |
1478 | SET_INT_VALUE(regs[a], z); | |
1473 | 1479 | } |
1474 | 1480 | break; |
1475 | 1481 | case TYPES2(MRB_TT_FIXNUM,MRB_TT_FLOAT): |
1476 | 1482 | { |
1477 | 1483 | mrb_int x = mrb_fixnum(regs[a]); |
1478 | 1484 | mrb_float y = mrb_float(regs[a+1]); |
1479 | SET_FLT_VALUE(regs[a], (mrb_float)x + y); | |
1485 | SET_FLT_VALUE(mrb, regs[a], (mrb_float)x + y); | |
1480 | 1486 | } |
1481 | 1487 | break; |
1482 | 1488 | case TYPES2(MRB_TT_FLOAT,MRB_TT_FIXNUM): |
1489 | #ifdef MRB_WORD_BOXING | |
1490 | { | |
1491 | mrb_float x = mrb_float(regs[a]); | |
1492 | mrb_int y = mrb_fixnum(regs[a+1]); | |
1493 | SET_FLT_VALUE(mrb, regs[a], x + y); | |
1494 | } | |
1495 | #else | |
1483 | 1496 | OP_MATH_BODY(+,attr_f,attr_i); |
1497 | #endif | |
1484 | 1498 | break; |
1485 | 1499 | case TYPES2(MRB_TT_FLOAT,MRB_TT_FLOAT): |
1500 | #ifdef MRB_WORD_BOXING | |
1501 | { | |
1502 | mrb_float x = mrb_float(regs[a]); | |
1503 | mrb_float y = mrb_float(regs[a+1]); | |
1504 | SET_FLT_VALUE(mrb, regs[a], x + y); | |
1505 | } | |
1506 | #else | |
1486 | 1507 | OP_MATH_BODY(+,attr_f,attr_f); |
1508 | #endif | |
1487 | 1509 | break; |
1488 | 1510 | case TYPES2(MRB_TT_STRING,MRB_TT_STRING): |
1489 | 1511 | regs[a] = mrb_str_plus(mrb, regs[a], regs[a+1]); |
1508 | 1530 | x = mrb_fixnum(regs[a]); |
1509 | 1531 | y = mrb_fixnum(regs[a+1]); |
1510 | 1532 | z = x - y; |
1533 | #ifdef MRB_WORD_BOXING | |
1534 | z = (z << MRB_FIXNUM_SHIFT) / (1 << MRB_FIXNUM_SHIFT); | |
1535 | #endif | |
1511 | 1536 | if (((x < 0) ^ (y < 0)) != 0 && (x < 0) != (z < 0)) { |
1512 | 1537 | /* integer overflow */ |
1513 | SET_FLT_VALUE(regs[a], (mrb_float)x - (mrb_float)y); | |
1538 | SET_FLT_VALUE(mrb, regs[a], (mrb_float)x - (mrb_float)y); | |
1514 | 1539 | break; |
1515 | 1540 | } |
1516 | 1541 | SET_INT_VALUE(regs[a], z); |
1520 | 1545 | { |
1521 | 1546 | mrb_int x = mrb_fixnum(regs[a]); |
1522 | 1547 | mrb_float y = mrb_float(regs[a+1]); |
1523 | SET_FLT_VALUE(regs[a], (mrb_float)x - y); | |
1548 | SET_FLT_VALUE(mrb, regs[a], (mrb_float)x - y); | |
1524 | 1549 | } |
1525 | 1550 | break; |
1526 | 1551 | case TYPES2(MRB_TT_FLOAT,MRB_TT_FIXNUM): |
1552 | #ifdef MRB_WORD_BOXING | |
1553 | { | |
1554 | mrb_float x = mrb_float(regs[a]); | |
1555 | mrb_int y = mrb_fixnum(regs[a+1]); | |
1556 | SET_FLT_VALUE(mrb, regs[a], x - y); | |
1557 | } | |
1558 | #else | |
1527 | 1559 | OP_MATH_BODY(-,attr_f,attr_i); |
1560 | #endif | |
1528 | 1561 | break; |
1529 | 1562 | case TYPES2(MRB_TT_FLOAT,MRB_TT_FLOAT): |
1563 | #ifdef MRB_WORD_BOXING | |
1564 | { | |
1565 | mrb_float x = mrb_float(regs[a]); | |
1566 | mrb_float y = mrb_float(regs[a+1]); | |
1567 | SET_FLT_VALUE(mrb, regs[a], x - y); | |
1568 | } | |
1569 | #else | |
1530 | 1570 | OP_MATH_BODY(-,attr_f,attr_f); |
1571 | #endif | |
1531 | 1572 | break; |
1532 | 1573 | default: |
1533 | 1574 | goto L_SEND; |
1548 | 1589 | x = mrb_fixnum(regs[a]); |
1549 | 1590 | y = mrb_fixnum(regs[a+1]); |
1550 | 1591 | z = x * y; |
1592 | #ifdef MRB_WORD_BOXING | |
1593 | z = (z << MRB_FIXNUM_SHIFT) / (1 << MRB_FIXNUM_SHIFT); | |
1594 | #endif | |
1551 | 1595 | if (x != 0 && z/x != y) { |
1552 | SET_FLT_VALUE(regs[a], (mrb_float)x * (mrb_float)y); | |
1596 | SET_FLT_VALUE(mrb, regs[a], (mrb_float)x * (mrb_float)y); | |
1553 | 1597 | } |
1554 | 1598 | else { |
1555 | 1599 | SET_INT_VALUE(regs[a], z); |
1560 | 1604 | { |
1561 | 1605 | mrb_int x = mrb_fixnum(regs[a]); |
1562 | 1606 | mrb_float y = mrb_float(regs[a+1]); |
1563 | SET_FLT_VALUE(regs[a], (mrb_float)x * y); | |
1607 | SET_FLT_VALUE(mrb, regs[a], (mrb_float)x * y); | |
1564 | 1608 | } |
1565 | 1609 | break; |
1566 | 1610 | case TYPES2(MRB_TT_FLOAT,MRB_TT_FIXNUM): |
1611 | #ifdef MRB_WORD_BOXING | |
1612 | { | |
1613 | mrb_float x = mrb_float(regs[a]); | |
1614 | mrb_int y = mrb_fixnum(regs[a+1]); | |
1615 | SET_FLT_VALUE(mrb, regs[a], x * y); | |
1616 | } | |
1617 | #else | |
1567 | 1618 | OP_MATH_BODY(*,attr_f,attr_i); |
1619 | #endif | |
1568 | 1620 | break; |
1569 | 1621 | case TYPES2(MRB_TT_FLOAT,MRB_TT_FLOAT): |
1622 | #ifdef MRB_WORD_BOXING | |
1623 | { | |
1624 | mrb_float x = mrb_float(regs[a]); | |
1625 | mrb_float y = mrb_float(regs[a+1]); | |
1626 | SET_FLT_VALUE(mrb, regs[a], x * y); | |
1627 | } | |
1628 | #else | |
1570 | 1629 | OP_MATH_BODY(*,attr_f,attr_f); |
1630 | #endif | |
1571 | 1631 | break; |
1572 | 1632 | default: |
1573 | 1633 | goto L_SEND; |
1585 | 1645 | { |
1586 | 1646 | mrb_int x = mrb_fixnum(regs[a]); |
1587 | 1647 | mrb_int y = mrb_fixnum(regs[a+1]); |
1588 | SET_FLT_VALUE(regs[a], (mrb_float)x / (mrb_float)y); | |
1648 | SET_FLT_VALUE(mrb, regs[a], (mrb_float)x / (mrb_float)y); | |
1589 | 1649 | } |
1590 | 1650 | break; |
1591 | 1651 | case TYPES2(MRB_TT_FIXNUM,MRB_TT_FLOAT): |
1592 | 1652 | { |
1593 | 1653 | mrb_int x = mrb_fixnum(regs[a]); |
1594 | 1654 | mrb_float y = mrb_float(regs[a+1]); |
1595 | SET_FLT_VALUE(regs[a], (mrb_float)x / y); | |
1655 | SET_FLT_VALUE(mrb, regs[a], (mrb_float)x / y); | |
1596 | 1656 | } |
1597 | 1657 | break; |
1598 | 1658 | case TYPES2(MRB_TT_FLOAT,MRB_TT_FIXNUM): |
1659 | #ifdef MRB_WORD_BOXING | |
1660 | { | |
1661 | mrb_float x = mrb_float(regs[a]); | |
1662 | mrb_int y = mrb_fixnum(regs[a+1]); | |
1663 | SET_FLT_VALUE(mrb, regs[a], x / y); | |
1664 | } | |
1665 | #else | |
1599 | 1666 | OP_MATH_BODY(/,attr_f,attr_i); |
1667 | #endif | |
1600 | 1668 | break; |
1601 | 1669 | case TYPES2(MRB_TT_FLOAT,MRB_TT_FLOAT): |
1670 | #ifdef MRB_WORD_BOXING | |
1671 | { | |
1672 | mrb_float x = mrb_float(regs[a]); | |
1673 | mrb_float y = mrb_float(regs[a+1]); | |
1674 | SET_FLT_VALUE(mrb, regs[a], x / y); | |
1675 | } | |
1676 | #else | |
1602 | 1677 | OP_MATH_BODY(/,attr_f,attr_f); |
1678 | #endif | |
1603 | 1679 | break; |
1604 | 1680 | default: |
1605 | 1681 | goto L_SEND; |
1621 | 1697 | |
1622 | 1698 | if (((x < 0) ^ (y < 0)) == 0 && (x < 0) != (z < 0)) { |
1623 | 1699 | /* integer overflow */ |
1624 | SET_FLT_VALUE(regs[a], (mrb_float)x + (mrb_float)y); | |
1700 | SET_FLT_VALUE(mrb, regs[a], (mrb_float)x + (mrb_float)y); | |
1625 | 1701 | break; |
1626 | 1702 | } |
1627 | 1703 | regs[a].attr_i = z; |
1628 | 1704 | } |
1629 | 1705 | break; |
1630 | 1706 | case MRB_TT_FLOAT: |
1707 | #ifdef MRB_WORD_BOXING | |
1708 | { | |
1709 | mrb_float x = mrb_float(regs[a]); | |
1710 | SET_FLT_VALUE(mrb, regs[a], x + GETARG_C(i)); | |
1711 | } | |
1712 | #else | |
1631 | 1713 | regs[a].attr_f += GETARG_C(i); |
1714 | #endif | |
1632 | 1715 | break; |
1633 | 1716 | default: |
1634 | 1717 | SET_INT_VALUE(regs[a+1], GETARG_C(i)); |
1653 | 1736 | |
1654 | 1737 | if ((x < 0) != (z < 0) && ((x < 0) ^ (y < 0)) != 0) { |
1655 | 1738 | /* integer overflow */ |
1656 | SET_FLT_VALUE(regs_a[0], (mrb_float)x - (mrb_float)y); | |
1739 | SET_FLT_VALUE(mrb, regs_a[0], (mrb_float)x - (mrb_float)y); | |
1657 | 1740 | } |
1658 | 1741 | else { |
1659 | 1742 | regs_a[0].attr_i = z; |
1661 | 1744 | } |
1662 | 1745 | break; |
1663 | 1746 | case MRB_TT_FLOAT: |
1747 | #ifdef MRB_WORD_BOXING | |
1748 | { | |
1749 | mrb_float x = mrb_float(regs[a]); | |
1750 | SET_FLT_VALUE(mrb, regs[a], x - GETARG_C(i)); | |
1751 | } | |
1752 | #else | |
1664 | 1753 | regs_a[0].attr_f -= GETARG_C(i); |
1754 | #endif | |
1665 | 1755 | break; |
1666 | 1756 | default: |
1667 | 1757 | SET_INT_VALUE(regs_a[1], GETARG_C(i)); |