mruby/c VM Source Code release 3.4
Loading...
Searching...
No Matches
c_numeric.c
Go to the documentation of this file.
1
13
14
15/***** Feature test switches ************************************************/
16/***** System headers *******************************************************/
17//@cond
18#include "vm_config.h"
19#include <stdio.h>
20#include <limits.h>
21#if MRBC_USE_FLOAT
22#include <math.h>
23#endif
24//@endcond
25
26/***** Local headers ********************************************************/
27#include "mrubyc.h"
28
29/***** Constat values *******************************************************/
30/***** Macros ***************************************************************/
31/***** Typedefs *************************************************************/
32/***** Function prototypes **************************************************/
33/***** Local variables ******************************************************/
34/***** Global variables *****************************************************/
35/***** Signal catching functions ********************************************/
36/***** Local functions ******************************************************/
37
38/***** Integer class ********************************************************/
39//================================================================
42static void c_integer_bitref(struct VM *vm, mrbc_value v[], int argc)
43{
44 if( mrbc_integer(v[1]) < 0 ) {
45 SET_INT_RETURN( 0 );
46 } else {
47 mrbc_int_t mask = (argc == 1) ? 1 : (1 << mrbc_integer(v[2])) - 1;
48 SET_INT_RETURN( (mrbc_integer(v[0]) >> mrbc_integer(v[1])) & mask );
49 }
50}
51
52
53//================================================================
56static void c_integer_positive(struct VM *vm, mrbc_value v[], int argc)
57{
58 // do nothing
59}
60
61
62//================================================================
65static void c_integer_negative(struct VM *vm, mrbc_value v[], int argc)
66{
67 mrbc_int_t num = mrbc_integer(v[0]);
68 SET_INT_RETURN( -num );
69}
70
71
72//================================================================
75static void c_integer_power(struct VM *vm, mrbc_value v[], int argc)
76{
77 if( mrbc_type(v[1]) == MRBC_TT_INTEGER ) {
78 mrbc_int_t x = 1;
79
80 if( mrbc_integer(v[1]) < 0 ) x = 0;
81 for( int i = 0; i < mrbc_integer(v[1]); i++ ) {
82 x *= mrbc_integer(v[0]);
83 }
84 SET_INT_RETURN( x );
85 }
86
87#if MRBC_USE_FLOAT && MRBC_USE_MATH
88 else if( mrbc_type(v[1]) == MRBC_TT_FLOAT ) {
89 SET_FLOAT_RETURN( pow( mrbc_integer(v[0]), mrbc_float(v[1])));
90 }
91#endif
92}
93
94
95//================================================================
98static void c_integer_mod(struct VM *vm, mrbc_value v[], int argc)
99{
100 if( v[1].tt != MRBC_TT_INTEGER ) {
101 mrbc_raise(vm, MRBC_CLASS(TypeError), 0 );
102 return;
103 }
104
105 mrbc_int_t v0 = v[0].i;
106 mrbc_int_t v1 = v[1].i;
107
108 if( v1 == 0 ) {
109 mrbc_raise(vm, MRBC_CLASS(ZeroDivisionError), 0 );
110 return;
111 }
112
113 mrbc_int_t ret = v0 % v1;
114
115 if( (ret != 0) && ((v0 ^ v1) < 0) ) ret += v1;
116 SET_INT_RETURN( ret );
117}
118
119
120//================================================================
123static void c_integer_and(struct VM *vm, mrbc_value v[], int argc)
124{
125 mrbc_int_t num = mrbc_integer(v[1]);
126 SET_INT_RETURN(v->i & num);
127}
128
129
130//================================================================
133static void c_integer_or(struct VM *vm, mrbc_value v[], int argc)
134{
135 mrbc_int_t num = mrbc_integer(v[1]);
136 SET_INT_RETURN(v->i | num);
137}
138
139
140//================================================================
143static void c_integer_xor(struct VM *vm, mrbc_value v[], int argc)
144{
145 mrbc_int_t num = mrbc_integer(v[1]);
146 SET_INT_RETURN( v->i ^ num );
147}
148
149
150//================================================================
153static void c_integer_not(struct VM *vm, mrbc_value v[], int argc)
154{
155 mrbc_int_t num = mrbc_integer(v[0]);
156 SET_INT_RETURN( ~num );
157}
158
159
160//================================================================
164{
165 // Don't support environments that include padding in int.
166 const int INT_BITS = sizeof(mrbc_int_t) * CHAR_BIT;
167
168 if( y >= INT_BITS ) return 0;
169 if( y >= 0 ) return x << y;
170 if( y <= -INT_BITS ) return 0;
171 return x >> -y;
172}
173
174
175//================================================================
178static void c_integer_lshift(struct VM *vm, mrbc_value v[], int argc)
179{
180 int num = mrbc_integer(v[1]);
181 SET_INT_RETURN( shift(v->i, num) );
182}
183
184
185//================================================================
188static void c_integer_rshift(struct VM *vm, mrbc_value v[], int argc)
189{
190 int num = mrbc_integer(v[1]);
191 SET_INT_RETURN( shift(v->i, -num) );
192}
193
194
195//================================================================
198static void c_integer_abs(struct VM *vm, mrbc_value v[], int argc)
199{
200 if( mrbc_integer(v[0]) < 0 ) {
201 mrbc_integer(v[0]) = -mrbc_integer(v[0]);
202 }
203}
204
205
206//================================================================
212static void c_numeric_clamp(struct VM *vm, mrbc_value v[], int argc)
213{
214 if (argc != 2) {
215 mrbc_raise(vm, MRBC_CLASS(ArgumentError), "wrong number of arguments");
216 return;
217 }
218 mrbc_value min = v[1];
219 mrbc_value max = v[2];
220 if (
221 (mrbc_type(min) != MRBC_TT_INTEGER && mrbc_type(min) != MRBC_TT_FLOAT) ||
223 ) {
224 mrbc_raise(vm, MRBC_CLASS(ArgumentError), "comparison failed");
225 return;
226 }
227 if (mrbc_compare(&max, &min) < 0) {
228 mrbc_raise(vm, MRBC_CLASS(ArgumentError), "min argument must be smaller than max argument");
229 return;
230 }
231 if (mrbc_compare(&v[0], &min) < 0) {
232 SET_RETURN(min);
233 return;
234 }
235 if (mrbc_compare(&max, &v[0]) < 0) {
236 SET_RETURN(max);
237 return;
238 }
239 SET_RETURN(v[0]); /* return self */
240}
241
242
243#if MRBC_USE_FLOAT
244//================================================================
247static void c_integer_to_f(struct VM *vm, mrbc_value v[], int argc)
248{
249 mrbc_float_t f = mrbc_integer(v[0]);
250 SET_FLOAT_RETURN( f );
251}
252#endif
253
254
255#if MRBC_USE_STRING
256//================================================================
259static void c_integer_chr(struct VM *vm, mrbc_value v[], int argc)
260{
261 char buf[2] = { mrbc_integer(v[0]) };
262
263 mrbc_value value = mrbc_string_new(vm, buf, 1);
264 SET_RETURN(value);
265}
266
267
268//================================================================
271static void c_integer_inspect(struct VM *vm, mrbc_value v[], int argc)
272{
273 if( v[0].tt == MRBC_TT_CLASS ) {
274 v[0] = mrbc_string_new_cstr(vm, mrbc_symid_to_str( v[0].cls->sym_id ));
275 return;
276 }
277
278 int base = 10;
279 if( argc ) {
280 base = mrbc_integer(v[1]);
281 if( base < 2 || base > 36 ) {
282 mrbc_raisef(vm, MRBC_CLASS(ArgumentError), "invalid radix %d", base);
283 return;
284 }
285 }
286
287 mrbc_printf_t pf;
288 char buf[16];
289 mrbc_printf_init( &pf, buf, sizeof(buf), NULL );
290 pf.fmt.type = 'd';
291 mrbc_printf_int( &pf, v->i, base );
292 mrbc_printf_end( &pf );
293
294 mrbc_value value = mrbc_string_new_cstr(vm, buf);
295 SET_RETURN(value);
296}
297#endif
298
299
300/* MRBC_AUTOGEN_METHOD_TABLE
301
302 CLASS("Integer")
303 FILE("_autogen_class_integer.h")
304
305 METHOD( "[]", c_integer_bitref )
306 METHOD( "+@", c_integer_positive )
307 METHOD( "-@", c_integer_negative )
308 METHOD( "**", c_integer_power )
309 METHOD( "%", c_integer_mod )
310 METHOD( "&", c_integer_and )
311 METHOD( "|", c_integer_or )
312 METHOD( "^", c_integer_xor )
313 METHOD( "~", c_integer_not )
314 METHOD( "<<", c_integer_lshift )
315 METHOD( ">>", c_integer_rshift )
316 METHOD( "abs", c_integer_abs )
317 METHOD( "to_i", c_ineffect )
318 METHOD( "clamp", c_numeric_clamp )
319#if MRBC_USE_FLOAT
320 METHOD( "to_f", c_integer_to_f )
321#endif
322#if MRBC_USE_STRING
323 METHOD( "chr", c_integer_chr )
324 METHOD( "inspect", c_integer_inspect )
325 METHOD( "to_s", c_integer_inspect )
326#endif
327*/
328#include "_autogen_class_integer.h"
329
330
331
332/***** Float class **********************************************************/
333#if MRBC_USE_FLOAT
334
335//================================================================
338static void c_float_positive(struct VM *vm, mrbc_value v[], int argc)
339{
340 // do nothing
341}
342
343
344//================================================================
347static void c_float_negative(struct VM *vm, mrbc_value v[], int argc)
348{
349 mrbc_float_t num = mrbc_float(v[0]);
350 SET_FLOAT_RETURN( -num );
351}
352
353
354#if MRBC_USE_MATH
355//================================================================
358static void c_float_power(struct VM *vm, mrbc_value v[], int argc)
359{
360 mrbc_float_t n = 0;
361 switch( mrbc_type(v[1]) ) {
362 case MRBC_TT_INTEGER: n = mrbc_integer(v[1]); break;
363 case MRBC_TT_FLOAT: n = mrbc_float(v[1]); break;
364 default: break;
365 }
366
367 SET_FLOAT_RETURN( pow( mrbc_float(v[0]), n ));
368}
369#endif
370
371
372//================================================================
375static void c_float_abs(struct VM *vm, mrbc_value v[], int argc)
376{
377 if( mrbc_float(v[0]) < 0 ) {
378 mrbc_float(v[0]) = -mrbc_float(v[0]);
379 }
380}
381
382
383//================================================================
386static void c_float_to_i(struct VM *vm, mrbc_value v[], int argc)
387{
389 SET_INT_RETURN( i );
390}
391
392
393#if MRBC_USE_STRING
394//================================================================
397static void c_float_inspect(struct VM *vm, mrbc_value v[], int argc)
398{
399 if( v[0].tt == MRBC_TT_CLASS ) {
400 v[0] = mrbc_string_new_cstr(vm, mrbc_symid_to_str( v[0].cls->sym_id ));
401 return;
402 }
403
404 char buf[16];
405
406 snprintf( buf, sizeof(buf), "%g", v->d );
407 mrbc_value value = mrbc_string_new_cstr(vm, buf);
408 SET_RETURN(value);
409}
410#endif
411
412
413/* MRBC_AUTOGEN_METHOD_TABLE
414
415 CLASS("Float")
416 FILE("_autogen_class_float.h")
417
418 METHOD( "+@", c_float_positive )
419 METHOD( "-@", c_float_negative )
420#if MRBC_USE_MATH
421 METHOD( "**", c_float_power )
422#endif
423 METHOD( "abs", c_float_abs )
424 METHOD( "to_i", c_float_to_i )
425 METHOD( "to_f", c_ineffect )
426 METHOD( "clamp", c_numeric_clamp )
427#if MRBC_USE_STRING
428 METHOD( "inspect", c_float_inspect )
429 METHOD( "to_s", c_float_inspect )
430#endif
431*/
432#include "_autogen_class_float.h"
433
434#endif // MRBC_USE_FLOAT
static mrbc_int_t shift(mrbc_int_t x, mrbc_int_t y)
Definition c_numeric.c:163
mrbc_value mrbc_string_new(struct VM *vm, const void *src, int len)
Definition c_string.c:62
static mrbc_value mrbc_string_new_cstr(struct VM *vm, const char *src)
Definition c_string.h:85
#define MRBC_CLASS(cls)
Definition class.h:51
int mrbc_printf_int(mrbc_printf_t *pf, mrbc_int_t value, unsigned int base)
Definition console.c:687
static void mrbc_printf_end(mrbc_printf_t *pf)
Definition console.h:144
struct RPrintf mrbc_printf_t
printf tiny (mruby/c) version data container.
static void mrbc_printf_init(mrbc_printf_t *pf, char *buf, int size, const char *fstr)
Definition console.h:118
void mrbc_raise(struct VM *vm, struct RClass *exc_cls, const char *msg)
Definition error.c:150
void mrbc_raisef(struct VM *vm, struct RClass *exc_cls, const char *fstr,...)
Definition error.c:173
Include at once the necessary header files.
mrbc_float_t d
Definition value.h:156
mrbc_int_t i
Definition value.h:154
char type
format char. (e.g. 'd','f','x'...)
Definition console.h:48
struct RPrintfFormat fmt
Definition console.h:67
Virtual Machine.
Definition vm.h:140
const char * mrbc_symid_to_str(mrbc_sym sym_id)
Definition symbol.c:238
int mrbc_compare(const mrbc_value *v1, const mrbc_value *v2)
Definition value.c:66
float mrbc_float_t
Definition value.h:51
int32_t mrbc_int_t
Definition value.h:45
#define SET_INT_RETURN(n)
Definition value.h:283
#define mrbc_type(o)
Definition value.h:193
@ MRBC_TT_FLOAT
Float.
Definition value.h:85
@ MRBC_TT_INTEGER
Integer.
Definition value.h:83
@ MRBC_TT_CLASS
Class.
Definition value.h:87
struct RObject mrbc_value
Definition value.h:174
#define mrbc_float(o)
Definition value.h:195
#define SET_RETURN(n)
Definition value.h:261
#define mrbc_integer(o)
Definition value.h:194
#define SET_FLOAT_RETURN(n)
Definition value.h:289
Global configuration of mruby/c VM's.