2 ** numeric.c - Numeric, Integer, Float, Fixnum class
4 ** See Copyright Notice in mruby.h
7 #ifndef MRB_WITHOUT_FLOAT
15 #include <mruby/array.h>
16 #include <mruby/numeric.h>
17 #include <mruby/string.h>
18 #include <mruby/class.h>
20 #ifndef MRB_WITHOUT_FLOAT
22 #define trunc(f) truncf(f)
23 #define floor(f) floorf(f)
24 #define ceil(f) ceilf(f)
25 #define fmod(x,y) fmodf(x,y)
26 #define MRB_FLO_TO_STR_FMT "%.7g"
28 #define MRB_FLO_TO_STR_FMT "%.14g"
32 #ifndef MRB_WITHOUT_FLOAT
34 mrb_to_flo(mrb_state
*mrb
, mrb_value val
)
36 switch (mrb_type(val
)) {
38 return (mrb_float
)mrb_fixnum(val
);
42 mrb_raise(mrb
, E_TYPE_ERROR
, "non float value");
44 return mrb_float(val
);
53 * Raises <code>num</code> the <code>other</code> power.
58 num_pow(mrb_state
*mrb
, mrb_value x
)
61 #ifndef MRB_WITHOUT_FLOAT
65 mrb_get_args(mrb
, "o", &y
);
66 if (mrb_fixnum_p(x
) && mrb_fixnum_p(y
)) {
68 mrb_int base
= mrb_fixnum(x
);
69 mrb_int exp
= mrb_fixnum(y
);
73 #ifdef MRB_WITHOUT_FLOAT
74 return mrb_fixnum_value(0);
80 if (mrb_int_mul_overflow(result
, base
, &result
)) {
81 #ifndef MRB_WITHOUT_FLOAT
88 if (mrb_int_mul_overflow(base
, base
, &base
)) {
89 #ifndef MRB_WITHOUT_FLOAT
94 return mrb_fixnum_value(result
);
96 #ifdef MRB_WITHOUT_FLOAT
97 mrb_raise(mrb
, E_TYPE_ERROR
, "non fixnum value");
100 d
= pow(mrb_to_flo(mrb
, x
), mrb_to_flo(mrb
, y
));
101 return mrb_float_value(mrb
, d
);
111 * Performs division: the class of the resulting object depends on
112 * the class of <code>num</code> and on the magnitude of the
117 mrb_num_div(mrb_state
*mrb
, mrb_value x
, mrb_value y
)
119 #ifdef MRB_WITHOUT_FLOAT
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
));
125 return mrb_float_value(mrb
, mrb_to_flo(mrb
, x
) / mrb_to_flo(mrb
, y
));
132 * num.quo(numeric) -> real
134 * Returns most exact division.
138 num_div(mrb_state
*mrb
, mrb_value x
)
140 #ifdef MRB_WITHOUT_FLOAT
143 mrb_get_args(mrb
, "o", &y
);
144 if (!mrb_fixnum_p(y
)) {
145 mrb_raise(mrb
, E_TYPE_ERROR
, "non fixnum value");
147 return mrb_fixnum_value(mrb_fixnum(x
) / mrb_fixnum(y
));
151 mrb_get_args(mrb
, "f", &y
);
152 return mrb_float_value(mrb
, mrb_to_flo(mrb
, x
) / y
);
156 #ifndef MRB_WITHOUT_FLOAT
157 /********************************************************************
159 * Document-class: Float
161 * <code>Float</code> objects represent inexact real numbers using
162 * the native architecture's double-precision floating point
171 * Returns a string containing a representation of self. As well as a
172 * fixed or exponential form of the number, the call may return
173 * "<code>NaN</code>", "<code>Infinity</code>", and
174 * "<code>-Infinity</code>".
178 flo_to_s(mrb_state
*mrb
, mrb_value flt
)
180 if (isnan(mrb_float(flt
))) {
181 return mrb_str_new_lit(mrb
, "NaN");
183 return mrb_float_to_str(mrb
, flt
, MRB_FLO_TO_STR_FMT
);
189 * float - other -> float
191 * Returns a new float which is the difference of <code>float</code>
192 * and <code>other</code>.
196 flo_minus(mrb_state
*mrb
, mrb_value x
)
200 mrb_get_args(mrb
, "o", &y
);
201 return mrb_float_value(mrb
, mrb_float(x
) - mrb_to_flo(mrb
, y
));
207 * float * other -> float
209 * Returns a new float which is the product of <code>float</code>
210 * and <code>other</code>.
214 flo_mul(mrb_state
*mrb
, mrb_value x
)
218 mrb_get_args(mrb
, "o", &y
);
219 return mrb_float_value(mrb
, mrb_float(x
) * mrb_to_flo(mrb
, y
));
223 flodivmod(mrb_state
*mrb
, mrb_float x
, mrb_float y
, mrb_float
*divp
, mrb_float
*modp
)
229 if (x
> 0.0) div
= INFINITY
;
230 else if (x
< 0.0) div
= -INFINITY
;
231 else div
= NAN
; /* x == 0.0 */
236 if (isinf(x
) && isfinite(y
))
246 if (modp
) *modp
= mod
;
247 if (divp
) *divp
= div
;
253 * flt % other -> float
254 * flt.modulo(other) -> float
256 * Return the modulo after division of <code>flt</code> by <code>other</code>.
258 * 6543.21.modulo(137) #=> 104.21
259 * 6543.21.modulo(137.24) #=> 92.9299999999996
263 flo_mod(mrb_state
*mrb
, mrb_value x
)
268 mrb_get_args(mrb
, "o", &y
);
270 flodivmod(mrb
, mrb_float(x
), mrb_to_flo(mrb
, y
), 0, &mod
);
271 return mrb_float_value(mrb
, mod
);
278 * num.eql?(numeric) -> true or false
280 * Returns <code>true</code> if <i>num</i> and <i>numeric</i> are the
281 * same type and have equal values.
284 * 1.eql?(1.0) #=> false
285 * (1.0).eql?(1.0) #=> true
288 fix_eql(mrb_state
*mrb
, mrb_value x
)
292 mrb_get_args(mrb
, "o", &y
);
293 if (!mrb_fixnum_p(y
)) return mrb_false_value();
294 return mrb_bool_value(mrb_fixnum(x
) == mrb_fixnum(y
));
297 #ifndef MRB_WITHOUT_FLOAT
299 flo_eql(mrb_state
*mrb
, mrb_value x
)
303 mrb_get_args(mrb
, "o", &y
);
304 if (!mrb_float_p(y
)) return mrb_false_value();
305 return mrb_bool_value(mrb_float(x
) == (mrb_float
)mrb_fixnum(y
));
311 * flt == obj -> true or false
313 * Returns <code>true</code> only if <i>obj</i> has the same value
314 * as <i>flt</i>. Contrast this with <code>Float#eql?</code>, which
315 * requires <i>obj</i> to be a <code>Float</code>.
322 flo_eq(mrb_state
*mrb
, mrb_value x
)
325 mrb_get_args(mrb
, "o", &y
);
327 switch (mrb_type(y
)) {
329 return mrb_bool_value(mrb_float(x
) == (mrb_float
)mrb_fixnum(y
));
331 return mrb_bool_value(mrb_float(x
) == mrb_float(y
));
333 return mrb_false_value();
338 value_int64(mrb_state
*mrb
, mrb_value x
)
340 switch (mrb_type(x
)) {
342 return (int64_t)mrb_fixnum(x
);
345 return (int64_t)mrb_float(x
);
347 mrb_raise(mrb
, E_TYPE_ERROR
, "cannot convert to Integer");
355 int64_value(mrb_state
*mrb
, int64_t v
)
358 return mrb_fixnum_value((mrb_int
)v
);
360 return mrb_float_value(mrb
, (mrb_float
)v
);
364 flo_rev(mrb_state
*mrb
, mrb_value x
)
367 mrb_get_args(mrb
, "");
368 v1
= (int64_t)mrb_float(x
);
369 return int64_value(mrb
, ~v1
);
373 flo_and(mrb_state
*mrb
, mrb_value x
)
377 mrb_get_args(mrb
, "o", &y
);
379 v1
= (int64_t)mrb_float(x
);
380 v2
= value_int64(mrb
, y
);
381 return int64_value(mrb
, v1
& v2
);
385 flo_or(mrb_state
*mrb
, mrb_value x
)
389 mrb_get_args(mrb
, "o", &y
);
391 v1
= (int64_t)mrb_float(x
);
392 v2
= value_int64(mrb
, y
);
393 return int64_value(mrb
, v1
| v2
);
397 flo_xor(mrb_state
*mrb
, mrb_value x
)
401 mrb_get_args(mrb
, "o", &y
);
403 v1
= (int64_t)mrb_float(x
);
404 v2
= value_int64(mrb
, y
);
405 return int64_value(mrb
, v1
^ v2
);
409 flo_shift(mrb_state
*mrb
, mrb_value x
, mrb_int width
)
421 #if defined(_ISOC99_SOURCE)
430 if (val
== 0 && mrb_float(x
) < 0) {
431 return mrb_fixnum_value(-1);
439 if (FIXABLE_FLOAT(val
)) {
440 return mrb_fixnum_value((mrb_int
)val
);
442 return mrb_float_value(mrb
, val
);
446 flo_lshift(mrb_state
*mrb
, mrb_value x
)
450 mrb_get_args(mrb
, "i", &width
);
451 return flo_shift(mrb
, x
, -width
);
455 flo_rshift(mrb_state
*mrb
, mrb_value x
)
459 mrb_get_args(mrb
, "i", &width
);
460 return flo_shift(mrb
, x
, width
);
468 * As <code>flt</code> is already a float, returns +self+.
472 flo_to_f(mrb_state
*mrb
, mrb_value num
)
480 * flt.infinite? -> nil, -1, +1
482 * Returns <code>nil</code>, -1, or +1 depending on whether <i>flt</i>
483 * is finite, -infinity, or +infinity.
485 * (0.0).infinite? #=> nil
486 * (-1.0/0.0).infinite? #=> -1
487 * (+1.0/0.0).infinite? #=> 1
491 flo_infinite_p(mrb_state
*mrb
, mrb_value num
)
493 mrb_float value
= mrb_float(num
);
496 return mrb_fixnum_value(value
< 0 ? -1 : 1);
498 return mrb_nil_value();
504 * flt.finite? -> true or false
506 * Returns <code>true</code> if <i>flt</i> is a valid IEEE floating
507 * point number (it is not infinite, and <code>nan?</code> is
508 * <code>false</code>).
513 flo_finite_p(mrb_state
*mrb
, mrb_value num
)
515 return mrb_bool_value(isfinite(mrb_float(num
)));
519 mrb_check_num_exact(mrb_state
*mrb
, mrb_float num
)
522 mrb_raise(mrb
, E_FLOATDOMAIN_ERROR
, num
< 0 ? "-Infinity" : "Infinity");
525 mrb_raise(mrb
, E_FLOATDOMAIN_ERROR
, "NaN");
532 * flt.floor -> integer
534 * Returns the largest integer less than or equal to <i>flt</i>.
538 * (-1.2).floor #=> -2
539 * (-2.0).floor #=> -2
543 flo_floor(mrb_state
*mrb
, mrb_value num
)
545 mrb_float f
= floor(mrb_float(num
));
547 mrb_check_num_exact(mrb
, f
);
548 if (!FIXABLE_FLOAT(f
)) {
549 return mrb_float_value(mrb
, f
);
551 return mrb_fixnum_value((mrb_int
)f
);
557 * flt.ceil -> integer
559 * Returns the smallest <code>Integer</code> greater than or equal to
569 flo_ceil(mrb_state
*mrb
, mrb_value num
)
571 mrb_float f
= ceil(mrb_float(num
));
573 mrb_check_num_exact(mrb
, f
);
574 if (!FIXABLE_FLOAT(f
)) {
575 return mrb_float_value(mrb
, f
);
577 return mrb_fixnum_value((mrb_int
)f
);
583 * flt.round([ndigits]) -> integer or float
585 * Rounds <i>flt</i> to a given precision in decimal digits (default 0 digits).
586 * Precision may be negative. Returns a floating point number when ndigits
592 * (-1.5).round #=> -2
594 * 1.234567.round(2) #=> 1.23
595 * 1.234567.round(3) #=> 1.235
596 * 1.234567.round(4) #=> 1.2346
597 * 1.234567.round(5) #=> 1.23457
599 * 34567.89.round(-5) #=> 0
600 * 34567.89.round(-4) #=> 30000
601 * 34567.89.round(-3) #=> 35000
602 * 34567.89.round(-2) #=> 34600
603 * 34567.89.round(-1) #=> 34570
604 * 34567.89.round(0) #=> 34568
605 * 34567.89.round(1) #=> 34567.9
606 * 34567.89.round(2) #=> 34567.89
607 * 34567.89.round(3) #=> 34567.89
612 flo_round(mrb_state
*mrb
, mrb_value num
)
618 mrb_get_args(mrb
, "|i", &ndigits
);
619 number
= mrb_float(num
);
621 if (0 < ndigits
&& (isinf(number
) || isnan(number
))) {
624 mrb_check_num_exact(mrb
, number
);
627 i
= ndigits
>= 0 ? ndigits
: -ndigits
;
632 if (ndigits
< 0) number
= 0;
637 if (ndigits
< 0) number
/= f
;
640 /* home-made inline implementation of round(3) */
643 number
= d
+ (number
- d
>= 0.5);
645 else if (number
< 0.0) {
647 number
= d
- (d
- number
>= 0.5);
650 if (ndigits
< 0) number
*= f
;
655 if (!isfinite(number
)) return num
;
656 return mrb_float_value(mrb
, number
);
658 return mrb_fixnum_value((mrb_int
)number
);
665 * flt.to_i -> integer
666 * flt.to_int -> integer
667 * flt.truncate -> integer
669 * Returns <i>flt</i> truncated to an <code>Integer</code>.
673 flo_truncate(mrb_state
*mrb
, mrb_value num
)
675 mrb_float f
= mrb_float(num
);
677 if (f
> 0.0) f
= floor(f
);
678 if (f
< 0.0) f
= ceil(f
);
680 mrb_check_num_exact(mrb
, f
);
681 if (!FIXABLE_FLOAT(f
)) {
682 return mrb_float_value(mrb
, f
);
684 return mrb_fixnum_value((mrb_int
)f
);
688 flo_nan_p(mrb_state
*mrb
, mrb_value num
)
690 return mrb_bool_value(isnan(mrb_float(num
)));
695 * Document-class: Integer
697 * <code>Integer</code> is the basis for the two concrete classes that
698 * hold whole numbers, <code>Bignum</code> and <code>Fixnum</code>.
705 * int.to_i -> integer
706 * int.to_int -> integer
708 * As <i>int</i> is already an <code>Integer</code>, all these
709 * methods simply return the receiver.
713 int_to_i(mrb_state
*mrb
, mrb_value num
)
719 mrb_fixnum_mul(mrb_state
*mrb
, mrb_value x
, mrb_value y
)
724 if (mrb_fixnum_p(y
)) {
727 if (a
== 0) return x
;
729 if (mrb_int_mul_overflow(a
, b
, &c
)) {
730 #ifndef MRB_WITHOUT_FLOAT
731 return mrb_float_value(mrb
, (mrb_float
)a
* (mrb_float
)b
);
734 return mrb_fixnum_value(c
);
736 #ifdef MRB_WITHOUT_FLOAT
737 mrb_raise(mrb
, E_TYPE_ERROR
, "non fixnum value");
739 return mrb_float_value(mrb
, (mrb_float
)a
* mrb_to_flo(mrb
, y
));
746 * fix * numeric -> numeric_result
748 * Performs multiplication: the class of the resulting object depends on
749 * the class of <code>numeric</code> and on the magnitude of the
754 fix_mul(mrb_state
*mrb
, mrb_value x
)
758 mrb_get_args(mrb
, "o", &y
);
759 return mrb_fixnum_mul(mrb
, x
, y
);
763 fixdivmod(mrb_state
*mrb
, mrb_int x
, mrb_int y
, mrb_int
*divp
, mrb_int
*modp
)
767 /* TODO: add mrb_assert(y != 0) to make sure */
782 if ((mod
< 0 && y
> 0) || (mod
> 0 && y
< 0)) {
786 if (divp
) *divp
= div
;
787 if (modp
) *modp
= mod
;
793 * fix % other -> real
794 * fix.modulo(other) -> real
796 * Returns <code>fix</code> modulo <code>other</code>.
797 * See <code>numeric.divmod</code> for more information.
801 fix_mod(mrb_state
*mrb
, mrb_value x
)
806 mrb_get_args(mrb
, "o", &y
);
808 if (mrb_fixnum_p(y
)) {
811 if ((b
=mrb_fixnum(y
)) == 0) {
812 #ifdef MRB_WITHOUT_FLOAT
813 /* ZeroDivisionError */
814 return mrb_fixnum_value(0);
816 return mrb_float_value(mrb
, NAN
);
819 fixdivmod(mrb
, a
, b
, 0, &mod
);
820 return mrb_fixnum_value(mod
);
822 #ifdef MRB_WITHOUT_FLOAT
823 mrb_raise(mrb
, E_TYPE_ERROR
, "non fixnum value");
828 flodivmod(mrb
, (mrb_float
)a
, mrb_to_flo(mrb
, y
), 0, &mod
);
829 return mrb_float_value(mrb
, mod
);
836 * fix.divmod(numeric) -> array
838 * See <code>Numeric#divmod</code>.
841 fix_divmod(mrb_state
*mrb
, mrb_value x
)
845 mrb_get_args(mrb
, "o", &y
);
847 if (mrb_fixnum_p(y
)) {
850 if (mrb_fixnum(y
) == 0) {
851 #ifdef MRB_WITHOUT_FLOAT
852 return mrb_assoc_new(mrb
, mrb_fixnum_value(0), mrb_fixnum_value(0));
854 return mrb_assoc_new(mrb
, ((mrb_fixnum(x
) == 0) ?
855 mrb_float_value(mrb
, NAN
):
856 mrb_float_value(mrb
, INFINITY
)),
857 mrb_float_value(mrb
, NAN
));
860 fixdivmod(mrb
, mrb_fixnum(x
), mrb_fixnum(y
), &div
, &mod
);
861 return mrb_assoc_new(mrb
, mrb_fixnum_value(div
), mrb_fixnum_value(mod
));
863 #ifdef MRB_WITHOUT_FLOAT
864 mrb_raise(mrb
, E_TYPE_ERROR
, "non fixnum value");
870 flodivmod(mrb
, (mrb_float
)mrb_fixnum(x
), mrb_to_flo(mrb
, y
), &div
, &mod
);
871 a
= mrb_float_value(mrb
, div
);
872 b
= mrb_float_value(mrb
, mod
);
873 return mrb_assoc_new(mrb
, a
, b
);
878 #ifndef MRB_WITHOUT_FLOAT
880 flo_divmod(mrb_state
*mrb
, mrb_value x
)
886 mrb_get_args(mrb
, "o", &y
);
888 flodivmod(mrb
, mrb_float(x
), mrb_to_flo(mrb
, y
), &div
, &mod
);
889 a
= mrb_float_value(mrb
, div
);
890 b
= mrb_float_value(mrb
, mod
);
891 return mrb_assoc_new(mrb
, a
, b
);
898 * fix == other -> true or false
900 * Return <code>true</code> if <code>fix</code> equals <code>other</code>
908 fix_equal(mrb_state
*mrb
, mrb_value x
)
912 mrb_get_args(mrb
, "o", &y
);
913 switch (mrb_type(y
)) {
915 return mrb_bool_value(mrb_fixnum(x
) == mrb_fixnum(y
));
916 #ifndef MRB_WITHOUT_FLOAT
918 return mrb_bool_value((mrb_float
)mrb_fixnum(x
) == mrb_float(y
));
921 return mrb_false_value();
930 * One's complement: returns a number where each bit is flipped.
931 * ex.0---00001 (1)-> 1---11110 (-2)
932 * ex.0---00010 (2)-> 1---11101 (-3)
933 * ex.0---00100 (4)-> 1---11011 (-5)
937 fix_rev(mrb_state
*mrb
, mrb_value num
)
939 mrb_int val
= mrb_fixnum(num
);
941 return mrb_fixnum_value(~val
);
944 #ifdef MRB_WITHOUT_FLOAT
945 #define bit_op(x,y,op1,op2) do {\
946 return mrb_fixnum_value(mrb_fixnum(x) op2 mrb_fixnum(y));\
949 static mrb_value
flo_and(mrb_state
*mrb
, mrb_value x
);
950 static mrb_value
flo_or(mrb_state
*mrb
, mrb_value x
);
951 static mrb_value
flo_xor(mrb_state
*mrb
, mrb_value x
);
952 #define bit_op(x,y,op1,op2) do {\
953 if (mrb_fixnum_p(y)) return mrb_fixnum_value(mrb_fixnum(x) op2 mrb_fixnum(y));\
954 return flo_ ## op1(mrb, mrb_float_value(mrb, (mrb_float)mrb_fixnum(x)));\
961 * fix & integer -> integer_result
967 fix_and(mrb_state
*mrb
, mrb_value x
)
971 mrb_get_args(mrb
, "o", &y
);
972 bit_op(x
, y
, and, &);
978 * fix | integer -> integer_result
984 fix_or(mrb_state
*mrb
, mrb_value x
)
988 mrb_get_args(mrb
, "o", &y
);
995 * fix ^ integer -> integer_result
997 * Bitwise EXCLUSIVE OR.
1001 fix_xor(mrb_state
*mrb
, mrb_value x
)
1005 mrb_get_args(mrb
, "o", &y
);
1006 bit_op(x
, y
, or, ^);
1009 #define NUMERIC_SHIFT_WIDTH_MAX (MRB_INT_BIT-1)
1012 lshift(mrb_state
*mrb
, mrb_int val
, mrb_int width
)
1014 if (width
< 0) { /* mrb_int overflow */
1015 #ifdef MRB_WITHOUT_FLOAT
1016 return mrb_fixnum_value(0);
1018 return mrb_float_value(mrb
, INFINITY
);
1022 if ((width
> NUMERIC_SHIFT_WIDTH_MAX
) ||
1023 (val
> (MRB_INT_MAX
>> width
))) {
1024 #ifdef MRB_WITHOUT_FLOAT
1025 return mrb_fixnum_value(-1);
1030 return mrb_fixnum_value(val
<< width
);
1033 if ((width
> NUMERIC_SHIFT_WIDTH_MAX
) ||
1034 (val
< (MRB_INT_MIN
>> width
))) {
1035 #ifdef MRB_WITHOUT_FLOAT
1036 return mrb_fixnum_value(0);
1041 return mrb_fixnum_value(val
* ((mrb_int
)1 << width
));
1044 #ifndef MRB_WITHOUT_FLOAT
1047 mrb_float f
= (mrb_float
)val
;
1051 return mrb_float_value(mrb
, f
);
1057 rshift(mrb_int val
, mrb_int width
)
1059 if (width
< 0) { /* mrb_int overflow */
1060 return mrb_fixnum_value(0);
1062 if (width
>= NUMERIC_SHIFT_WIDTH_MAX
) {
1064 return mrb_fixnum_value(-1);
1066 return mrb_fixnum_value(0);
1068 return mrb_fixnum_value(val
>> width
);
1074 * fix << count -> integer or float
1076 * Shifts _fix_ left _count_ positions (right if _count_ is negative).
1080 fix_lshift(mrb_state
*mrb
, mrb_value x
)
1084 mrb_get_args(mrb
, "i", &width
);
1088 val
= mrb_fixnum(x
);
1089 if (val
== 0) return x
;
1091 return rshift(val
, -width
);
1093 return lshift(mrb
, val
, width
);
1099 * fix >> count -> integer or float
1101 * Shifts _fix_ right _count_ positions (left if _count_ is negative).
1105 fix_rshift(mrb_state
*mrb
, mrb_value x
)
1109 mrb_get_args(mrb
, "i", &width
);
1113 val
= mrb_fixnum(x
);
1114 if (val
== 0) return x
;
1116 return lshift(mrb
, val
, -width
);
1118 return rshift(val
, width
);
1126 * Converts <i>fix</i> to a <code>Float</code>.
1130 #ifndef MRB_WITHOUT_FLOAT
1132 fix_to_f(mrb_state
*mrb
, mrb_value num
)
1134 return mrb_float_value(mrb
, (mrb_float
)mrb_fixnum(num
));
1138 * Document-class: FloatDomainError
1140 * Raised when attempting to convert special float values
1141 * (in particular infinite or NaN)
1142 * to numerical classes which don't support them.
1144 * Float::INFINITY.to_r
1146 * <em>raises the exception:</em>
1148 * FloatDomainError: Infinity
1150 /* ------------------------------------------------------------------------*/
1152 mrb_flo_to_fixnum(mrb_state
*mrb
, mrb_value x
)
1156 if (!mrb_float_p(x
)) {
1157 mrb_raise(mrb
, E_TYPE_ERROR
, "non float value");
1158 z
= 0; /* not reached. just suppress warnings. */
1161 mrb_float d
= mrb_float(x
);
1164 mrb_raise(mrb
, E_FLOATDOMAIN_ERROR
, d
< 0 ? "-Infinity" : "Infinity");
1167 mrb_raise(mrb
, E_FLOATDOMAIN_ERROR
, "NaN");
1169 if (FIXABLE_FLOAT(d
)) {
1173 mrb_raisef(mrb
, E_ARGUMENT_ERROR
, "number (%S) too big for integer", x
);
1176 return mrb_fixnum_value(z
);
1181 mrb_fixnum_plus(mrb_state
*mrb
, mrb_value x
, mrb_value y
)
1186 if (mrb_fixnum_p(y
)) {
1189 if (a
== 0) return y
;
1191 if (mrb_int_add_overflow(a
, b
, &c
)) {
1192 #ifndef MRB_WITHOUT_FLOAT
1193 return mrb_float_value(mrb
, (mrb_float
)a
+ (mrb_float
)b
);
1196 return mrb_fixnum_value(c
);
1198 #ifdef MRB_WITHOUT_FLOAT
1199 mrb_raise(mrb
, E_TYPE_ERROR
, "non fixnum value");
1201 return mrb_float_value(mrb
, (mrb_float
)a
+ mrb_to_flo(mrb
, y
));
1208 * fix + numeric -> numeric_result
1210 * Performs addition: the class of the resulting object depends on
1211 * the class of <code>numeric</code> and on the magnitude of the
1215 fix_plus(mrb_state
*mrb
, mrb_value self
)
1219 mrb_get_args(mrb
, "o", &other
);
1220 return mrb_fixnum_plus(mrb
, self
, other
);
1224 mrb_fixnum_minus(mrb_state
*mrb
, mrb_value x
, mrb_value y
)
1229 if (mrb_fixnum_p(y
)) {
1233 if (mrb_int_sub_overflow(a
, b
, &c
)) {
1234 #ifndef MRB_WITHOUT_FLOAT
1235 return mrb_float_value(mrb
, (mrb_float
)a
- (mrb_float
)b
);
1238 return mrb_fixnum_value(c
);
1240 #ifdef MRB_WITHOUT_FLOAT
1241 mrb_raise(mrb
, E_TYPE_ERROR
, "non fixnum value");
1243 return mrb_float_value(mrb
, (mrb_float
)a
- mrb_to_flo(mrb
, y
));
1251 * fix - numeric -> numeric_result
1253 * Performs subtraction: the class of the resulting object depends on
1254 * the class of <code>numeric</code> and on the magnitude of the
1258 fix_minus(mrb_state
*mrb
, mrb_value self
)
1262 mrb_get_args(mrb
, "o", &other
);
1263 return mrb_fixnum_minus(mrb
, self
, other
);
1268 mrb_fixnum_to_str(mrb_state
*mrb
, mrb_value x
, mrb_int base
)
1270 char buf
[MRB_INT_BIT
+1];
1271 char *b
= buf
+ sizeof buf
;
1272 mrb_int val
= mrb_fixnum(x
);
1274 if (base
< 2 || 36 < base
) {
1275 mrb_raisef(mrb
, E_ARGUMENT_ERROR
, "invalid radix %S", mrb_fixnum_value(base
));
1283 *--b
= mrb_digitmap
[-(val
% base
)];
1284 } while (val
/= base
);
1289 *--b
= mrb_digitmap
[(int)(val
% base
)];
1290 } while (val
/= base
);
1293 return mrb_str_new(mrb
, b
, buf
+ sizeof(buf
) - b
);
1299 * fix.to_s(base=10) -> string
1301 * Returns a string containing the representation of <i>fix</i> radix
1302 * <i>base</i> (between 2 and 36).
1304 * 12345.to_s #=> "12345"
1305 * 12345.to_s(2) #=> "11000000111001"
1306 * 12345.to_s(8) #=> "30071"
1307 * 12345.to_s(10) #=> "12345"
1308 * 12345.to_s(16) #=> "3039"
1309 * 12345.to_s(36) #=> "9ix"
1313 fix_to_s(mrb_state
*mrb
, mrb_value self
)
1317 mrb_get_args(mrb
, "|i", &base
);
1318 return mrb_fixnum_to_str(mrb
, self
, base
);
1321 /* compare two numbers: (1:0:-1; -2 for error) */
1323 cmpnum(mrb_state
*mrb
, mrb_value v1
, mrb_value v2
)
1325 #ifdef MRB_WITHOUT_FLOAT
1331 #ifdef MRB_WITHOUT_FLOAT
1334 x
= mrb_to_flo(mrb
, v1
);
1336 switch (mrb_type(v2
)) {
1338 #ifdef MRB_WITHOUT_FLOAT
1341 y
= (mrb_float
)mrb_fixnum(v2
);
1344 #ifndef MRB_WITHOUT_FLOAT
1364 * self.f <=> other.f => -1, 0, +1
1368 * Comparison---Returns -1, 0, or +1 depending on whether <i>fix</i> is
1369 * less than, equal to, or greater than <i>numeric</i>. This is the
1370 * basis for the tests in <code>Comparable</code>.
1373 num_cmp(mrb_state
*mrb
, mrb_value self
)
1378 mrb_get_args(mrb
, "o", &other
);
1379 n
= cmpnum(mrb
, self
, other
);
1380 if (n
== -2) return mrb_nil_value();
1381 return mrb_fixnum_value(n
);
1385 cmperr(mrb_state
*mrb
, mrb_value v1
, mrb_value v2
)
1387 mrb_raisef(mrb
, E_ARGUMENT_ERROR
, "comparison of %S with %S failed",
1388 mrb_obj_value(mrb_class(mrb
, v1
)),
1389 mrb_obj_value(mrb_class(mrb
, v2
)));
1393 num_lt(mrb_state
*mrb
, mrb_value self
)
1398 mrb_get_args(mrb
, "o", &other
);
1399 n
= cmpnum(mrb
, self
, other
);
1400 if (n
== -2) cmperr(mrb
, self
, other
);
1401 if (n
< 0) return mrb_true_value();
1402 return mrb_false_value();
1406 num_le(mrb_state
*mrb
, mrb_value self
)
1411 mrb_get_args(mrb
, "o", &other
);
1412 n
= cmpnum(mrb
, self
, other
);
1413 if (n
== -2) cmperr(mrb
, self
, other
);
1414 if (n
<= 0) return mrb_true_value();
1415 return mrb_false_value();
1419 num_gt(mrb_state
*mrb
, mrb_value self
)
1424 mrb_get_args(mrb
, "o", &other
);
1425 n
= cmpnum(mrb
, self
, other
);
1426 if (n
== -2) cmperr(mrb
, self
, other
);
1427 if (n
> 0) return mrb_true_value();
1428 return mrb_false_value();
1432 num_ge(mrb_state
*mrb
, mrb_value self
)
1437 mrb_get_args(mrb
, "o", &other
);
1438 n
= cmpnum(mrb
, self
, other
);
1439 if (n
== -2) cmperr(mrb
, self
, other
);
1440 if (n
>= 0) return mrb_true_value();
1441 return mrb_false_value();
1445 num_finite_p(mrb_state
*mrb
, mrb_value self
)
1447 mrb_get_args(mrb
, "");
1448 return mrb_true_value();
1452 num_infinite_p(mrb_state
*mrb
, mrb_value self
)
1454 mrb_get_args(mrb
, "");
1455 return mrb_false_value();
1461 * float + other -> float
1463 * Returns a new float which is the sum of <code>float</code>
1464 * and <code>other</code>.
1466 #ifndef MRB_WITHOUT_FLOAT
1468 flo_plus(mrb_state
*mrb
, mrb_value x
)
1472 mrb_get_args(mrb
, "o", &y
);
1473 return mrb_float_value(mrb
, mrb_float(x
) + mrb_to_flo(mrb
, y
));
1477 /* ------------------------------------------------------------------------*/
1479 mrb_init_numeric(mrb_state
*mrb
)
1481 struct RClass
*numeric
, *integer
, *fixnum
;
1482 #ifndef MRB_WITHOUT_FLOAT
1487 numeric
= mrb_define_class(mrb
, "Numeric", mrb
->object_class
); /* 15.2.7 */
1489 mrb_define_method(mrb
, numeric
, "**", num_pow
, MRB_ARGS_REQ(1));
1490 mrb_define_method(mrb
, numeric
, "/", num_div
, MRB_ARGS_REQ(1)); /* 15.2.8.3.4 */
1491 mrb_define_method(mrb
, numeric
, "quo", num_div
, MRB_ARGS_REQ(1)); /* 15.2.7.4.5 (x) */
1492 mrb_define_method(mrb
, numeric
, "<=>", num_cmp
, MRB_ARGS_REQ(1)); /* 15.2.9.3.6 */
1493 mrb_define_method(mrb
, numeric
, "<", num_lt
, MRB_ARGS_REQ(1));
1494 mrb_define_method(mrb
, numeric
, "<=", num_le
, MRB_ARGS_REQ(1));
1495 mrb_define_method(mrb
, numeric
, ">", num_gt
, MRB_ARGS_REQ(1));
1496 mrb_define_method(mrb
, numeric
, ">=", num_ge
, MRB_ARGS_REQ(1));
1497 mrb_define_method(mrb
, numeric
, "finite?", num_finite_p
, MRB_ARGS_NONE());
1498 mrb_define_method(mrb
, numeric
, "infinite?",num_infinite_p
, MRB_ARGS_NONE());
1501 integer
= mrb_define_class(mrb
, "Integer", numeric
); /* 15.2.8 */
1502 MRB_SET_INSTANCE_TT(integer
, MRB_TT_FIXNUM
);
1503 mrb_undef_class_method(mrb
, integer
, "new");
1504 mrb_define_method(mrb
, integer
, "to_i", int_to_i
, MRB_ARGS_NONE()); /* 15.2.8.3.24 */
1505 mrb_define_method(mrb
, integer
, "to_int", int_to_i
, MRB_ARGS_NONE());
1506 #ifndef MRB_WITHOUT_FLOAT
1507 mrb_define_method(mrb
, integer
, "ceil", int_to_i
, MRB_ARGS_REQ(1)); /* 15.2.8.3.8 (x) */
1508 mrb_define_method(mrb
, integer
, "floor", int_to_i
, MRB_ARGS_REQ(1)); /* 15.2.8.3.10 (x) */
1509 mrb_define_method(mrb
, integer
, "round", int_to_i
, MRB_ARGS_REQ(1)); /* 15.2.8.3.12 (x) */
1510 mrb_define_method(mrb
, integer
, "truncate", int_to_i
, MRB_ARGS_REQ(1)); /* 15.2.8.3.15 (x) */
1514 mrb
->fixnum_class
= fixnum
= mrb_define_class(mrb
, "Fixnum", integer
);
1515 mrb_define_method(mrb
, fixnum
, "+", fix_plus
, MRB_ARGS_REQ(1)); /* 15.2.8.3.1 */
1516 mrb_define_method(mrb
, fixnum
, "-", fix_minus
, MRB_ARGS_REQ(1)); /* 15.2.8.3.2 */
1517 mrb_define_method(mrb
, fixnum
, "*", fix_mul
, MRB_ARGS_REQ(1)); /* 15.2.8.3.3 */
1518 mrb_define_method(mrb
, fixnum
, "%", fix_mod
, MRB_ARGS_REQ(1)); /* 15.2.8.3.5 */
1519 mrb_define_method(mrb
, fixnum
, "==", fix_equal
, MRB_ARGS_REQ(1)); /* 15.2.8.3.7 */
1520 mrb_define_method(mrb
, fixnum
, "~", fix_rev
, MRB_ARGS_NONE()); /* 15.2.8.3.8 */
1521 mrb_define_method(mrb
, fixnum
, "&", fix_and
, MRB_ARGS_REQ(1)); /* 15.2.8.3.9 */
1522 mrb_define_method(mrb
, fixnum
, "|", fix_or
, MRB_ARGS_REQ(1)); /* 15.2.8.3.10 */
1523 mrb_define_method(mrb
, fixnum
, "^", fix_xor
, MRB_ARGS_REQ(1)); /* 15.2.8.3.11 */
1524 mrb_define_method(mrb
, fixnum
, "<<", fix_lshift
, MRB_ARGS_REQ(1)); /* 15.2.8.3.12 */
1525 mrb_define_method(mrb
, fixnum
, ">>", fix_rshift
, MRB_ARGS_REQ(1)); /* 15.2.8.3.13 */
1526 mrb_define_method(mrb
, fixnum
, "eql?", fix_eql
, MRB_ARGS_REQ(1)); /* 15.2.8.3.16 */
1527 #ifndef MRB_WITHOUT_FLOAT
1528 mrb_define_method(mrb
, fixnum
, "to_f", fix_to_f
, MRB_ARGS_NONE()); /* 15.2.8.3.23 */
1530 mrb_define_method(mrb
, fixnum
, "to_s", fix_to_s
, MRB_ARGS_NONE()); /* 15.2.8.3.25 */
1531 mrb_define_method(mrb
, fixnum
, "inspect", fix_to_s
, MRB_ARGS_NONE());
1532 mrb_define_method(mrb
, fixnum
, "divmod", fix_divmod
, MRB_ARGS_REQ(1)); /* 15.2.8.3.30 (x) */
1534 #ifndef MRB_WITHOUT_FLOAT
1536 mrb
->float_class
= fl
= mrb_define_class(mrb
, "Float", numeric
); /* 15.2.9 */
1537 MRB_SET_INSTANCE_TT(fl
, MRB_TT_FLOAT
);
1538 mrb_undef_class_method(mrb
, fl
, "new");
1539 mrb_define_method(mrb
, fl
, "+", flo_plus
, MRB_ARGS_REQ(1)); /* 15.2.9.3.1 */
1540 mrb_define_method(mrb
, fl
, "-", flo_minus
, MRB_ARGS_REQ(1)); /* 15.2.9.3.2 */
1541 mrb_define_method(mrb
, fl
, "*", flo_mul
, MRB_ARGS_REQ(1)); /* 15.2.9.3.3 */
1542 mrb_define_method(mrb
, fl
, "%", flo_mod
, MRB_ARGS_REQ(1)); /* 15.2.9.3.5 */
1543 mrb_define_method(mrb
, fl
, "==", flo_eq
, MRB_ARGS_REQ(1)); /* 15.2.9.3.7 */
1544 mrb_define_method(mrb
, fl
, "~", flo_rev
, MRB_ARGS_NONE());
1545 mrb_define_method(mrb
, fl
, "&", flo_and
, MRB_ARGS_REQ(1));
1546 mrb_define_method(mrb
, fl
, "|", flo_or
, MRB_ARGS_REQ(1));
1547 mrb_define_method(mrb
, fl
, "^", flo_xor
, MRB_ARGS_REQ(1));
1548 mrb_define_method(mrb
, fl
, ">>", flo_lshift
, MRB_ARGS_REQ(1));
1549 mrb_define_method(mrb
, fl
, "<<", flo_rshift
, MRB_ARGS_REQ(1));
1550 mrb_define_method(mrb
, fl
, "ceil", flo_ceil
, MRB_ARGS_NONE()); /* 15.2.9.3.8 */
1551 mrb_define_method(mrb
, fl
, "finite?", flo_finite_p
, MRB_ARGS_NONE()); /* 15.2.9.3.9 */
1552 mrb_define_method(mrb
, fl
, "floor", flo_floor
, MRB_ARGS_NONE()); /* 15.2.9.3.10 */
1553 mrb_define_method(mrb
, fl
, "infinite?", flo_infinite_p
, MRB_ARGS_NONE()); /* 15.2.9.3.11 */
1554 mrb_define_method(mrb
, fl
, "round", flo_round
, MRB_ARGS_OPT(1)); /* 15.2.9.3.12 */
1555 mrb_define_method(mrb
, fl
, "to_f", flo_to_f
, MRB_ARGS_NONE()); /* 15.2.9.3.13 */
1556 mrb_define_method(mrb
, fl
, "to_i", flo_truncate
, MRB_ARGS_NONE()); /* 15.2.9.3.14 */
1557 mrb_define_method(mrb
, fl
, "to_int", flo_truncate
, MRB_ARGS_NONE());
1558 mrb_define_method(mrb
, fl
, "truncate", flo_truncate
, MRB_ARGS_NONE()); /* 15.2.9.3.15 */
1559 mrb_define_method(mrb
, fl
, "divmod", flo_divmod
, MRB_ARGS_REQ(1));
1560 mrb_define_method(mrb
, fl
, "eql?", flo_eql
, MRB_ARGS_REQ(1)); /* 15.2.8.3.16 */
1562 mrb_define_method(mrb
, fl
, "to_s", flo_to_s
, MRB_ARGS_NONE()); /* 15.2.9.3.16(x) */
1563 mrb_define_method(mrb
, fl
, "inspect", flo_to_s
, MRB_ARGS_NONE());
1564 mrb_define_method(mrb
, fl
, "nan?", flo_nan_p
, MRB_ARGS_NONE());
1567 mrb_define_const(mrb
, fl
, "INFINITY", mrb_float_value(mrb
, INFINITY
));
1570 mrb_define_const(mrb
, fl
, "NAN", mrb_float_value(mrb
, NAN
));
1573 mrb_define_module(mrb
, "Integral");