diff options
Diffstat (limited to 'mrbgems/mruby-numeric-ext/src')
| -rw-r--r-- | mrbgems/mruby-numeric-ext/src/numeric_ext.c | 79 |
1 files changed, 69 insertions, 10 deletions
diff --git a/mrbgems/mruby-numeric-ext/src/numeric_ext.c b/mrbgems/mruby-numeric-ext/src/numeric_ext.c index dbc7f39d9..2f2a6c755 100644 --- a/mrbgems/mruby-numeric-ext/src/numeric_ext.c +++ b/mrbgems/mruby-numeric-ext/src/numeric_ext.c @@ -1,4 +1,3 @@ -#include <limits.h> #include <mruby.h> #include <mruby/numeric.h> #include <mruby/presym.h> @@ -10,12 +9,12 @@ * Returns +true+ if all bits of <code>+int+ & +mask+</code> are 1. */ static mrb_value -mrb_int_allbits(mrb_state *mrb, mrb_value self) +int_allbits(mrb_state *mrb, mrb_value self) { mrb_int n, m; mrb_get_args(mrb, "i", &m); - n = mrb_int(mrb, self); + n = mrb_integer(self); return mrb_bool_value((n & m) == m); } @@ -26,12 +25,12 @@ mrb_int_allbits(mrb_state *mrb, mrb_value self) * Returns +true+ if any bits of <code>+int+ & +mask+</code> are 1. */ static mrb_value -mrb_int_anybits(mrb_state *mrb, mrb_value self) +int_anybits(mrb_state *mrb, mrb_value self) { mrb_int n, m; mrb_get_args(mrb, "i", &m); - n = mrb_int(mrb, self); + n = mrb_integer(self); return mrb_bool_value((n & m) != 0); } @@ -42,25 +41,85 @@ mrb_int_anybits(mrb_state *mrb, mrb_value self) * Returns +true+ if no bits of <code>+int+ & +mask+</code> are 1. */ static mrb_value -mrb_int_nobits(mrb_state *mrb, mrb_value self) +int_nobits(mrb_state *mrb, mrb_value self) { mrb_int n, m; mrb_get_args(mrb, "i", &m); - n = mrb_int(mrb, self); + n = mrb_integer(self); return mrb_bool_value((n & m) == 0); } +static void +zerodiv(mrb_state *mrb) +{ + mrb_raise(mrb, E_ZERODIV_ERROR, "divided by 0"); +} + +/* + * call-seq: + * num.remainder(numeric) -> real + * + * <code>x.remainder(y)</code> means <code>x-y*(x/y).truncate</code>. + * + * See Numeric#divmod. + */ +static mrb_value +int_remainder(mrb_state *mrb, mrb_value x) +{ + mrb_value y = mrb_get_arg1(mrb); + mrb_int a, b; + + a = mrb_integer(x); + if (mrb_integer_p(y)) { + b = mrb_integer(y); + if (b == 0) zerodiv(mrb); + if (a == MRB_INT_MIN && b == -1) return mrb_fixnum_value(0); + return mrb_int_value(mrb, a % b); + } +#ifdef MRB_NO_FLOAT + mrb_raise(mrb, E_TYPE_ERROR, "non integer remainder"); +#else + mrb_float n = (mrb_float)a; + mrb_float m = mrb_as_float(mrb, y); + + if (isinf(m)) return mrb_float_value(mrb, n); + return mrb_float_value(mrb, n-m*trunc(n/m)); +#endif +} + +#ifndef MRB_NO_FLOAT +static mrb_value +flo_remainder(mrb_state *mrb, mrb_value self) +{ + mrb_float a, b; + + a = mrb_float(self); + mrb_get_args(mrb, "f", &b); + if (b == 0) zerodiv(mrb); + if (isinf(b)) return mrb_float_value(mrb, a); + return mrb_float_value(mrb, a-b*trunc(a/b)); +} +#endif + void mrb_mruby_numeric_ext_gem_init(mrb_state* mrb) { struct RClass *i = mrb_class_get(mrb, "Integer"); - mrb_define_method(mrb, i, "allbits?", mrb_int_allbits, MRB_ARGS_REQ(1)); - mrb_define_method(mrb, i, "anybits?", mrb_int_anybits, MRB_ARGS_REQ(1)); - mrb_define_method(mrb, i, "nobits?", mrb_int_nobits, MRB_ARGS_REQ(1)); + mrb_define_method(mrb, i, "allbits?", int_allbits, MRB_ARGS_REQ(1)); + mrb_define_method(mrb, i, "anybits?", int_anybits, MRB_ARGS_REQ(1)); + mrb_define_method(mrb, i, "nobits?", int_nobits, MRB_ARGS_REQ(1)); + + mrb_define_alias(mrb, i, "modulo", "%"); + mrb_define_method(mrb, i, "remainder", int_remainder, MRB_ARGS_REQ(1)); #ifndef MRB_NO_FLOAT + struct RClass *f = mrb_class_get(mrb, "Float"); + + mrb_define_alias(mrb, f, "modulo", "%"); + mrb_define_method(mrb, f, "remainder", flo_remainder, MRB_ARGS_REQ(1)); + mrb_define_const_id(mrb, mrb->float_class, MRB_SYM(RADIX), mrb_fixnum_value(MRB_FLT_RADIX)); mrb_define_const_id(mrb, mrb->float_class, MRB_SYM(MANT_DIG), mrb_fixnum_value(MRB_FLT_MANT_DIG)); mrb_define_const_id(mrb, mrb->float_class, MRB_SYM(EPSILON), mrb_float_value(mrb, MRB_FLT_EPSILON)); |
