2 ** numeric.c - Numeric, Integer, Float, Fixnum class
4 ** See Copyright Notice in mruby.h
7 #ifndef MRB_WITHOUT_FLOAT
16 #include <mruby/array.h>
17 #include <mruby/numeric.h>
18 #include <mruby/string.h>
19 #include <mruby/class.h>
21 #ifndef MRB_WITHOUT_FLOAT
23 #define trunc(f) truncf(f)
24 #define floor(f) floorf(f)
25 #define ceil(f) ceilf(f)
26 #define fmod(x,y) fmodf(x,y)
27 #define FLO_TO_STR_PREC 8
29 #define FLO_TO_STR_PREC 16
33 #ifndef MRB_WITHOUT_FLOAT
35 mrb_to_flo(mrb_state *mrb, mrb_value val)
37 switch (mrb_type(val)) {
39 return (mrb_float)mrb_fixnum(val);
43 mrb_raise(mrb, E_TYPE_ERROR, "non float value");
45 return mrb_float(val);
49 mrb_int_value(mrb_state *mrb, mrb_float f)
51 if (FIXABLE_FLOAT(f)) {
52 return mrb_fixnum_value((mrb_int)f);
54 return mrb_float_value(mrb, f);
63 * Raises <code>num</code> the <code>other</code> power.
68 integral_pow(mrb_state *mrb, mrb_value x)
70 mrb_value y = mrb_get_arg1(mrb);
71 #ifndef MRB_WITHOUT_FLOAT
75 if (mrb_fixnum_p(x) && mrb_fixnum_p(y)) {
77 mrb_int base = mrb_fixnum(x);
78 mrb_int exp = mrb_fixnum(y);
82 #ifdef MRB_WITHOUT_FLOAT
83 return mrb_fixnum_value(0);
89 if (mrb_int_mul_overflow(result, base, &result)) {
90 #ifndef MRB_WITHOUT_FLOAT
97 if (mrb_int_mul_overflow(base, base, &base)) {
98 #ifndef MRB_WITHOUT_FLOAT
103 return mrb_fixnum_value(result);
105 #ifdef MRB_WITHOUT_FLOAT
106 mrb_raise(mrb, E_TYPE_ERROR, "non fixnum value");
109 d = pow(mrb_to_flo(mrb, x), mrb_to_flo(mrb, y));
110 return mrb_float_value(mrb, d);
115 integral_idiv(mrb_state *mrb, mrb_value x)
117 #ifdef MRB_WITHOUT_FLOAT
118 mrb_value y = mrb_get_arg1(mrb);
120 if (!mrb_fixnum_p(y)) {
121 mrb_raise(mrb, E_TYPE_ERROR, "non fixnum value");
123 return mrb_fixnum_value(mrb_fixnum(x) / mrb_fixnum(y));
127 mrb_get_args(mrb, "f", &y);
128 return mrb_int_value(mrb, mrb_to_flo(mrb, x) / y);
138 * Performs division: the class of the resulting object depends on
139 * the class of <code>num</code> and on the magnitude of the
146 * num.quo(numeric) -> real
148 * Returns most exact division.
152 integral_div(mrb_state *mrb, mrb_value x)
154 #ifdef MRB_WITHOUT_FLOAT
155 mrb_value y = mrb_get_arg1(mrb);
157 if (!mrb_fixnum_p(y)) {
158 mrb_raise(mrb, E_TYPE_ERROR, "non fixnum value");
160 return mrb_fixnum_value(mrb_fixnum(x) / mrb_fixnum(y));
164 mrb_get_args(mrb, "f", &y);
165 return mrb_float_value(mrb, mrb_to_flo(mrb, x) / y);
170 integral_coerce_step_counter(mrb_state *mrb, mrb_value self)
174 mrb_get_args(mrb, "oo", &num, &step);
176 #ifndef MRB_WITHOUT_FLOAT
177 if (mrb_float_p(self) || mrb_float_p(num) || mrb_float_p(step)) {
178 return mrb_Float(mrb, self);
185 #ifndef MRB_WITHOUT_FLOAT
186 /********************************************************************
188 * Document-class: Float
190 * <code>Float</code> objects represent inexact real numbers using
191 * the native architecture's double-precision floating point
200 * Returns a string containing a representation of self. As well as a
201 * fixed or exponential form of the number, the call may return
202 * "<code>NaN</code>", "<code>Infinity</code>", and
203 * "<code>-Infinity</code>".
207 flo_to_s(mrb_state *mrb, mrb_value flt)
209 mrb_float f = mrb_float(flt);
213 str = f < 0 ? mrb_str_new_lit(mrb, "-Infinity")
214 : mrb_str_new_lit(mrb, "Infinity");
218 str = mrb_str_new_lit(mrb, "NaN");
222 char fmt[] = "%." MRB_STRINGIZE(FLO_TO_STR_PREC) "g";
224 char *begp, *p, *endp;
226 str = mrb_float_to_str(mrb, flt, fmt);
229 begp = RSTRING_PTR(str);
230 len = RSTRING_LEN(str);
231 for (p = begp, endp = p + len; p < endp; ++p) {
235 else if (*p == 'e') {
236 ptrdiff_t e_pos = p - begp;
237 mrb_str_cat(mrb, str, ".0", 2);
238 p = RSTRING_PTR(str) + e_pos;
239 memmove(p + 2, p, len - e_pos);
245 if (FLO_TO_STR_PREC + (begp[0] == '-') <= len) {
246 --fmt[sizeof(fmt) - 3]; /* %.16g(%.8g) -> %.15g(%.7g) */
247 str = mrb_float_to_str(mrb, flt, fmt);
248 goto insert_dot_zero;
255 RSTR_SET_ASCII_FLAG(mrb_str_ptr(str));
262 * float - other -> float
264 * Returns a new float which is the difference of <code>float</code>
265 * and <code>other</code>.
269 flo_minus(mrb_state *mrb, mrb_value x)
271 mrb_value y = mrb_get_arg1(mrb);
273 return mrb_float_value(mrb, mrb_float(x) - mrb_to_flo(mrb, y));
279 * float * other -> float
281 * Returns a new float which is the product of <code>float</code>
282 * and <code>other</code>.
286 flo_mul(mrb_state *mrb, mrb_value x)
288 mrb_value y = mrb_get_arg1(mrb);
290 return mrb_float_value(mrb, mrb_float(x) * mrb_to_flo(mrb, y));
294 flodivmod(mrb_state *mrb, double x, double y, mrb_float *divp, mrb_float *modp)
299 /* y is NaN so all results are NaN */
304 if (x == 0) div = NAN;
305 else if (x > 0.0) div = INFINITY;
306 else div = -INFINITY; /* x < 0.0 */
310 if ((x == 0.0) || (isinf(y) && !isinf(x))) {
316 if (isinf(x) && !isinf(y)) {
321 if (modp && divp) div = round(div);
323 if (div == 0) div = 0.0;
324 if (mod == 0) mod = 0.0;
330 if (modp) *modp = mod;
331 if (divp) *divp = div;
337 * flt % other -> float
338 * flt.modulo(other) -> float
340 * Return the modulo after division of <code>flt</code> by <code>other</code>.
342 * 6543.21.modulo(137) #=> 104.21
343 * 6543.21.modulo(137.24) #=> 92.9299999999996
347 flo_mod(mrb_state *mrb, mrb_value x)
349 mrb_value y = mrb_get_arg1(mrb);
352 flodivmod(mrb, mrb_float(x), mrb_to_flo(mrb, y), 0, &mod);
353 return mrb_float_value(mrb, mod);
360 * num.eql?(numeric) -> true or false
362 * Returns <code>true</code> if <i>num</i> and <i>numeric</i> are the
363 * same type and have equal values.
366 * 1.eql?(1.0) #=> false
367 * (1.0).eql?(1.0) #=> true
370 fix_eql(mrb_state *mrb, mrb_value x)
372 mrb_value y = mrb_get_arg1(mrb);
374 if (!mrb_fixnum_p(y)) return mrb_false_value();
375 return mrb_bool_value(mrb_fixnum(x) == mrb_fixnum(y));
378 #ifndef MRB_WITHOUT_FLOAT
380 flo_eql(mrb_state *mrb, mrb_value x)
382 mrb_value y = mrb_get_arg1(mrb);
384 if (!mrb_float_p(y)) return mrb_false_value();
385 return mrb_bool_value(mrb_float(x) == mrb_float(y));
391 * flt == obj -> true or false
393 * Returns <code>true</code> only if <i>obj</i> has the same value
394 * as <i>flt</i>. Contrast this with <code>Float#eql?</code>, which
395 * requires <i>obj</i> to be a <code>Float</code>.
402 flo_eq(mrb_state *mrb, mrb_value x)
404 mrb_value y = mrb_get_arg1(mrb);
406 switch (mrb_type(y)) {
408 return mrb_bool_value(mrb_float(x) == (mrb_float)mrb_fixnum(y));
410 return mrb_bool_value(mrb_float(x) == mrb_float(y));
412 return mrb_false_value();
417 value_int64(mrb_state *mrb, mrb_value x)
419 switch (mrb_type(x)) {
421 return (int64_t)mrb_fixnum(x);
423 return (int64_t)mrb_float(x);
425 mrb_raise(mrb, E_TYPE_ERROR, "cannot convert to Integer");
433 int64_value(mrb_state *mrb, int64_t v)
435 if (TYPED_FIXABLE(v,int64_t)) {
436 return mrb_fixnum_value((mrb_int)v);
438 return mrb_float_value(mrb, (mrb_float)v);
442 flo_rev(mrb_state *mrb, mrb_value x)
445 v1 = (int64_t)mrb_float(x);
446 return int64_value(mrb, ~v1);
450 flo_and(mrb_state *mrb, mrb_value x)
452 mrb_value y = mrb_get_arg1(mrb);
455 v1 = (int64_t)mrb_float(x);
456 v2 = value_int64(mrb, y);
457 return int64_value(mrb, v1 & v2);
461 flo_or(mrb_state *mrb, mrb_value x)
463 mrb_value y = mrb_get_arg1(mrb);
466 v1 = (int64_t)mrb_float(x);
467 v2 = value_int64(mrb, y);
468 return int64_value(mrb, v1 | v2);
472 flo_xor(mrb_state *mrb, mrb_value x)
474 mrb_value y = mrb_get_arg1(mrb);
477 v1 = (int64_t)mrb_float(x);
478 v2 = value_int64(mrb, y);
479 return int64_value(mrb, v1 ^ v2);
483 flo_shift(mrb_state *mrb, mrb_value x, mrb_int width)
499 #if defined(_ISOC99_SOURCE)
508 if (val == 0 && mrb_float(x) < 0) {
509 return mrb_fixnum_value(-1);
517 return mrb_int_value(mrb, val);
521 flo_rshift(mrb_state *mrb, mrb_value x)
525 mrb_get_args(mrb, "i", &width);
526 return flo_shift(mrb, x, -width);
530 flo_lshift(mrb_state *mrb, mrb_value x)
534 mrb_get_args(mrb, "i", &width);
535 return flo_shift(mrb, x, width);
543 * As <code>flt</code> is already a float, returns +self+.
547 flo_to_f(mrb_state *mrb, mrb_value num)
555 * flt.infinite? -> nil, -1, +1
557 * Returns <code>nil</code>, -1, or +1 depending on whether <i>flt</i>
558 * is finite, -infinity, or +infinity.
560 * (0.0).infinite? #=> nil
561 * (-1.0/0.0).infinite? #=> -1
562 * (+1.0/0.0).infinite? #=> 1
566 flo_infinite_p(mrb_state *mrb, mrb_value num)
568 mrb_float value = mrb_float(num);
571 return mrb_fixnum_value(value < 0 ? -1 : 1);
573 return mrb_nil_value();
579 * flt.finite? -> true or false
581 * Returns <code>true</code> if <i>flt</i> is a valid IEEE floating
582 * point number (it is not infinite, and <code>nan?</code> is
583 * <code>false</code>).
588 flo_finite_p(mrb_state *mrb, mrb_value num)
590 return mrb_bool_value(isfinite(mrb_float(num)));
594 mrb_check_num_exact(mrb_state *mrb, mrb_float num)
597 mrb_raise(mrb, E_FLOATDOMAIN_ERROR, num < 0 ? "-Infinity" : "Infinity");
600 mrb_raise(mrb, E_FLOATDOMAIN_ERROR, "NaN");
607 * flt.floor -> integer
609 * Returns the largest integer less than or equal to <i>flt</i>.
613 * (-1.2).floor #=> -2
614 * (-2.0).floor #=> -2
618 flo_floor(mrb_state *mrb, mrb_value num)
620 mrb_float f = floor(mrb_float(num));
622 mrb_check_num_exact(mrb, f);
623 return mrb_int_value(mrb, f);
629 * flt.ceil -> integer
631 * Returns the smallest <code>Integer</code> greater than or equal to
641 flo_ceil(mrb_state *mrb, mrb_value num)
643 mrb_float f = ceil(mrb_float(num));
645 mrb_check_num_exact(mrb, f);
646 return mrb_int_value(mrb, f);
652 * flt.round([ndigits]) -> integer or float
654 * Rounds <i>flt</i> to a given precision in decimal digits (default 0 digits).
655 * Precision may be negative. Returns a floating point number when ndigits
661 * (-1.5).round #=> -2
663 * 1.234567.round(2) #=> 1.23
664 * 1.234567.round(3) #=> 1.235
665 * 1.234567.round(4) #=> 1.2346
666 * 1.234567.round(5) #=> 1.23457
668 * 34567.89.round(-5) #=> 0
669 * 34567.89.round(-4) #=> 30000
670 * 34567.89.round(-3) #=> 35000
671 * 34567.89.round(-2) #=> 34600
672 * 34567.89.round(-1) #=> 34570
673 * 34567.89.round(0) #=> 34568
674 * 34567.89.round(1) #=> 34567.9
675 * 34567.89.round(2) #=> 34567.89
676 * 34567.89.round(3) #=> 34567.89
681 flo_round(mrb_state *mrb, mrb_value num)
687 mrb_get_args(mrb, "|i", &ndigits);
688 number = mrb_float(num);
690 if (0 < ndigits && (isinf(number) || isnan(number))) {
693 mrb_check_num_exact(mrb, number);
696 i = ndigits >= 0 ? ndigits : -ndigits;
697 if (ndigits > DBL_DIG+2) return num;
702 if (ndigits < 0) number = 0;
707 if (ndigits < 0) number /= f;
710 /* home-made inline implementation of round(3) */
713 number = d + (number - d >= 0.5);
715 else if (number < 0.0) {
717 number = d - (d - number >= 0.5);
720 if (ndigits < 0) number *= f;
725 if (!isfinite(number)) return num;
726 return mrb_float_value(mrb, number);
728 return mrb_int_value(mrb, number);
735 * flt.to_i -> integer
736 * flt.truncate -> integer
738 * Returns <i>flt</i> truncated to an <code>Integer</code>.
742 flo_truncate(mrb_state *mrb, mrb_value num)
744 mrb_float f = mrb_float(num);
746 if (f > 0.0) f = floor(f);
747 if (f < 0.0) f = ceil(f);
749 mrb_check_num_exact(mrb, f);
750 return mrb_int_value(mrb, f);
754 flo_nan_p(mrb_state *mrb, mrb_value num)
756 return mrb_bool_value(isnan(mrb_float(num)));
761 * Document-class: Integer
763 * <code>Integer</code> is the basis for the two concrete classes that
764 * hold whole numbers, <code>Bignum</code> and <code>Fixnum</code>.
771 * int.to_i -> integer
773 * As <i>int</i> is already an <code>Integer</code>, all these
774 * methods simply return the receiver.
778 int_to_i(mrb_state *mrb, mrb_value num)
784 fixnum_mul(mrb_state *mrb, mrb_value x, mrb_value y)
789 if (mrb_fixnum_p(y)) {
792 if (a == 0) return x;
794 if (mrb_int_mul_overflow(a, b, &c)) {
795 #ifndef MRB_WITHOUT_FLOAT
796 return mrb_float_value(mrb, (mrb_float)a * (mrb_float)b);
799 return mrb_fixnum_value(c);
801 #ifdef MRB_WITHOUT_FLOAT
802 mrb_raise(mrb, E_TYPE_ERROR, "non fixnum value");
804 return mrb_float_value(mrb, (mrb_float)a * mrb_to_flo(mrb, y));
809 mrb_num_mul(mrb_state *mrb, mrb_value x, mrb_value y)
811 if (mrb_fixnum_p(x)) {
812 return fixnum_mul(mrb, x, y);
814 #ifndef MRB_WITHOUT_FLOAT
815 if (mrb_float_p(x)) {
816 return mrb_float_value(mrb, mrb_float(x) * mrb_to_flo(mrb, y));
819 mrb_raise(mrb, E_TYPE_ERROR, "no number multiply");
820 return mrb_nil_value(); /* not reached */
826 * fix * numeric -> numeric_result
828 * Performs multiplication: the class of the resulting object depends on
829 * the class of <code>numeric</code> and on the magnitude of the
834 fix_mul(mrb_state *mrb, mrb_value x)
836 mrb_value y = mrb_get_arg1(mrb);
838 return fixnum_mul(mrb, x, y);
842 fixdivmod(mrb_state *mrb, mrb_int x, mrb_int y, mrb_int *divp, mrb_int *modp)
846 /* TODO: add mrb_assert(y != 0) to make sure */
861 if ((mod < 0 && y > 0) || (mod > 0 && y < 0)) {
865 if (divp) *divp = div;
866 if (modp) *modp = mod;
872 * fix % other -> real
873 * fix.modulo(other) -> real
875 * Returns <code>fix</code> modulo <code>other</code>.
876 * See <code>numeric.divmod</code> for more information.
880 fix_mod(mrb_state *mrb, mrb_value x)
882 mrb_value y = mrb_get_arg1(mrb);
886 if (mrb_fixnum_p(y) && a != MRB_INT_MIN && (b=mrb_fixnum(y)) != MRB_INT_MIN) {
890 #ifdef MRB_WITHOUT_FLOAT
891 /* ZeroDivisionError */
892 return mrb_fixnum_value(0);
894 if (a > 0) return mrb_float_value(mrb, INFINITY);
895 if (a < 0) return mrb_float_value(mrb, INFINITY);
896 return mrb_float_value(mrb, NAN);
899 fixdivmod(mrb, a, b, NULL, &mod);
900 return mrb_fixnum_value(mod);
902 #ifdef MRB_WITHOUT_FLOAT
903 mrb_raise(mrb, E_TYPE_ERROR, "non fixnum value");
908 flodivmod(mrb, (mrb_float)a, mrb_to_flo(mrb, y), NULL, &mod);
909 return mrb_float_value(mrb, mod);
916 * fix.divmod(numeric) -> array
918 * See <code>Numeric#divmod</code>.
921 fix_divmod(mrb_state *mrb, mrb_value x)
923 mrb_value y = mrb_get_arg1(mrb);
925 if (mrb_fixnum_p(y)) {
928 if (mrb_fixnum(y) == 0) {
929 #ifdef MRB_WITHOUT_FLOAT
930 return mrb_assoc_new(mrb, mrb_fixnum_value(0), mrb_fixnum_value(0));
932 return mrb_assoc_new(mrb, ((mrb_fixnum(x) == 0) ?
933 mrb_float_value(mrb, NAN):
934 mrb_float_value(mrb, INFINITY)),
935 mrb_float_value(mrb, NAN));
938 fixdivmod(mrb, mrb_fixnum(x), mrb_fixnum(y), &div, &mod);
939 return mrb_assoc_new(mrb, mrb_fixnum_value(div), mrb_fixnum_value(mod));
941 #ifdef MRB_WITHOUT_FLOAT
942 mrb_raise(mrb, E_TYPE_ERROR, "non fixnum value");
948 flodivmod(mrb, (mrb_float)mrb_fixnum(x), mrb_to_flo(mrb, y), &div, &mod);
949 a = mrb_int_value(mrb, div);
950 b = mrb_float_value(mrb, mod);
951 return mrb_assoc_new(mrb, a, b);
956 #ifndef MRB_WITHOUT_FLOAT
958 flo_divmod(mrb_state *mrb, mrb_value x)
960 mrb_value y = mrb_get_arg1(mrb);
964 flodivmod(mrb, mrb_float(x), mrb_to_flo(mrb, y), &div, &mod);
965 a = mrb_int_value(mrb, div);
966 b = mrb_float_value(mrb, mod);
967 return mrb_assoc_new(mrb, a, b);
974 * fix == other -> true or false
976 * Return <code>true</code> if <code>fix</code> equals <code>other</code>
984 fix_equal(mrb_state *mrb, mrb_value x)
986 mrb_value y = mrb_get_arg1(mrb);
988 switch (mrb_type(y)) {
990 return mrb_bool_value(mrb_fixnum(x) == mrb_fixnum(y));
991 #ifndef MRB_WITHOUT_FLOAT
993 return mrb_bool_value((mrb_float)mrb_fixnum(x) == mrb_float(y));
996 return mrb_false_value();
1005 * One's complement: returns a number where each bit is flipped.
1006 * ex.0---00001 (1)-> 1---11110 (-2)
1007 * ex.0---00010 (2)-> 1---11101 (-3)
1008 * ex.0---00100 (4)-> 1---11011 (-5)
1012 fix_rev(mrb_state *mrb, mrb_value num)
1014 mrb_int val = mrb_fixnum(num);
1016 return mrb_fixnum_value(~val);
1019 #ifdef MRB_WITHOUT_FLOAT
1020 #define bit_op(x,y,op1,op2) do {\
1021 return mrb_fixnum_value(mrb_fixnum(x) op2 mrb_fixnum(y));\
1024 static mrb_value flo_and(mrb_state *mrb, mrb_value x);
1025 static mrb_value flo_or(mrb_state *mrb, mrb_value x);
1026 static mrb_value flo_xor(mrb_state *mrb, mrb_value x);
1027 #define bit_op(x,y,op1,op2) do {\
1028 if (mrb_fixnum_p(y)) return mrb_fixnum_value(mrb_fixnum(x) op2 mrb_fixnum(y));\
1029 return flo_ ## op1(mrb, mrb_float_value(mrb, (mrb_float)mrb_fixnum(x)));\
1036 * fix & integer -> integer_result
1042 fix_and(mrb_state *mrb, mrb_value x)
1044 mrb_value y = mrb_get_arg1(mrb);
1046 bit_op(x, y, and, &);
1052 * fix | integer -> integer_result
1058 fix_or(mrb_state *mrb, mrb_value x)
1060 mrb_value y = mrb_get_arg1(mrb);
1062 bit_op(x, y, or, |);
1068 * fix ^ integer -> integer_result
1070 * Bitwise EXCLUSIVE OR.
1074 fix_xor(mrb_state *mrb, mrb_value x)
1076 mrb_value y = mrb_get_arg1(mrb);
1078 bit_op(x, y, or, ^);
1081 #define NUMERIC_SHIFT_WIDTH_MAX (MRB_INT_BIT-1)
1084 lshift(mrb_state *mrb, mrb_int val, mrb_int width)
1086 if (width < 0) { /* mrb_int overflow */
1087 #ifdef MRB_WITHOUT_FLOAT
1088 return mrb_fixnum_value(0);
1090 return mrb_float_value(mrb, INFINITY);
1094 if ((width > NUMERIC_SHIFT_WIDTH_MAX) ||
1095 (val > (MRB_INT_MAX >> width))) {
1096 #ifdef MRB_WITHOUT_FLOAT
1097 return mrb_fixnum_value(-1);
1102 return mrb_fixnum_value(val << width);
1105 if ((width > NUMERIC_SHIFT_WIDTH_MAX) ||
1106 (val <= (MRB_INT_MIN >> width))) {
1107 #ifdef MRB_WITHOUT_FLOAT
1108 return mrb_fixnum_value(0);
1113 return mrb_fixnum_value(val * ((mrb_int)1 << width));
1116 #ifndef MRB_WITHOUT_FLOAT
1119 mrb_float f = (mrb_float)val;
1123 return mrb_float_value(mrb, f);
1129 rshift(mrb_int val, mrb_int width)
1131 if (width < 0) { /* mrb_int overflow */
1132 return mrb_fixnum_value(0);
1134 if (width >= NUMERIC_SHIFT_WIDTH_MAX) {
1136 return mrb_fixnum_value(-1);
1138 return mrb_fixnum_value(0);
1140 return mrb_fixnum_value(val >> width);
1146 * fix << count -> integer or float
1148 * Shifts _fix_ left _count_ positions (right if _count_ is negative).
1152 fix_lshift(mrb_state *mrb, mrb_value x)
1156 mrb_get_args(mrb, "i", &width);
1160 val = mrb_fixnum(x);
1161 if (val == 0) return x;
1163 return rshift(val, -width);
1165 return lshift(mrb, val, width);
1171 * fix >> count -> integer or float
1173 * Shifts _fix_ right _count_ positions (left if _count_ is negative).
1177 fix_rshift(mrb_state *mrb, mrb_value x)
1181 mrb_get_args(mrb, "i", &width);
1185 val = mrb_fixnum(x);
1186 if (val == 0) return x;
1188 return lshift(mrb, val, -width);
1190 return rshift(val, width);
1198 * Converts <i>fix</i> to a <code>Float</code>.
1202 #ifndef MRB_WITHOUT_FLOAT
1204 fix_to_f(mrb_state *mrb, mrb_value num)
1206 return mrb_float_value(mrb, (mrb_float)mrb_fixnum(num));
1210 * Document-class: FloatDomainError
1212 * Raised when attempting to convert special float values
1213 * (in particular infinite or NaN)
1214 * to numerical classes which don't support them.
1216 * Float::INFINITY.to_i
1218 * <em>raises the exception:</em>
1220 * FloatDomainError: Infinity
1222 /* ------------------------------------------------------------------------*/
1224 mrb_flo_to_fixnum(mrb_state *mrb, mrb_value x)
1228 if (!mrb_float_p(x)) {
1229 mrb_raise(mrb, E_TYPE_ERROR, "non float value");
1230 z = 0; /* not reached. just suppress warnings. */
1233 mrb_float d = mrb_float(x);
1235 mrb_check_num_exact(mrb, d);
1236 if (FIXABLE_FLOAT(d)) {
1240 mrb_raisef(mrb, E_RANGE_ERROR, "number (%v) too big for integer", x);
1243 return mrb_fixnum_value(z);
1248 fixnum_plus(mrb_state *mrb, mrb_value x, mrb_value y)
1253 if (mrb_fixnum_p(y)) {
1256 if (a == 0) return y;
1258 if (mrb_int_add_overflow(a, b, &c)) {
1259 #ifndef MRB_WITHOUT_FLOAT
1260 return mrb_float_value(mrb, (mrb_float)a + (mrb_float)b);
1263 return mrb_fixnum_value(c);
1265 #ifdef MRB_WITHOUT_FLOAT
1266 mrb_raise(mrb, E_TYPE_ERROR, "non fixnum value");
1268 return mrb_float_value(mrb, (mrb_float)a + mrb_to_flo(mrb, y));
1273 mrb_num_plus(mrb_state *mrb, mrb_value x, mrb_value y)
1275 if (mrb_fixnum_p(x)) {
1276 return fixnum_plus(mrb, x, y);
1278 #ifndef MRB_WITHOUT_FLOAT
1279 if (mrb_float_p(x)) {
1280 return mrb_float_value(mrb, mrb_float(x) + mrb_to_flo(mrb, y));
1283 mrb_raise(mrb, E_TYPE_ERROR, "no number addition");
1284 return mrb_nil_value(); /* not reached */
1290 * fix + numeric -> numeric_result
1292 * Performs addition: the class of the resulting object depends on
1293 * the class of <code>numeric</code> and on the magnitude of the
1297 fix_plus(mrb_state *mrb, mrb_value self)
1299 mrb_value other = mrb_get_arg1(mrb);
1301 return fixnum_plus(mrb, self, other);
1305 fixnum_minus(mrb_state *mrb, mrb_value x, mrb_value y)
1310 if (mrb_fixnum_p(y)) {
1314 if (mrb_int_sub_overflow(a, b, &c)) {
1315 #ifndef MRB_WITHOUT_FLOAT
1316 return mrb_float_value(mrb, (mrb_float)a - (mrb_float)b);
1319 return mrb_fixnum_value(c);
1321 #ifdef MRB_WITHOUT_FLOAT
1322 mrb_raise(mrb, E_TYPE_ERROR, "non fixnum value");
1324 return mrb_float_value(mrb, (mrb_float)a - mrb_to_flo(mrb, y));
1329 mrb_num_minus(mrb_state *mrb, mrb_value x, mrb_value y)
1331 if (mrb_fixnum_p(x)) {
1332 return fixnum_minus(mrb, x, y);
1334 #ifndef MRB_WITHOUT_FLOAT
1335 if (mrb_float_p(x)) {
1336 return mrb_float_value(mrb, mrb_float(x) - mrb_to_flo(mrb, y));
1339 mrb_raise(mrb, E_TYPE_ERROR, "no number subtraction");
1340 return mrb_nil_value(); /* not reached */
1347 * fix - numeric -> numeric_result
1349 * Performs subtraction: the class of the resulting object depends on
1350 * the class of <code>numeric</code> and on the magnitude of the
1354 fix_minus(mrb_state *mrb, mrb_value self)
1356 mrb_value other = mrb_get_arg1(mrb);
1358 return fixnum_minus(mrb, self, other);
1363 mrb_fixnum_to_str(mrb_state *mrb, mrb_value x, mrb_int base)
1365 char buf[MRB_INT_BIT+1];
1366 char *b = buf + sizeof buf;
1367 mrb_int val = mrb_fixnum(x);
1370 if (base < 2 || 36 < base) {
1371 mrb_raisef(mrb, E_ARGUMENT_ERROR, "invalid radix %i", base);
1379 *--b = mrb_digitmap[-(val % base)];
1380 } while (val /= base);
1385 *--b = mrb_digitmap[(int)(val % base)];
1386 } while (val /= base);
1389 str = mrb_str_new(mrb, b, buf + sizeof(buf) - b);
1390 RSTR_SET_ASCII_FLAG(mrb_str_ptr(str));
1397 * fix.to_s(base=10) -> string
1399 * Returns a string containing the representation of <i>fix</i> radix
1400 * <i>base</i> (between 2 and 36).
1402 * 12345.to_s #=> "12345"
1403 * 12345.to_s(2) #=> "11000000111001"
1404 * 12345.to_s(8) #=> "30071"
1405 * 12345.to_s(10) #=> "12345"
1406 * 12345.to_s(16) #=> "3039"
1407 * 12345.to_s(36) #=> "9ix"
1411 fix_to_s(mrb_state *mrb, mrb_value self)
1415 mrb_get_args(mrb, "|i", &base);
1416 return mrb_fixnum_to_str(mrb, self, base);
1419 /* compare two numbers: (1:0:-1; -2 for error) */
1421 cmpnum(mrb_state *mrb, mrb_value v1, mrb_value v2)
1423 #ifdef MRB_WITHOUT_FLOAT
1429 #ifdef MRB_WITHOUT_FLOAT
1432 x = mrb_to_flo(mrb, v1);
1434 switch (mrb_type(v2)) {
1436 #ifdef MRB_WITHOUT_FLOAT
1439 y = (mrb_float)mrb_fixnum(v2);
1442 #ifndef MRB_WITHOUT_FLOAT
1462 * self.f <=> other.f => -1, 0, +1, or nil
1466 * Comparison---Returns -1, 0, or +1 depending on whether <i>fix</i> is
1467 * less than, equal to, or greater than <i>numeric</i>. This is the
1468 * basis for the tests in <code>Comparable</code>. When the operands are
1469 * not comparable, it returns nil instead of raising an exception.
1472 integral_cmp(mrb_state *mrb, mrb_value self)
1474 mrb_value other = mrb_get_arg1(mrb);
1477 n = cmpnum(mrb, self, other);
1478 if (n == -2) return mrb_nil_value();
1479 return mrb_fixnum_value(n);
1482 static mrb_noreturn void
1483 cmperr(mrb_state *mrb, mrb_value v1, mrb_value v2)
1485 mrb_raisef(mrb, E_ARGUMENT_ERROR, "comparison of %t with %t failed", v1, v2);
1489 integral_lt(mrb_state *mrb, mrb_value self)
1491 mrb_value other = mrb_get_arg1(mrb);
1494 n = cmpnum(mrb, self, other);
1495 if (n == -2) cmperr(mrb, self, other);
1496 if (n < 0) return mrb_true_value();
1497 return mrb_false_value();
1501 integral_le(mrb_state *mrb, mrb_value self)
1503 mrb_value other = mrb_get_arg1(mrb);
1506 n = cmpnum(mrb, self, other);
1507 if (n == -2) cmperr(mrb, self, other);
1508 if (n <= 0) return mrb_true_value();
1509 return mrb_false_value();
1513 integral_gt(mrb_state *mrb, mrb_value self)
1515 mrb_value other = mrb_get_arg1(mrb);
1518 n = cmpnum(mrb, self, other);
1519 if (n == -2) cmperr(mrb, self, other);
1520 if (n > 0) return mrb_true_value();
1521 return mrb_false_value();
1525 integral_ge(mrb_state *mrb, mrb_value self)
1527 mrb_value other = mrb_get_arg1(mrb);
1530 n = cmpnum(mrb, self, other);
1531 if (n == -2) cmperr(mrb, self, other);
1532 if (n >= 0) return mrb_true_value();
1533 return mrb_false_value();
1537 mrb_cmp(mrb_state *mrb, mrb_value obj1, mrb_value obj2)
1541 switch (mrb_type(obj1)) {
1544 return cmpnum(mrb, obj1, obj2);
1546 if (!mrb_string_p(obj2))
1548 return mrb_str_cmp(mrb, obj1, obj2);
1550 v = mrb_funcall(mrb, obj1, "<=>", 1, obj2);
1551 if (mrb_nil_p(v) || !mrb_fixnum_p(v))
1553 return mrb_fixnum(v);
1558 num_finite_p(mrb_state *mrb, mrb_value self)
1560 return mrb_true_value();
1564 num_infinite_p(mrb_state *mrb, mrb_value self)
1566 return mrb_false_value();
1572 * float + other -> float
1574 * Returns a new float which is the sum of <code>float</code>
1575 * and <code>other</code>.
1577 #ifndef MRB_WITHOUT_FLOAT
1579 flo_plus(mrb_state *mrb, mrb_value x)
1581 mrb_value y = mrb_get_arg1(mrb);
1583 return mrb_float_value(mrb, mrb_float(x) + mrb_to_flo(mrb, y));
1587 /* ------------------------------------------------------------------------*/
1589 mrb_init_numeric(mrb_state *mrb)
1591 struct RClass *numeric, *integer, *fixnum, *integral;
1592 #ifndef MRB_WITHOUT_FLOAT
1596 integral = mrb_define_module(mrb, "Integral");
1597 mrb_define_method(mrb, integral,"**", integral_pow, MRB_ARGS_REQ(1));
1598 mrb_define_method(mrb, integral,"/", integral_div, MRB_ARGS_REQ(1)); /* 15.2.{8,9}.3.6 */
1599 mrb_define_method(mrb, integral,"quo", integral_div, MRB_ARGS_REQ(1)); /* 15.2.7.4.5 (x) */
1600 mrb_define_method(mrb, integral,"div", integral_idiv, MRB_ARGS_REQ(1));
1601 mrb_define_method(mrb, integral,"<=>", integral_cmp, MRB_ARGS_REQ(1)); /* 15.2.{8,9}.3.1 */
1602 mrb_define_method(mrb, integral,"<", integral_lt, MRB_ARGS_REQ(1));
1603 mrb_define_method(mrb, integral,"<=", integral_le, MRB_ARGS_REQ(1));
1604 mrb_define_method(mrb, integral,">", integral_gt, MRB_ARGS_REQ(1));
1605 mrb_define_method(mrb, integral,">=", integral_ge, MRB_ARGS_REQ(1));
1606 mrb_define_method(mrb, integral,"__coerce_step_counter", integral_coerce_step_counter, MRB_ARGS_REQ(2));
1609 numeric = mrb_define_class(mrb, "Numeric", mrb->object_class); /* 15.2.7 */
1610 mrb_define_method(mrb, numeric, "finite?", num_finite_p, MRB_ARGS_NONE());
1611 mrb_define_method(mrb, numeric, "infinite?",num_infinite_p, MRB_ARGS_NONE());
1614 integer = mrb_define_class(mrb, "Integer", numeric); /* 15.2.8 */
1615 MRB_SET_INSTANCE_TT(integer, MRB_TT_FIXNUM);
1616 mrb_undef_class_method(mrb, integer, "new");
1617 mrb_define_method(mrb, integer, "to_i", int_to_i, MRB_ARGS_NONE()); /* 15.2.8.3.24 */
1618 mrb_define_method(mrb, integer, "to_int", int_to_i, MRB_ARGS_NONE());
1619 #ifndef MRB_WITHOUT_FLOAT
1620 mrb_define_method(mrb, integer, "ceil", int_to_i, MRB_ARGS_NONE()); /* 15.2.8.3.8 (x) */
1621 mrb_define_method(mrb, integer, "floor", int_to_i, MRB_ARGS_NONE()); /* 15.2.8.3.10 (x) */
1622 mrb_define_method(mrb, integer, "round", int_to_i, MRB_ARGS_NONE()); /* 15.2.8.3.12 (x) */
1623 mrb_define_method(mrb, integer, "truncate", int_to_i, MRB_ARGS_NONE()); /* 15.2.8.3.15 (x) */
1627 mrb->fixnum_class = fixnum = mrb_define_class(mrb, "Fixnum", integer);
1628 mrb_define_method(mrb, fixnum, "+", fix_plus, MRB_ARGS_REQ(1)); /* 15.2.8.3.1 */
1629 mrb_define_method(mrb, fixnum, "-", fix_minus, MRB_ARGS_REQ(1)); /* 15.2.8.3.2 */
1630 mrb_define_method(mrb, fixnum, "*", fix_mul, MRB_ARGS_REQ(1)); /* 15.2.8.3.3 */
1631 mrb_define_method(mrb, fixnum, "%", fix_mod, MRB_ARGS_REQ(1)); /* 15.2.8.3.5 */
1632 mrb_define_method(mrb, fixnum, "==", fix_equal, MRB_ARGS_REQ(1)); /* 15.2.8.3.7 */
1633 mrb_define_method(mrb, fixnum, "~", fix_rev, MRB_ARGS_NONE()); /* 15.2.8.3.8 */
1634 mrb_define_method(mrb, fixnum, "&", fix_and, MRB_ARGS_REQ(1)); /* 15.2.8.3.9 */
1635 mrb_define_method(mrb, fixnum, "|", fix_or, MRB_ARGS_REQ(1)); /* 15.2.8.3.10 */
1636 mrb_define_method(mrb, fixnum, "^", fix_xor, MRB_ARGS_REQ(1)); /* 15.2.8.3.11 */
1637 mrb_define_method(mrb, fixnum, "<<", fix_lshift, MRB_ARGS_REQ(1)); /* 15.2.8.3.12 */
1638 mrb_define_method(mrb, fixnum, ">>", fix_rshift, MRB_ARGS_REQ(1)); /* 15.2.8.3.13 */
1639 mrb_define_method(mrb, fixnum, "eql?", fix_eql, MRB_ARGS_REQ(1)); /* 15.2.8.3.16 */
1640 #ifndef MRB_WITHOUT_FLOAT
1641 mrb_define_method(mrb, fixnum, "to_f", fix_to_f, MRB_ARGS_NONE()); /* 15.2.8.3.23 */
1643 mrb_define_method(mrb, fixnum, "to_s", fix_to_s, MRB_ARGS_OPT(1)); /* 15.2.8.3.25 */
1644 mrb_define_method(mrb, fixnum, "inspect", fix_to_s, MRB_ARGS_OPT(1));
1645 mrb_define_method(mrb, fixnum, "divmod", fix_divmod, MRB_ARGS_REQ(1)); /* 15.2.8.3.30 (x) */
1647 #ifndef MRB_WITHOUT_FLOAT
1649 mrb->float_class = fl = mrb_define_class(mrb, "Float", numeric); /* 15.2.9 */
1650 MRB_SET_INSTANCE_TT(fl, MRB_TT_FLOAT);
1651 mrb_undef_class_method(mrb, fl, "new");
1652 mrb_define_method(mrb, fl, "+", flo_plus, MRB_ARGS_REQ(1)); /* 15.2.9.3.1 */
1653 mrb_define_method(mrb, fl, "-", flo_minus, MRB_ARGS_REQ(1)); /* 15.2.9.3.2 */
1654 mrb_define_method(mrb, fl, "*", flo_mul, MRB_ARGS_REQ(1)); /* 15.2.9.3.3 */
1655 mrb_define_method(mrb, fl, "%", flo_mod, MRB_ARGS_REQ(1)); /* 15.2.9.3.5 */
1656 mrb_define_method(mrb, fl, "==", flo_eq, MRB_ARGS_REQ(1)); /* 15.2.9.3.7 */
1657 mrb_define_method(mrb, fl, "~", flo_rev, MRB_ARGS_NONE());
1658 mrb_define_method(mrb, fl, "&", flo_and, MRB_ARGS_REQ(1));
1659 mrb_define_method(mrb, fl, "|", flo_or, MRB_ARGS_REQ(1));
1660 mrb_define_method(mrb, fl, "^", flo_xor, MRB_ARGS_REQ(1));
1661 mrb_define_method(mrb, fl, ">>", flo_rshift, MRB_ARGS_REQ(1));
1662 mrb_define_method(mrb, fl, "<<", flo_lshift, MRB_ARGS_REQ(1));
1663 mrb_define_method(mrb, fl, "ceil", flo_ceil, MRB_ARGS_NONE()); /* 15.2.9.3.8 */
1664 mrb_define_method(mrb, fl, "finite?", flo_finite_p, MRB_ARGS_NONE()); /* 15.2.9.3.9 */
1665 mrb_define_method(mrb, fl, "floor", flo_floor, MRB_ARGS_NONE()); /* 15.2.9.3.10 */
1666 mrb_define_method(mrb, fl, "infinite?", flo_infinite_p, MRB_ARGS_NONE()); /* 15.2.9.3.11 */
1667 mrb_define_method(mrb, fl, "round", flo_round, MRB_ARGS_OPT(1)); /* 15.2.9.3.12 */
1668 mrb_define_method(mrb, fl, "to_f", flo_to_f, MRB_ARGS_NONE()); /* 15.2.9.3.13 */
1669 mrb_define_method(mrb, fl, "to_i", flo_truncate, MRB_ARGS_NONE()); /* 15.2.9.3.14 */
1670 mrb_define_method(mrb, fl, "to_int", flo_truncate, MRB_ARGS_NONE());
1671 mrb_define_method(mrb, fl, "truncate", flo_truncate, MRB_ARGS_NONE()); /* 15.2.9.3.15 */
1672 mrb_define_method(mrb, fl, "divmod", flo_divmod, MRB_ARGS_REQ(1));
1673 mrb_define_method(mrb, fl, "eql?", flo_eql, MRB_ARGS_REQ(1)); /* 15.2.8.3.16 */
1675 mrb_define_method(mrb, fl, "to_s", flo_to_s, MRB_ARGS_NONE()); /* 15.2.9.3.16(x) */
1676 mrb_define_method(mrb, fl, "inspect", flo_to_s, MRB_ARGS_NONE());
1677 mrb_define_method(mrb, fl, "nan?", flo_nan_p, MRB_ARGS_NONE());
1680 mrb_define_const(mrb, fl, "INFINITY", mrb_float_value(mrb, INFINITY));
1683 mrb_define_const(mrb, fl, "NAN", mrb_float_value(mrb, NAN));
1686 mrb_include_module(mrb, fl, integral);