2 ** numeric.c - Numeric, Integer, Float class
4 ** See Copyright Notice in mruby.h
8 #include <mruby/array.h>
9 #include <mruby/numeric.h>
10 #include <mruby/string.h>
11 #include <mruby/class.h>
12 #include <mruby/internal.h>
13 #include <mruby/presym.h>
17 #ifdef MRB_USE_FLOAT32
18 #define trunc(f) truncf(f)
19 #define fmod(x,y) fmodf(x,y)
25 mrb_int_overflow(mrb_state
*mrb
, const char *reason
)
27 mrb_raisef(mrb
, E_RANGE_ERROR
, "integer overflow in %s", reason
);
31 mrb_int_zerodiv(mrb_state
*mrb
)
33 mrb_raise(mrb
, E_ZERODIV_ERROR
, "divided by 0");
36 static mrb_noreturn
void
37 mrb_int_noconv(mrb_state
*mrb
, mrb_value y
)
39 mrb_raisef(mrb
, E_TYPE_ERROR
, "can't convert %Y into Integer", y
);
43 mrb_int_pow(mrb_state
*mrb
, mrb_value x
, mrb_value y
)
46 if (mrb_bigint_p(x
)) {
49 return mrb_float_value(mrb
, pow(mrb_bint_as_float(mrb
, x
), mrb_float(y
)));
52 return mrb_bint_pow(mrb
, x
, y
);
55 mrb_int base
= mrb_integer(x
);
61 return mrb_float_value(mrb
, pow((double)base
, mrb_float(y
)));
63 else if (mrb_integer_p(y
)) {
69 exp
= mrb_as_int(mrb
, y
);
73 return mrb_float_value(mrb
, pow((double)base
, (double)exp
));
75 mrb_int_overflow(mrb
, "negative power");
80 if (mrb_int_mul_overflow(result
, base
, &result
)) {
82 return mrb_bint_pow(mrb
, mrb_bint_new_int(mrb
, mrb_integer(x
)), y
);
84 mrb_int_overflow(mrb
, "power");
90 if (mrb_int_mul_overflow(base
, base
, &base
)) {
92 return mrb_bint_pow(mrb
, mrb_bint_new_int(mrb
, mrb_integer(x
)), y
);
94 mrb_int_overflow(mrb
, "power");
98 return mrb_int_value(mrb
, result
);
104 * num ** other -> num
106 * Raises <code>num</code> the <code>other</code> power.
111 int_pow(mrb_state
*mrb
, mrb_value x
)
113 return mrb_int_pow(mrb
, x
, mrb_get_arg1(mrb
));
117 mrb_div_int(mrb_int x
, mrb_int y
)
121 if ((x
^ y
) < 0 && x
!= div
* y
) {
128 mrb_div_int_value(mrb_state
*mrb
, mrb_int x
, mrb_int y
)
131 mrb_int_zerodiv(mrb
);
133 else if (x
== MRB_INT_MIN
&& y
== -1) {
134 #ifdef MRB_USE_BIGINT
135 return mrb_bint_mul_ii(mrb
, x
, y
);
137 mrb_int_overflow(mrb
, "division");
140 return mrb_int_value(mrb
, mrb_div_int(x
, y
));
148 * Performs division: the class of the resulting object depends on
149 * the class of <code>num</code> and on the magnitude of the
153 int_div(mrb_state
*mrb
, mrb_value x
)
155 mrb_value y
= mrb_get_arg1(mrb
);
156 #ifdef MRB_USE_BIGINT
157 if (mrb_bigint_p(x
)) {
158 return mrb_bint_div(mrb
, x
, y
);
161 mrb_int a
= mrb_integer(x
);
163 if (mrb_integer_p(y
)) {
164 return mrb_div_int_value(mrb
, a
, mrb_integer(y
));
166 switch (mrb_type(y
)) {
167 #ifdef MRB_USE_BIGINT
169 return mrb_bint_div(mrb
, mrb_bint_new_int(mrb
, a
), y
);
171 #ifdef MRB_USE_RATIONAL
172 case MRB_TT_RATIONAL
:
173 return mrb_rational_div(mrb
, mrb_rational_new(mrb
, a
, 1), y
);
175 #ifdef MRB_USE_COMPLEX
177 x
= mrb_complex_new(mrb
, (mrb_float
)a
, 0);
178 return mrb_complex_div(mrb
, x
, y
);
182 return mrb_float_value(mrb
, mrb_div_float((mrb_float
)a
, mrb_as_float(mrb
, y
)));
185 mrb_int_noconv(mrb
, y
);
192 * num.quo(numeric) -> real
194 * Returns most exact division.
199 * int.div(other) -> int
201 * Performs division: resulting integer.
204 int_idiv(mrb_state
*mrb
, mrb_value x
)
206 #ifdef MRB_USE_BIGINT
207 if (mrb_bigint_p(x
)) {
208 return mrb_bint_div(mrb
, x
, mrb_get_arg1(mrb
));
211 mrb_int y
= mrb_as_int(mrb
, mrb_get_arg1(mrb
));
212 return mrb_div_int_value(mrb
, mrb_integer(x
), y
);
216 int_quo(mrb_state
*mrb
, mrb_value x
)
218 #ifndef MRB_USE_RATIONAL
220 return int_idiv(mrb
, x
);
222 mrb_float y
= mrb_as_float(mrb
, mrb_get_arg1(mrb
));
225 mrb_int_zerodiv(mrb
);
227 #ifdef MRB_USE_BIGINT
228 if (mrb_bigint_p(x
)) {
229 return mrb_float_value(mrb
, mrb_bint_as_float(mrb
, x
) / y
);
232 return mrb_float_value(mrb
, mrb_integer(x
) / y
);
235 mrb_int a
= mrb_integer(x
);
236 mrb_value y
= mrb_get_arg1(mrb
);
237 if (mrb_integer_p(y
) && mrb_class_defined_id(mrb
, MRB_SYM(Rational
))) {
238 return mrb_rational_new(mrb
, a
, mrb_integer(y
));
240 switch (mrb_type(y
)) {
241 case MRB_TT_RATIONAL
:
242 x
= mrb_rational_new(mrb
, a
, 1);
243 return mrb_rational_div(mrb
, x
, y
);
246 return mrb_float_value(mrb
, mrb_div_float((mrb_float
)a
, mrb_as_float(mrb
, y
)));
248 mrb_int_noconv(mrb
, y
);
256 coerce_step_counter(mrb_state
*mrb
, mrb_value self
)
260 mrb_get_args(mrb
, "oo", &num
, &step
);
264 if (mrb_float_p(num
) || mrb_float_p(step
)) {
265 return mrb_ensure_float_type(mrb
, self
);
273 /********************************************************************
275 * Document-class: Float
277 * <code>Float</code> objects represent inexact real numbers using
278 * the native architecture's double-precision floating-point
283 flo_pow(mrb_state
*mrb
, mrb_value x
)
285 mrb_value y
= mrb_get_arg1(mrb
);
286 mrb_float d
= pow(mrb_as_float(mrb
, x
), mrb_as_float(mrb
, y
));
287 return mrb_float_value(mrb
, d
);
291 flo_idiv(mrb_state
*mrb
, mrb_value xv
)
293 mrb_float x
= mrb_float(xv
);
294 mrb_check_num_exact(mrb
, x
);
295 mrb_int y
= mrb_as_int(mrb
, mrb_get_arg1(mrb
));
296 return mrb_div_int_value(mrb
, (mrb_int
)x
, y
);
300 mrb_div_float(mrb_float x
, mrb_float y
)
309 return x
* (signbit(y
) ? -1.0 : 1.0) * INFINITY
;
316 * float / num -> float
318 * Returns a new Float which is the result of dividing float by num.
321 flo_div(mrb_state
*mrb
, mrb_value x
)
323 mrb_value y
= mrb_get_arg1(mrb
);
324 mrb_float a
= mrb_float(x
);
326 switch(mrb_type(y
)) {
327 #ifdef MRB_USE_COMPLEX
329 return mrb_complex_div(mrb
, mrb_complex_new(mrb
, a
, 0), y
);
332 a
= mrb_div_float(a
, mrb_float(y
));
333 return mrb_float_value(mrb
, a
);
335 a
= mrb_div_float(a
, mrb_as_float(mrb
, y
));
336 return mrb_float_value(mrb
, a
);
338 return mrb_float_value(mrb
, a
);
341 /* the argument `fmt` is no longer used; you can pass `NULL` */
343 mrb_float_to_str(mrb_state
*mrb
, mrb_value flo
, const char *fmt
)
346 #ifdef MRB_USE_FLOAT32
352 mrb_format_float(mrb_float(flo
), buf
, sizeof(buf
), 'g', prec
, '\0');
353 for (char *p
= buf
; *p
; p
++) {
354 if (*p
== '.') goto exit
;
356 memmove(p
+2, p
, strlen(p
)+1);
364 return mrb_str_new_cstr(mrb
, buf
);
371 * flt.inspect -> string
373 * Returns a string containing a representation of self. As well as a
374 * fixed or exponential form of the number, the call may return
375 * "<code>NaN</code>", "<code>Infinity</code>", and
376 * "<code>-Infinity</code>".
383 flo_to_s(mrb_state
*mrb
, mrb_value flt
)
385 mrb_float f
= mrb_float(flt
);
389 str
= f
< 0 ? mrb_str_new_lit(mrb
, "-Infinity")
390 : mrb_str_new_lit(mrb
, "Infinity");
393 str
= mrb_str_new_lit(mrb
, "NaN");
396 str
= mrb_float_to_str(mrb
, flt
, NULL
);
399 RSTR_SET_ASCII_FLAG(mrb_str_ptr(str
));
406 * float + other -> float
408 * Returns a new float which is the sum of <code>float</code>
409 * and <code>other</code>.
412 flo_add(mrb_state
*mrb
, mrb_value x
)
414 mrb_value y
= mrb_get_arg1(mrb
);
415 mrb_float a
= mrb_float(x
);
417 switch (mrb_type(y
)) {
419 return mrb_float_value(mrb
, a
+ mrb_float(y
));
420 #if defined(MRB_USE_COMPLEX)
422 return mrb_complex_add(mrb
, y
, x
);
425 return mrb_float_value(mrb
, a
+ mrb_as_float(mrb
, y
));
432 * float - other -> float
434 * Returns a new float which is the difference of <code>float</code>
435 * and <code>other</code>.
439 flo_sub(mrb_state
*mrb
, mrb_value x
)
441 mrb_value y
= mrb_get_arg1(mrb
);
442 mrb_float a
= mrb_float(x
);
444 switch (mrb_type(y
)) {
446 return mrb_float_value(mrb
, a
- mrb_float(y
));
447 #if defined(MRB_USE_COMPLEX)
449 return mrb_complex_sub(mrb
, mrb_complex_new(mrb
, a
, 0), y
);
452 return mrb_float_value(mrb
, a
- mrb_as_float(mrb
, y
));
459 * float * other -> float
461 * Returns a new float which is the product of <code>float</code>
462 * and <code>other</code>.
466 flo_mul(mrb_state
*mrb
, mrb_value x
)
468 mrb_value y
= mrb_get_arg1(mrb
);
469 mrb_float a
= mrb_float(x
);
471 switch (mrb_type(y
)) {
473 return mrb_float_value(mrb
, a
* mrb_float(y
));
474 #if defined(MRB_USE_COMPLEX)
476 return mrb_complex_mul(mrb
, y
, x
);
479 return mrb_float_value(mrb
, a
* mrb_as_float(mrb
, y
));
484 flodivmod(mrb_state
*mrb
, double x
, double y
, mrb_float
*divp
, mrb_float
*modp
)
489 /* y is NaN so all results are NaN */
494 mrb_int_zerodiv(mrb
);
496 if (isinf(y
) && !isinf(x
)) {
502 if (isinf(x
) && !isinf(y
)) {
507 if (modp
&& divp
) div
= round(div
);
509 if (div
== 0) div
= 0.0;
510 if (mod
== 0) mod
= 0.0;
516 if (modp
) *modp
= mod
;
517 if (divp
) *divp
= div
;
523 * flt % other -> float
524 * flt.modulo(other) -> float
526 * Return the modulo after division of <code>flt</code> by <code>other</code>.
528 * 6543.21.modulo(137) #=> 104.21
529 * 6543.21.modulo(137.24) #=> 92.9299999999996
533 flo_mod(mrb_state
*mrb
, mrb_value x
)
535 mrb_value y
= mrb_get_arg1(mrb
);
538 flodivmod(mrb
, mrb_float(x
), mrb_as_float(mrb
, y
), NULL
, &mod
);
539 return mrb_float_value(mrb
, mod
);
546 * num.eql?(numeric) -> true or false
548 * Returns <code>true</code> if <i>num</i> and <i>numeric</i> are the
549 * same type and have equal values.
552 * 1.eql?(1.0) #=> false
553 * (1.0).eql?(1.0) #=> true
556 num_eql(mrb_state
*mrb
, mrb_value x
)
558 mrb_value y
= mrb_get_arg1(mrb
);
560 #ifdef MRB_USE_BIGINT
561 if (mrb_bigint_p(x
)) {
562 return mrb_bool_value(mrb_bint_cmp(mrb
, x
, y
) == 0);
566 if (mrb_float_p(x
)) {
567 if (!mrb_float_p(y
)) return mrb_false_value();
568 return mrb_bool_value(mrb_float(x
) == mrb_float(y
));
571 if (mrb_integer_p(x
)) {
572 if (!mrb_integer_p(y
)) return mrb_false_value();
573 return mrb_bool_value(mrb_integer(x
) == mrb_integer(y
));
575 return mrb_bool_value(mrb_equal(mrb
, x
, y
));
582 * flt == obj -> true or false
584 * Returns <code>true</code> only if <i>obj</i> has the same value
585 * as <i>flt</i>. Contrast this with <code>Float#eql?</code>, which
586 * requires <i>obj</i> to be a <code>Float</code>.
593 flo_eq(mrb_state
*mrb
, mrb_value x
)
595 mrb_value y
= mrb_get_arg1(mrb
);
597 switch (mrb_type(y
)) {
599 return mrb_bool_value(mrb_float(x
) == (mrb_float
)mrb_integer(y
));
601 return mrb_bool_value(mrb_float(x
) == mrb_float(y
));
602 #ifdef MRB_USE_RATIONAL
603 case MRB_TT_RATIONAL
:
604 return mrb_bool_value(mrb_float(x
) == mrb_as_float(mrb
, y
));
606 #ifdef MRB_USE_COMPLEX
608 return mrb_bool_value(mrb_equal(mrb
, y
, x
));
611 return mrb_false_value();
617 * Document-method: Float#to_f
622 * As <code>flt</code> is already a float, returns +self+.
628 * flt.infinite? -> nil, -1, +1
630 * Returns <code>nil</code>, -1, or +1 depending on whether <i>flt</i>
631 * is finite, -infinity, or +infinity.
633 * (0.0).infinite? #=> nil
634 * (-1.0/0.0).infinite? #=> -1
635 * (+1.0/0.0).infinite? #=> 1
639 flo_infinite_p(mrb_state
*mrb
, mrb_value num
)
641 mrb_float value
= mrb_float(num
);
644 return mrb_fixnum_value(value
< 0 ? -1 : 1);
646 return mrb_nil_value();
652 * flt.finite? -> true or false
654 * Returns <code>true</code> if <i>flt</i> is a valid IEEE floating
655 * point number (it is not infinite, and <code>nan?</code> is
656 * <code>false</code>).
661 flo_finite_p(mrb_state
*mrb
, mrb_value num
)
663 return mrb_bool_value(isfinite(mrb_float(num
)));
667 * Document-class: FloatDomainError
669 * Raised when attempting to convert special float values
670 * (in particular infinite or NaN)
671 * to numerical classes which don't support them.
673 * Float::INFINITY.to_i
675 * <em>raises the exception:</em>
677 * FloatDomainError: Infinity
679 /* ------------------------------------------------------------------------*/
681 mrb_check_num_exact(mrb_state
*mrb
, mrb_float num
)
684 mrb_raise(mrb
, E_FLOATDOMAIN_ERROR
, num
< 0 ? "-Infinity" : "Infinity");
687 mrb_raise(mrb
, E_FLOATDOMAIN_ERROR
, "NaN");
692 flo_rounding_int(mrb_state
*mrb
, mrb_float f
)
694 if (!FIXABLE_FLOAT(f
)) {
695 #ifdef MRB_USE_BIGINT
696 return mrb_bint_new_float(mrb
, f
);
698 mrb_int_overflow(mrb
, "rounding");
701 return mrb_int_value(mrb
, (mrb_int
)f
);
705 flo_rounding(mrb_state
*mrb
, mrb_value num
, double (*func
)(double))
707 mrb_float f
= mrb_float(num
);
709 #ifdef MRB_USE_FLOAT32
712 const int fprec
= 15;
715 mrb_get_args(mrb
, "|i", &ndigits
);
717 return ndigits
> 0 ? mrb_float_value(mrb
, f
) : mrb_fixnum_value(0);
720 if (ndigits
> fprec
) return num
;
721 mrb_float d
= pow(10, (double)ndigits
);
723 mrb_check_num_exact(mrb
, f
);
724 return mrb_float_value(mrb
, f
);
727 mrb_float d
= pow(10, -(double)ndigits
);
730 else { /* ndigits == 0 */
733 mrb_check_num_exact(mrb
, f
);
734 return flo_rounding_int(mrb
, f
);
740 * float.floor([ndigits]) -> integer or float
742 * Returns the largest number less than or equal to +float+ with
743 * a precision of +ndigits+ decimal digits (default: 0).
745 * When the precision is negative, the returned value is an integer
746 * with at least <code>ndigits.abs</code> trailing zeros.
748 * Returns a floating-point number when +ndigits+ is positive,
749 * otherwise returns an integer.
753 * (-1.2).floor #=> -2
754 * (-2.0).floor #=> -2
756 * 1.234567.floor(2) #=> 1.23
757 * 1.234567.floor(3) #=> 1.234
758 * 1.234567.floor(4) #=> 1.2345
759 * 1.234567.floor(5) #=> 1.23456
761 * 34567.89.floor(-5) #=> 0
762 * 34567.89.floor(-4) #=> 30000
763 * 34567.89.floor(-3) #=> 34000
764 * 34567.89.floor(-2) #=> 34500
765 * 34567.89.floor(-1) #=> 34560
766 * 34567.89.floor(0) #=> 34567
767 * 34567.89.floor(1) #=> 34567.8
768 * 34567.89.floor(2) #=> 34567.89
769 * 34567.89.floor(3) #=> 34567.89
771 * Note that the limited precision of floating-point arithmetic
772 * might lead to surprising results:
774 * (0.3 / 0.1).floor #=> 2 (!)
777 flo_floor(mrb_state
*mrb
, mrb_value num
)
779 return flo_rounding(mrb
, num
, floor
);
785 * float.ceil([ndigits]) -> integer or float
787 * Returns the smallest number greater than or equal to +float+ with
788 * a precision of +ndigits+ decimal digits (default: 0).
790 * When the precision is negative, the returned value is an integer
791 * with at least <code>ndigits.abs</code> trailing zeros.
793 * Returns a floating-point number when +ndigits+ is positive,
794 * otherwise returns an integer.
801 * 1.234567.ceil(2) #=> 1.24
802 * 1.234567.ceil(3) #=> 1.235
803 * 1.234567.ceil(4) #=> 1.2346
804 * 1.234567.ceil(5) #=> 1.23457
806 * 34567.89.ceil(-5) #=> 100000
807 * 34567.89.ceil(-4) #=> 40000
808 * 34567.89.ceil(-3) #=> 35000
809 * 34567.89.ceil(-2) #=> 34600
810 * 34567.89.ceil(-1) #=> 34570
811 * 34567.89.ceil(0) #=> 34568
812 * 34567.89.ceil(1) #=> 34567.9
813 * 34567.89.ceil(2) #=> 34567.89
814 * 34567.89.ceil(3) #=> 34567.89
816 * Note that the limited precision of floating-point arithmetic
817 * might lead to surprising results:
819 * (2.1 / 0.7).ceil #=> 4 (!)
823 flo_ceil(mrb_state
*mrb
, mrb_value num
)
825 return flo_rounding(mrb
, num
, ceil
);
831 * flt.round([ndigits]) -> integer or float
833 * Rounds <i>flt</i> to a given precision in decimal digits (default 0 digits).
834 * Precision may be negative. Returns a floating-point number when ndigits
840 * (-1.5).round #=> -2
842 * 1.234567.round(2) #=> 1.23
843 * 1.234567.round(3) #=> 1.235
844 * 1.234567.round(4) #=> 1.2346
845 * 1.234567.round(5) #=> 1.23457
847 * 34567.89.round(-5) #=> 0
848 * 34567.89.round(-4) #=> 30000
849 * 34567.89.round(-3) #=> 35000
850 * 34567.89.round(-2) #=> 34600
851 * 34567.89.round(-1) #=> 34570
852 * 34567.89.round(0) #=> 34568
853 * 34567.89.round(1) #=> 34567.9
854 * 34567.89.round(2) #=> 34567.89
855 * 34567.89.round(3) #=> 34567.89
860 flo_round(mrb_state
*mrb
, mrb_value num
)
866 mrb_get_args(mrb
, "|i", &ndigits
);
867 number
= mrb_float(num
);
869 if (0 < ndigits
&& (isinf(number
) || isnan(number
))) {
872 mrb_check_num_exact(mrb
, number
);
875 if (ndigits
< -DBL_DIG
-2) return mrb_fixnum_value(0);
876 i
= ndigits
>= 0 ? ndigits
: -ndigits
;
877 if (ndigits
> DBL_DIG
+2) return num
;
882 if (ndigits
< 0) number
= 0;
887 if (ndigits
< 0) number
/= f
;
890 /* home-made inline implementation of round(3) */
893 number
= d
+ (number
- d
>= 0.5);
895 else if (number
< 0.0) {
897 number
= d
- (d
- number
>= 0.5);
900 if (ndigits
< 0) number
*= f
;
905 if (!isfinite(number
)) return num
;
906 return mrb_float_value(mrb
, number
);
908 if (!FIXABLE_FLOAT(number
))
909 return mrb_float_value(mrb
, number
);
910 return mrb_int_value(mrb
, (mrb_int
)number
);
915 flo_to_i(mrb_state
*mrb
, mrb_value num
)
917 mrb_float f
= mrb_float(num
);
919 mrb_check_num_exact(mrb
, f
);
920 if (!FIXABLE_FLOAT(f
)) {
921 #ifdef MRB_USE_BIGINT
922 return mrb_bint_new_float(mrb
, f
);
924 mrb_int_overflow(mrb
, "to_f");
927 if (f
> 0.0) f
= floor(f
);
928 if (f
< 0.0) f
= ceil(f
);
930 return mrb_int_value(mrb
, (mrb_int
)f
);
936 * flt.to_i -> integer
937 * flt.truncate -> integer
939 * Returns <i>flt</i> truncated to an <code>Integer</code>.
943 flo_truncate(mrb_state
*mrb
, mrb_value num
)
945 if (signbit(mrb_float(num
))) return flo_ceil(mrb
, num
);
946 return flo_floor(mrb
, num
);
950 flo_nan_p(mrb_state
*mrb
, mrb_value num
)
952 return mrb_bool_value(isnan(mrb_float(num
)));
956 flo_abs(mrb_state
*mrb
, mrb_value num
)
958 mrb_float f
= mrb_float(num
);
960 if (signbit(f
)) return mrb_float_value(mrb
, -f
);
966 * Document-class: Integer
968 * <code>Integer</code> is hold whole numbers.
974 * Document-method: Integer#to_i
975 * Document-method: Integer#to_int
978 * int.to_i -> integer
979 * int.to_int -> integer
981 * As <i>int</i> is already an <code>Integer</code>, all these
982 * methods simply return the receiver.
986 mrb_int_mul(mrb_state
*mrb
, mrb_value x
, mrb_value y
)
991 if (mrb_integer_p(y
)) {
994 if (a
== 0) return x
;
995 if (a
== 1) return y
;
997 if (b
== 0) return y
;
998 if (b
== 1) return x
;
999 if (mrb_int_mul_overflow(a
, b
, &c
)) {
1000 #ifdef MRB_USE_BIGINT
1001 x
= mrb_bint_new_int(mrb
, a
);
1002 return mrb_bint_mul(mrb
, x
, y
);
1004 mrb_int_overflow(mrb
, "multiplication");
1007 return mrb_int_value(mrb
, c
);
1009 switch (mrb_type(y
)) {
1010 #ifdef MRB_USE_BIGINT
1012 if (a
== 0) return x
;
1013 if (a
== 1) return y
;
1014 return mrb_bint_mul(mrb
, y
, x
);
1016 #ifdef MRB_USE_RATIONAL
1017 case MRB_TT_RATIONAL
:
1018 if (a
== 0) return x
;
1019 if (a
== 1) return y
;
1020 return mrb_rational_mul(mrb
, y
, x
);
1022 #ifdef MRB_USE_COMPLEX
1023 case MRB_TT_COMPLEX
:
1024 if (a
== 0) return x
;
1025 if (a
== 1) return y
;
1026 return mrb_complex_mul(mrb
, y
, x
);
1028 #ifndef MRB_NO_FLOAT
1030 return mrb_float_value(mrb
, (mrb_float
)a
* mrb_as_float(mrb
, y
));
1033 mrb_int_noconv(mrb
, y
);
1040 * int * numeric -> numeric_result
1042 * Performs multiplication: the class of the resulting object depends on
1043 * the class of <code>numeric</code> and on the magnitude of the
1048 int_mul(mrb_state
*mrb
, mrb_value x
)
1050 mrb_value y
= mrb_get_arg1(mrb
);
1052 #ifdef MRB_USE_BIGINT
1053 if (mrb_bigint_p(x
)) {
1054 return mrb_bint_mul(mrb
, x
, y
);
1057 return mrb_int_mul(mrb
, x
, y
);
1061 intdivmod(mrb_state
*mrb
, mrb_int x
, mrb_int y
, mrb_int
*divp
, mrb_int
*modp
)
1064 mrb_int_zerodiv(mrb
);
1066 else if (x
== MRB_INT_MIN
&& y
== -1) {
1067 mrb_int_overflow(mrb
, "division");
1070 mrb_int div
= x
/ y
;
1071 mrb_int mod
= x
- div
* y
;
1073 if ((x
^ y
) < 0 && x
!= div
* y
) {
1077 if (divp
) *divp
= div
;
1078 if (modp
) *modp
= mod
;
1087 * Returns <code>int</code> modulo <code>other</code>.
1088 * See <code>numeric.divmod</code> for more information.
1092 int_mod(mrb_state
*mrb
, mrb_value x
)
1094 mrb_value y
= mrb_get_arg1(mrb
);
1097 #ifdef MRB_USE_BIGINT
1098 if (mrb_bigint_p(x
)) {
1099 return mrb_bint_mod(mrb
, x
, y
);
1103 if (a
== 0) return x
;
1104 if (mrb_integer_p(y
)) {
1106 if (b
== 0) mrb_int_zerodiv(mrb
);
1107 if (a
== MRB_INT_MIN
&& b
== -1) return mrb_fixnum_value(0);
1108 mrb_int mod
= a
% b
;
1109 if ((a
< 0) != (b
< 0) && mod
!= 0) {
1112 return mrb_int_value(mrb
, mod
);
1115 mrb_raise(mrb
, E_TYPE_ERROR
, "non integer modulo");
1119 flodivmod(mrb
, (mrb_float
)a
, mrb_as_float(mrb
, y
), NULL
, &mod
);
1120 return mrb_float_value(mrb
, mod
);
1124 #ifndef MRB_NO_FLOAT
1125 static mrb_value
flo_divmod(mrb_state
*mrb
, mrb_value x
);
1130 * int.divmod(numeric) -> array
1132 * See <code>Numeric#divmod</code>.
1135 int_divmod(mrb_state
*mrb
, mrb_value x
)
1137 mrb_value y
= mrb_get_arg1(mrb
);
1139 #ifdef MRB_USE_BIGINT
1140 if (mrb_bigint_p(x
)) {
1141 #ifndef MRB_NO_FLOAT
1142 if (mrb_float_p(y
)) {
1143 mrb_float f
= mrb_bint_as_float(mrb
, x
);
1144 return flo_divmod(mrb
, mrb_float_value(mrb
, f
));
1147 return mrb_bint_divmod(mrb
, x
, y
);
1150 if (mrb_integer_p(y
)) {
1153 intdivmod(mrb
, mrb_integer(x
), mrb_integer(y
), &div
, &mod
);
1154 return mrb_assoc_new(mrb
, mrb_int_value(mrb
, div
), mrb_int_value(mrb
, mod
));
1157 mrb_raise(mrb
, E_TYPE_ERROR
, "non integer divmod");
1159 return flo_divmod(mrb
, x
);
1163 #ifndef MRB_NO_FLOAT
1165 flo_divmod(mrb_state
*mrb
, mrb_value x
)
1167 mrb_value y
= mrb_get_arg1(mrb
);
1171 flodivmod(mrb
, mrb_float(x
), mrb_as_float(mrb
, y
), &div
, &mod
);
1172 if (!FIXABLE_FLOAT(div
))
1173 a
= mrb_float_value(mrb
, div
);
1175 a
= mrb_int_value(mrb
, (mrb_int
)div
);
1176 b
= mrb_float_value(mrb
, mod
);
1177 return mrb_assoc_new(mrb
, a
, b
);
1184 * int == other -> true or false
1186 * Return <code>true</code> if <code>int</code> equals <code>other</code>
1194 int_equal(mrb_state
*mrb
, mrb_value x
)
1196 mrb_value y
= mrb_get_arg1(mrb
);
1198 switch (mrb_type(y
)) {
1199 case MRB_TT_INTEGER
:
1200 return mrb_bool_value(mrb_integer(x
) == mrb_integer(y
));
1201 #ifndef MRB_NO_FLOAT
1203 return mrb_bool_value((mrb_float
)mrb_integer(x
) == mrb_float(y
));
1205 #ifdef MRB_USE_BIGINT
1207 return mrb_bool_value(mrb_bint_cmp(mrb
, y
, x
) == 0);
1209 #ifdef MRB_USE_RATIONAL
1210 case MRB_TT_RATIONAL
:
1211 return mrb_bool_value(mrb_equal(mrb
, y
, x
));
1213 #ifdef MRB_USE_COMPLEX
1214 case MRB_TT_COMPLEX
:
1215 return mrb_bool_value(mrb_equal(mrb
, y
, x
));
1218 return mrb_false_value();
1227 * One's complement: returns a number where each bit is flipped.
1228 * ex.0---00001 (1)-> 1---11110 (-2)
1229 * ex.0---00010 (2)-> 1---11101 (-3)
1230 * ex.0---00100 (4)-> 1---11011 (-5)
1234 int_rev(mrb_state
*mrb
, mrb_value num
)
1236 #ifdef MRB_USE_BIGINT
1237 if (mrb_bigint_p(num
)) {
1238 return mrb_bint_rev(mrb
, num
);
1241 mrb_int val
= mrb_integer(num
);
1242 return mrb_int_value(mrb
, ~val
);
1245 #define bit_op(x,y,op1,op2) do {\
1246 return mrb_int_value(mrb, (mrb_integer(x) op2 mrb_integer(y)));\
1252 * int & integer -> integer_result
1258 int_and(mrb_state
*mrb
, mrb_value x
)
1260 mrb_value y
= mrb_get_arg1(mrb
);
1262 #ifdef MRB_USE_BIGINT
1263 if (mrb_bigint_p(x
)) {
1264 return mrb_bint_and(mrb
, x
, y
);
1266 if (mrb_bigint_p(y
)) {
1267 return mrb_bint_and(mrb
, mrb_as_bint(mrb
, x
), y
);
1270 bit_op(x
, y
, and, &);
1276 * int | integer -> integer_result
1282 int_or(mrb_state
*mrb
, mrb_value x
)
1284 mrb_value y
= mrb_get_arg1(mrb
);
1286 #ifdef MRB_USE_BIGINT
1287 if (mrb_bigint_p(x
)) {
1288 return mrb_bint_or(mrb
, x
, y
);
1290 if (mrb_bigint_p(y
)) {
1291 return mrb_bint_or(mrb
, mrb_as_bint(mrb
, x
), y
);
1294 bit_op(x
, y
, or, |);
1300 * int ^ integer -> integer_result
1302 * Bitwise EXCLUSIVE OR.
1306 int_xor(mrb_state
*mrb
, mrb_value x
)
1308 mrb_value y
= mrb_get_arg1(mrb
);
1310 #ifdef MRB_USE_BIGINT
1311 if (mrb_bigint_p(x
)) {
1312 return mrb_bint_xor(mrb
, x
, y
);
1314 if (mrb_bigint_p(y
)) {
1315 return mrb_bint_xor(mrb
, mrb_as_bint(mrb
, x
), y
);
1318 bit_op(x
, y
, xor, ^);
1321 #define NUMERIC_SHIFT_WIDTH_MAX (MRB_INT_BIT-1)
1324 mrb_num_shift(mrb_state
*mrb
, mrb_int val
, mrb_int width
, mrb_int
*num
)
1326 if (width
< 0) { /* rshift */
1327 if (width
== MRB_INT_MIN
|| -width
>= NUMERIC_SHIFT_WIDTH_MAX
) {
1336 *num
= val
>> -width
;
1340 if ((width
> NUMERIC_SHIFT_WIDTH_MAX
) ||
1341 (val
> (MRB_INT_MAX
>> width
))) {
1344 *num
= val
<< width
;
1347 if ((width
> NUMERIC_SHIFT_WIDTH_MAX
) ||
1348 (val
< (MRB_INT_MIN
>> width
))) {
1351 if (width
== NUMERIC_SHIFT_WIDTH_MAX
)
1354 *num
= val
* ((mrb_int
)1 << width
);
1362 * int << count -> integer or float
1364 * Shifts _int_ left _count_ positions (right if _count_ is negative).
1368 int_lshift(mrb_state
*mrb
, mrb_value x
)
1372 width
= mrb_as_int(mrb
, mrb_get_arg1(mrb
));
1376 if (width
== MRB_INT_MIN
) mrb_int_overflow(mrb
, "bit shift");
1377 #ifdef MRB_USE_BIGINT
1378 if (mrb_bigint_p(x
)) {
1379 return mrb_bint_lshift(mrb
, x
, width
);
1382 val
= mrb_integer(x
);
1383 if (val
== 0) return x
;
1384 if (!mrb_num_shift(mrb
, val
, width
, &val
)) {
1385 #ifdef MRB_USE_BIGINT
1386 return mrb_bint_lshift(mrb
, mrb_bint_new_int(mrb
, val
), width
);
1388 mrb_int_overflow(mrb
, "bit shift");
1391 return mrb_int_value(mrb
, val
);
1397 * int >> count -> integer or float
1399 * Shifts _int_ right _count_ positions (left if _count_ is negative).
1403 int_rshift(mrb_state
*mrb
, mrb_value x
)
1407 width
= mrb_as_int(mrb
, mrb_get_arg1(mrb
));
1411 if (width
== MRB_INT_MIN
) mrb_int_overflow(mrb
, "bit shift");
1412 #ifdef MRB_USE_BIGINT
1413 if (mrb_bigint_p(x
)) {
1414 return mrb_bint_rshift(mrb
, x
, width
);
1417 val
= mrb_integer(x
);
1418 if (val
== 0) return x
;
1419 if (!mrb_num_shift(mrb
, val
, -width
, &val
)) {
1420 #ifdef MRB_USE_BIGINT
1421 return mrb_bint_rshift(mrb
, mrb_bint_new_int(mrb
, val
), width
);
1423 mrb_int_overflow(mrb
, "bit shift");
1426 return mrb_int_value(mrb
, val
);
1430 prepare_int_rounding(mrb_state
*mrb
, mrb_value x
)
1435 mrb_get_args(mrb
, "|i", &nd
);
1437 return mrb_nil_value();
1439 #ifdef MRB_USE_BIGINT
1440 if (mrb_bigint_p(x
)) {
1441 bytes
= mrb_bint_memsize(x
);
1445 bytes
= sizeof(mrb_int
);
1446 if (-0.415241 * nd
- 0.125 > bytes
) {
1447 return mrb_undef_value();
1449 return mrb_int_pow(mrb
, mrb_fixnum_value(10), mrb_fixnum_value(-nd
));
1452 /* 15.2.8.3.14 Integer#ceil */
1456 * int.ceil(ndigits) -> int
1460 * When the precision (ndigits) is negative, the returned value is an integer
1461 * with at least <code>ndigits.abs</code> trailing zeros.
1464 int_ceil(mrb_state
*mrb
, mrb_value x
)
1466 mrb_value f
= prepare_int_rounding(mrb
, x
);
1467 if (mrb_undef_p(f
)) return mrb_fixnum_value(0);
1468 if (mrb_nil_p(f
)) return x
;
1469 #ifdef MRB_USE_BIGINT
1470 if (mrb_bigint_p(x
)) {
1471 x
= mrb_bint_add_d(mrb
, x
, f
);
1472 return mrb_bint_sub(mrb
, x
, mrb_bint_mod(mrb
, x
, f
));
1475 mrb_int a
= mrb_integer(x
);
1476 mrb_int b
= mrb_integer(f
);
1481 if (mrb_int_add_overflow(a
, b
, &c
)) {
1482 #ifdef MRB_USE_BIGINT
1483 x
= mrb_bint_new_int(mrb
, a
);
1484 return mrb_bint_add(mrb
, x
, f
);
1486 mrb_int_overflow(mrb
, "ceil");
1491 return mrb_int_value(mrb
, a
);
1494 /* 15.2.8.3.17 Integer#floor */
1498 * int.floor(ndigits) -> int
1502 * When the precision (ndigits) is negative, the returned value is an integer
1503 * with at least <code>ndigits.abs</code> trailing zeros.
1506 int_floor(mrb_state
*mrb
, mrb_value x
)
1508 mrb_value f
= prepare_int_rounding(mrb
, x
);
1509 if (mrb_undef_p(f
)) return mrb_fixnum_value(0);
1510 if (mrb_nil_p(f
)) return x
;
1511 #ifdef MRB_USE_BIGINT
1512 if (mrb_bigint_p(x
)) {
1513 return mrb_bint_sub(mrb
, x
, mrb_bint_mod(mrb
, x
, f
));
1516 mrb_int a
= mrb_integer(x
);
1517 mrb_int b
= mrb_integer(f
);
1522 if (mrb_int_sub_overflow(a
, b
, &c
)) {
1523 #ifdef MRB_USE_BIGINT
1524 x
= mrb_bint_new_int(mrb
, a
);
1525 return mrb_bint_sub(mrb
, x
, f
);
1527 mrb_int_overflow(mrb
, "floor");
1532 return mrb_int_value(mrb
, a
);
1535 /* 15.2.8.3.20 Integer#round */
1539 * int.round(ndigits) -> int
1543 * When the precision (ndigits) is negative, the returned value is an integer
1544 * with at least <code>ndigits.abs</code> trailing zeros.
1547 int_round(mrb_state
*mrb
, mrb_value x
)
1549 mrb_value f
= prepare_int_rounding(mrb
, x
);
1550 if (mrb_undef_p(f
)) return mrb_fixnum_value(0);
1551 if (mrb_nil_p(f
)) return x
;
1552 #ifdef MRB_USE_BIGINT
1553 if (mrb_bigint_p(x
)) {
1554 mrb_value r
= mrb_bint_mod(mrb
, x
, f
);
1555 mrb_value n
= mrb_bint_sub(mrb
, x
, r
);
1556 mrb_value h
= mrb_bigint_p(f
) ? mrb_bint_rshift(mrb
, f
, 1) : mrb_int_value(mrb
, mrb_integer(f
)>>1);
1557 mrb_int cmp
= mrb_bigint_p(r
) ? mrb_bint_cmp(mrb
, r
, h
) : (mrb_bigint_p(h
) ? -mrb_bint_cmp(mrb
, h
, r
) : (mrb_integer(r
)-mrb_integer(h
)));
1558 if ((cmp
> 0) || (cmp
== 0 && mrb_bint_cmp(mrb
, x
, mrb_fixnum_value(0)) > 0)) {
1559 n
= mrb_as_bint(mrb
, n
);
1560 n
= mrb_bint_add(mrb
, n
, f
);
1565 mrb_int a
= mrb_integer(x
);
1566 mrb_int b
= mrb_integer(f
);
1572 if (mrb_int_sub_overflow(a
, b
, &c
)) {
1573 #ifdef MRB_USE_BIGINT
1574 x
= mrb_bint_new_int(mrb
, a
);
1575 return mrb_bint_sub(mrb
, x
, f
);
1577 mrb_int_overflow(mrb
, "round");
1585 if (mrb_int_add_overflow(a
, b
, &c
)) {
1586 #ifdef MRB_USE_BIGINT
1587 x
= mrb_bint_new_int(mrb
, a
);
1588 return mrb_bint_add(mrb
, x
, f
);
1590 mrb_int_overflow(mrb
, "round");
1596 return mrb_int_value(mrb
, a
);
1599 /* 15.2.8.3.26 Integer#truncate */
1602 * int.truncate -> int
1603 * int.truncate(ndigits) -> int
1607 * When the precision (ndigits) is negative, the returned value is an integer
1608 * with at least <code>ndigits.abs</code> trailing zeros.
1611 int_truncate(mrb_state
*mrb
, mrb_value x
)
1613 mrb_value f
= prepare_int_rounding(mrb
, x
);
1614 if (mrb_undef_p(f
)) return mrb_fixnum_value(0);
1615 if (mrb_nil_p(f
)) return x
;
1616 #ifdef MRB_USE_BIGINT
1617 if (mrb_bigint_p(x
)) {
1618 mrb_value m
= mrb_bint_mod(mrb
, x
, f
);
1619 x
= mrb_bint_sub_d(mrb
, x
, m
);
1620 if (mrb_bint_cmp(mrb
, x
, mrb_fixnum_value(0)) < 0) {
1621 return mrb_bint_add(mrb
, x
, f
);
1626 mrb_int a
= mrb_integer(x
);
1627 mrb_int b
= mrb_integer(f
);
1628 return mrb_int_value(mrb
, a
- (a
% b
));
1636 * Converts <i>int</i> to a <code>Float</code>.
1640 #ifndef MRB_NO_FLOAT
1642 int_to_f(mrb_state
*mrb
, mrb_value num
)
1644 #ifdef MRB_USE_BIGINT
1645 if (mrb_bigint_p(num
)) {
1646 return mrb_float_value(mrb
, mrb_bint_as_float(mrb
, num
));
1649 return mrb_float_value(mrb
, (mrb_float
)mrb_integer(num
));
1653 mrb_float_to_integer(mrb_state
*mrb
, mrb_value x
)
1655 if (!mrb_float_p(x
)) {
1656 mrb_raise(mrb
, E_TYPE_ERROR
, "non float value");
1658 mrb_float f
= mrb_float(x
);
1659 if (isinf(f
) || isnan(f
)) {
1660 mrb_raisef(mrb
, E_RANGE_ERROR
, "float %f out of range", f
);
1662 return flo_to_i(mrb
, x
);
1667 mrb_int_add(mrb_state
*mrb
, mrb_value x
, mrb_value y
)
1672 if (mrb_integer_p(y
)) {
1675 if (a
== 0) return y
;
1677 if (b
== 0) return x
;
1678 if (mrb_int_add_overflow(a
, b
, &c
)) {
1679 #ifdef MRB_USE_BIGINT
1680 x
= mrb_bint_new_int(mrb
, a
);
1681 return mrb_bint_add(mrb
, x
, y
);
1683 mrb_int_overflow(mrb
, "addition");
1686 return mrb_int_value(mrb
, c
);
1688 switch (mrb_type(y
)) {
1689 #ifdef MRB_USE_BIGINT
1691 return mrb_bint_add(mrb
, y
, x
);
1693 #ifdef MRB_USE_RATIONAL
1694 case MRB_TT_RATIONAL
:
1695 return mrb_rational_add(mrb
, y
, x
);
1697 #ifdef MRB_USE_COMPLEX
1698 case MRB_TT_COMPLEX
:
1699 return mrb_complex_add(mrb
, y
, x
);
1703 mrb_raise(mrb
, E_TYPE_ERROR
, "non integer addition");
1705 return mrb_float_value(mrb
, (mrb_float
)a
+ mrb_as_float(mrb
, y
));
1713 * int + numeric -> numeric_result
1715 * Performs addition: the class of the resulting object depends on
1716 * the class of <code>numeric</code> and on the magnitude of the
1720 int_add(mrb_state
*mrb
, mrb_value self
)
1722 mrb_value other
= mrb_get_arg1(mrb
);
1724 #ifdef MRB_USE_BIGINT
1725 if (mrb_bigint_p(self
)) {
1726 return mrb_bint_add(mrb
, self
, other
);
1729 return mrb_int_add(mrb
, self
, other
);
1733 mrb_int_sub(mrb_state
*mrb
, mrb_value x
, mrb_value y
)
1738 if (mrb_integer_p(y
)) {
1742 if (mrb_int_sub_overflow(a
, b
, &c
)) {
1743 #ifdef MRB_USE_BIGINT
1744 x
= mrb_bint_new_int(mrb
, a
);
1745 return mrb_bint_sub(mrb
, x
, y
);
1747 mrb_int_overflow(mrb
, "subtraction");
1750 return mrb_int_value(mrb
, c
);
1752 switch (mrb_type(y
)) {
1753 #ifdef MRB_USE_BIGINT
1755 return mrb_bint_sub(mrb
, mrb_bint_new_int(mrb
, a
), y
);
1757 #ifdef MRB_USE_RATIONAL
1758 case MRB_TT_RATIONAL
:
1759 return mrb_rational_sub(mrb
, mrb_rational_new(mrb
, a
, 1), y
);
1761 #ifdef MRB_USE_COMPLEX
1762 case MRB_TT_COMPLEX
:
1763 return mrb_complex_sub(mrb
, mrb_complex_new(mrb
, (mrb_float
)a
, 0), y
);
1767 mrb_raise(mrb
, E_TYPE_ERROR
, "non integer subtraction");
1769 return mrb_float_value(mrb
, (mrb_float
)a
- mrb_as_float(mrb
, y
));
1777 * int - numeric -> numeric
1779 * Performs subtraction: the class of the resulting object depends on
1780 * the class of <code>numeric</code> and on the magnitude of the
1784 int_sub(mrb_state
*mrb
, mrb_value self
)
1786 mrb_value other
= mrb_get_arg1(mrb
);
1788 #ifdef MRB_USE_BIGINT
1789 if (mrb_bigint_p(self
)) {
1790 return mrb_bint_sub(mrb
, self
, other
);
1793 return mrb_int_sub(mrb
, self
, other
);
1797 mrb_int_to_cstr(char *buf
, size_t len
, mrb_int n
, mrb_int base
)
1799 char *bufend
= buf
+ len
;
1802 if (base
< 2 || 36 < base
) return NULL
;
1803 if (len
< 2) return NULL
;
1814 if (b
-- == buf
) return NULL
;
1815 *b
= mrb_digitmap
[-(n
% base
)];
1816 } while (n
/= base
);
1817 if (b
-- == buf
) return NULL
;
1822 if (b
-- == buf
) return NULL
;
1823 *b
= mrb_digitmap
[(int)(n
% base
)];
1824 } while (n
/= base
);
1830 mrb_integer_to_str(mrb_state
*mrb
, mrb_value x
, mrb_int base
)
1832 char buf
[MRB_INT_BIT
+1];
1834 if (base
< 2 || 36 < base
) {
1835 mrb_raisef(mrb
, E_ARGUMENT_ERROR
, "invalid radix %i", base
);
1837 #ifdef MRB_USE_BIGINT
1838 if (mrb_bigint_p(x
)) {
1839 return mrb_bint_to_s(mrb
, x
, base
);
1842 mrb_int val
= mrb_integer(x
);
1843 const char *p
= mrb_int_to_cstr(buf
, sizeof(buf
), val
, base
);
1844 mrb_assert(p
!= NULL
);
1845 mrb_value str
= mrb_str_new_cstr(mrb
, p
);
1846 RSTR_SET_ASCII_FLAG(mrb_str_ptr(str
));
1853 * int.to_s(base=10) -> string
1855 * Returns a string containing the representation of <i>int</i> radix
1856 * <i>base</i> (between 2 and 36).
1858 * 12345.to_s #=> "12345"
1859 * 12345.to_s(2) #=> "11000000111001"
1860 * 12345.to_s(8) #=> "30071"
1861 * 12345.to_s(10) #=> "12345"
1862 * 12345.to_s(16) #=> "3039"
1863 * 12345.to_s(36) #=> "9ix"
1867 int_to_s(mrb_state
*mrb
, mrb_value self
)
1871 if (mrb_get_argc(mrb
) > 0) {
1872 base
= mrb_integer(mrb_get_arg1(mrb
));
1877 return mrb_integer_to_str(mrb
, self
, base
);
1880 /* compare two numbers: (1:0:-1; -2 for error) */
1882 cmpnum(mrb_state
*mrb
, mrb_value v1
, mrb_value v2
)
1884 #ifdef MRB_USE_BIGINT
1885 if (mrb_bigint_p(v1
)) {
1886 return mrb_bint_cmp(mrb
, v1
, v2
);
1888 if (mrb_bigint_p(v2
)) {
1889 return mrb_bint_cmp(mrb
, mrb_bint_new_int(mrb
, mrb_integer(v1
)), v2
);
1900 x
= mrb_integer(v1
);
1902 x
= mrb_as_float(mrb
, v1
);
1904 switch (mrb_type(v2
)) {
1905 case MRB_TT_INTEGER
:
1907 y
= mrb_integer(v2
);
1909 y
= (mrb_float
)mrb_integer(v2
);
1912 #ifndef MRB_NO_FLOAT
1916 #ifdef MRB_USE_RATIONAL
1917 case MRB_TT_RATIONAL
:
1918 y
= mrb_as_float(mrb
, v2
);
1935 int_hash(mrb_state
*mrb
, mrb_value self
)
1937 #ifdef MRB_USE_BIGINT
1938 if (mrb_bigint_p(self
)) {
1939 return mrb_bint_hash(mrb
, self
);
1942 mrb_int n
= mrb_integer(self
);
1943 return mrb_int_value(mrb
, mrb_byte_hash((uint8_t*)&n
, sizeof(n
)));
1950 * self.f <=> other.f => -1, 0, +1, or nil
1954 * Comparison---Returns -1, 0, or +1 depending on whether <i>int</i> is
1955 * less than, equal to, or greater than <i>numeric</i>. This is the
1956 * basis for the tests in <code>Comparable</code>. When the operands are
1957 * not comparable, it returns nil instead of raising an exception.
1960 num_cmp(mrb_state
*mrb
, mrb_value self
)
1962 mrb_value other
= mrb_get_arg1(mrb
);
1965 n
= cmpnum(mrb
, self
, other
);
1966 if (n
== -2) return mrb_nil_value();
1967 return mrb_fixnum_value(n
);
1970 static mrb_noreturn
void
1971 cmperr(mrb_state
*mrb
, mrb_value v1
, mrb_value v2
)
1973 mrb_raisef(mrb
, E_ARGUMENT_ERROR
, "comparison of %t with %t failed", v1
, v2
);
1977 num_lt(mrb_state
*mrb
, mrb_value self
)
1979 mrb_value other
= mrb_get_arg1(mrb
);
1982 n
= cmpnum(mrb
, self
, other
);
1983 if (n
== -2) cmperr(mrb
, self
, other
);
1984 if (n
< 0) return mrb_true_value();
1985 return mrb_false_value();
1989 num_le(mrb_state
*mrb
, mrb_value self
)
1991 mrb_value other
= mrb_get_arg1(mrb
);
1994 n
= cmpnum(mrb
, self
, other
);
1995 if (n
== -2) cmperr(mrb
, self
, other
);
1996 if (n
<= 0) return mrb_true_value();
1997 return mrb_false_value();
2001 num_gt(mrb_state
*mrb
, mrb_value self
)
2003 mrb_value other
= mrb_get_arg1(mrb
);
2006 n
= cmpnum(mrb
, self
, other
);
2007 if (n
== -2) cmperr(mrb
, self
, other
);
2008 if (n
> 0) return mrb_true_value();
2009 return mrb_false_value();
2013 num_ge(mrb_state
*mrb
, mrb_value self
)
2015 mrb_value other
= mrb_get_arg1(mrb
);
2018 n
= cmpnum(mrb
, self
, other
);
2019 if (n
== -2) cmperr(mrb
, self
, other
);
2020 if (n
>= 0) return mrb_true_value();
2021 return mrb_false_value();
2025 mrb_cmp(mrb_state
*mrb
, mrb_value obj1
, mrb_value obj2
)
2029 switch (mrb_type(obj1
)) {
2030 case MRB_TT_INTEGER
:
2033 return cmpnum(mrb
, obj1
, obj2
);
2035 if (!mrb_string_p(obj2
))
2037 return mrb_str_cmp(mrb
, obj1
, obj2
);
2039 if (!mrb_respond_to(mrb
, obj1
, MRB_OPSYM(cmp
))) return -2;
2040 v
= mrb_funcall_argv(mrb
, obj1
, MRB_OPSYM(cmp
), 1, &obj2
);
2041 if (mrb_nil_p(v
) || !mrb_integer_p(v
))
2043 return mrb_integer(v
);
2048 num_finite_p(mrb_state
*mrb
, mrb_value self
)
2050 return mrb_true_value();
2054 num_infinite_p(mrb_state
*mrb
, mrb_value self
)
2056 return mrb_false_value();
2059 #ifndef MRB_NO_FLOAT
2061 flo_hash(mrb_state
*mrb
, mrb_value flo
)
2063 mrb_float f
= mrb_float(flo
);
2064 /* normalize -0.0 to 0.0 */
2065 if (f
== 0) f
= 0.0;
2066 return mrb_int_value(mrb
, (mrb_int
)mrb_byte_hash((uint8_t*)&f
, sizeof(f
)));
2070 /* ------------------------------------------------------------------------*/
2072 mrb_init_numeric(mrb_state
*mrb
)
2074 struct RClass
*numeric
, *integer
;
2075 #ifndef MRB_NO_FLOAT
2080 numeric
= mrb_define_class_id(mrb
, MRB_SYM(Numeric
), mrb
->object_class
); /* 15.2.7 */
2081 mrb_define_method_id(mrb
, numeric
, MRB_SYM_Q(finite
), num_finite_p
, MRB_ARGS_NONE());
2082 mrb_define_method_id(mrb
, numeric
, MRB_SYM_Q(infinite
),num_infinite_p
, MRB_ARGS_NONE());
2083 mrb_define_method_id(mrb
, numeric
, MRB_SYM_Q(eql
), num_eql
, MRB_ARGS_REQ(1)); /* 15.2.8.3.16 */
2086 mrb
->integer_class
= integer
= mrb_define_class_id(mrb
, MRB_SYM(Integer
), numeric
); /* 15.2.8 */
2087 MRB_SET_INSTANCE_TT(integer
, MRB_TT_INTEGER
);
2088 MRB_UNDEF_ALLOCATOR(integer
);
2089 mrb_undef_class_method_id(mrb
, integer
, MRB_SYM(new));
2090 mrb_define_method_id(mrb
, integer
, MRB_OPSYM(pow
), int_pow
, MRB_ARGS_REQ(1));
2091 mrb_define_method_id(mrb
, integer
, MRB_OPSYM(cmp
), num_cmp
, MRB_ARGS_REQ(1)); /* 15.2.8.3.1 */
2092 mrb_define_method_id(mrb
, integer
, MRB_OPSYM(lt
), num_lt
, MRB_ARGS_REQ(1));
2093 mrb_define_method_id(mrb
, integer
, MRB_OPSYM(le
), num_le
, MRB_ARGS_REQ(1));
2094 mrb_define_method_id(mrb
, integer
, MRB_OPSYM(gt
), num_gt
, MRB_ARGS_REQ(1));
2095 mrb_define_method_id(mrb
, integer
, MRB_OPSYM(ge
), num_ge
, MRB_ARGS_REQ(1));
2097 mrb_define_method_id(mrb
, integer
, MRB_SYM(to_i
), mrb_obj_itself
, MRB_ARGS_NONE()); /* 15.2.8.3.24 */
2098 mrb_define_method_id(mrb
, integer
, MRB_SYM(to_int
), mrb_obj_itself
, MRB_ARGS_NONE());
2100 mrb_define_method_id(mrb
, integer
, MRB_OPSYM(add
), int_add
, MRB_ARGS_REQ(1)); /* 15.2.8.3.1 */
2101 mrb_define_method_id(mrb
, integer
, MRB_OPSYM(sub
), int_sub
, MRB_ARGS_REQ(1)); /* 15.2.8.3.2 */
2102 mrb_define_method_id(mrb
, integer
, MRB_OPSYM(mul
), int_mul
, MRB_ARGS_REQ(1)); /* 15.2.8.3.3 */
2103 mrb_define_method_id(mrb
, integer
, MRB_OPSYM(mod
), int_mod
, MRB_ARGS_REQ(1)); /* 15.2.8.3.5 */
2104 mrb_define_method_id(mrb
, integer
, MRB_OPSYM(div
), int_div
, MRB_ARGS_REQ(1)); /* 15.2.8.3.6 */
2105 mrb_define_method_id(mrb
, integer
, MRB_SYM(quo
), int_quo
, MRB_ARGS_REQ(1)); /* 15.2.7.4.5(x) */
2106 mrb_define_method_id(mrb
, integer
, MRB_SYM(div
), int_idiv
, MRB_ARGS_REQ(1));
2107 mrb_define_method_id(mrb
, integer
, MRB_OPSYM(eq
), int_equal
, MRB_ARGS_REQ(1)); /* 15.2.8.3.7 */
2108 mrb_define_method_id(mrb
, integer
, MRB_OPSYM(neg
), int_rev
, MRB_ARGS_NONE()); /* 15.2.8.3.8 */
2109 mrb_define_method_id(mrb
, integer
, MRB_OPSYM(and), int_and
, MRB_ARGS_REQ(1)); /* 15.2.8.3.9 */
2110 mrb_define_method_id(mrb
, integer
, MRB_OPSYM(or), int_or
, MRB_ARGS_REQ(1)); /* 15.2.8.3.10 */
2111 mrb_define_method_id(mrb
, integer
, MRB_OPSYM(xor), int_xor
, MRB_ARGS_REQ(1)); /* 15.2.8.3.11 */
2112 mrb_define_method_id(mrb
, integer
, MRB_OPSYM(lshift
), int_lshift
, MRB_ARGS_REQ(1)); /* 15.2.8.3.12 */
2113 mrb_define_method_id(mrb
, integer
, MRB_OPSYM(rshift
), int_rshift
, MRB_ARGS_REQ(1)); /* 15.2.8.3.13 */
2114 mrb_define_method_id(mrb
, integer
, MRB_SYM(ceil
), int_ceil
, MRB_ARGS_OPT(1)); /* 15.2.8.3.14 */
2115 mrb_define_method_id(mrb
, integer
, MRB_SYM(floor
), int_floor
, MRB_ARGS_OPT(1)); /* 15.2.8.3.17 */
2116 mrb_define_method_id(mrb
, integer
, MRB_SYM(round
), int_round
, MRB_ARGS_OPT(1)); /* 15.2.8.3.20 */
2117 mrb_define_method_id(mrb
, integer
, MRB_SYM(truncate
), int_truncate
, MRB_ARGS_OPT(1)); /* 15.2.8.3.26 */
2118 mrb_define_method_id(mrb
, integer
, MRB_SYM(hash
), int_hash
, MRB_ARGS_NONE()); /* 15.2.8.3.18 */
2119 #ifndef MRB_NO_FLOAT
2120 mrb_define_method_id(mrb
, integer
, MRB_SYM(to_f
), int_to_f
, MRB_ARGS_NONE()); /* 15.2.8.3.23 */
2122 mrb_define_method_id(mrb
, integer
, MRB_SYM(to_s
), int_to_s
, MRB_ARGS_OPT(1)); /* 15.2.8.3.25 */
2123 mrb_define_method_id(mrb
, integer
, MRB_SYM(inspect
), int_to_s
, MRB_ARGS_OPT(1));
2124 mrb_define_method_id(mrb
, integer
, MRB_SYM(divmod
), int_divmod
, MRB_ARGS_REQ(1)); /* 15.2.8.3.30(x) */
2125 mrb_define_method_id(mrb
, integer
, MRB_SYM(__coerce_step_counter
), coerce_step_counter
, MRB_ARGS_REQ(2));
2127 /* Fixnum Class for compatibility */
2128 mrb_define_const_id(mrb
, mrb
->object_class
, MRB_SYM(Fixnum
), mrb_obj_value(integer
));
2130 #ifndef MRB_NO_FLOAT
2132 mrb
->float_class
= fl
= mrb_define_class_id(mrb
, MRB_SYM(Float
), numeric
); /* 15.2.9 */
2133 MRB_SET_INSTANCE_TT(fl
, MRB_TT_FLOAT
);
2134 MRB_UNDEF_ALLOCATOR(fl
);
2135 mrb_undef_class_method(mrb
, fl
, "new");
2136 mrb_define_method_id(mrb
, fl
, MRB_OPSYM(pow
), flo_pow
, MRB_ARGS_REQ(1));
2137 mrb_define_method_id(mrb
, fl
, MRB_OPSYM(div
), flo_div
, MRB_ARGS_REQ(1)); /* 15.2.9.3.6 */
2138 mrb_define_method_id(mrb
, fl
, MRB_SYM(quo
), flo_div
, MRB_ARGS_REQ(1)); /* 15.2.7.4.5(x) */
2139 mrb_define_method_id(mrb
, fl
, MRB_SYM(div
), flo_idiv
, MRB_ARGS_REQ(1));
2140 mrb_define_method_id(mrb
, fl
, MRB_OPSYM(add
), flo_add
, MRB_ARGS_REQ(1)); /* 15.2.9.3.3 */
2141 mrb_define_method_id(mrb
, fl
, MRB_OPSYM(sub
), flo_sub
, MRB_ARGS_REQ(1)); /* 15.2.9.3.4 */
2142 mrb_define_method_id(mrb
, fl
, MRB_OPSYM(mul
), flo_mul
, MRB_ARGS_REQ(1)); /* 15.2.9.3.5 */
2143 mrb_define_method_id(mrb
, fl
, MRB_OPSYM(mod
), flo_mod
, MRB_ARGS_REQ(1)); /* 15.2.9.3.7 */
2144 mrb_define_method_id(mrb
, fl
, MRB_OPSYM(cmp
), num_cmp
, MRB_ARGS_REQ(1)); /* 15.2.9.3.1 */
2145 mrb_define_method_id(mrb
, fl
, MRB_OPSYM(lt
), num_lt
, MRB_ARGS_REQ(1));
2146 mrb_define_method_id(mrb
, fl
, MRB_OPSYM(le
), num_le
, MRB_ARGS_REQ(1));
2147 mrb_define_method_id(mrb
, fl
, MRB_OPSYM(gt
), num_gt
, MRB_ARGS_REQ(1));
2148 mrb_define_method_id(mrb
, fl
, MRB_OPSYM(ge
), num_ge
, MRB_ARGS_REQ(1));
2149 mrb_define_method_id(mrb
, fl
, MRB_OPSYM(eq
), flo_eq
, MRB_ARGS_REQ(1)); /* 15.2.9.3.2 */
2150 mrb_define_method_id(mrb
, fl
, MRB_SYM(ceil
), flo_ceil
, MRB_ARGS_OPT(1)); /* 15.2.9.3.8 */
2151 mrb_define_method_id(mrb
, fl
, MRB_SYM_Q(finite
), flo_finite_p
, MRB_ARGS_NONE()); /* 15.2.9.3.9 */
2152 mrb_define_method_id(mrb
, fl
, MRB_SYM(floor
), flo_floor
, MRB_ARGS_OPT(1)); /* 15.2.9.3.10 */
2153 mrb_define_method_id(mrb
, fl
, MRB_SYM_Q(infinite
),flo_infinite_p
, MRB_ARGS_NONE()); /* 15.2.9.3.11 */
2154 mrb_define_method_id(mrb
, fl
, MRB_SYM(round
), flo_round
, MRB_ARGS_OPT(1)); /* 15.2.9.3.12 */
2155 mrb_define_method_id(mrb
, fl
, MRB_SYM(to_f
), mrb_obj_itself
, MRB_ARGS_NONE()); /* 15.2.9.3.13 */
2156 mrb_define_method_id(mrb
, fl
, MRB_SYM(to_i
), flo_to_i
, MRB_ARGS_NONE()); /* 15.2.9.3.14 */
2157 mrb_define_method_id(mrb
, fl
, MRB_SYM(truncate
), flo_truncate
, MRB_ARGS_OPT(1)); /* 15.2.9.3.15 */
2158 mrb_define_method_id(mrb
, fl
, MRB_SYM(divmod
), flo_divmod
, MRB_ARGS_REQ(1));
2160 mrb_define_method_id(mrb
, fl
, MRB_SYM(to_s
), flo_to_s
, MRB_ARGS_NONE()); /* 15.2.9.3.16(x) */
2161 mrb_define_method_id(mrb
, fl
, MRB_SYM(inspect
), flo_to_s
, MRB_ARGS_NONE());
2162 mrb_define_method_id(mrb
, fl
, MRB_SYM_Q(nan
), flo_nan_p
, MRB_ARGS_NONE());
2163 mrb_define_method_id(mrb
, fl
, MRB_SYM(abs
), flo_abs
, MRB_ARGS_NONE()); /* 15.2.7.4.3 */
2164 mrb_define_method_id(mrb
, fl
, MRB_SYM(hash
), flo_hash
, MRB_ARGS_NONE());
2167 mrb_define_const_id(mrb
, fl
, MRB_SYM(INFINITY
), mrb_float_value(mrb
, INFINITY
));
2170 mrb_define_const_id(mrb
, fl
, MRB_SYM(NAN
), mrb_float_value(mrb
, NAN
));