Merge pull request #3974 from take-cheeze/repo_path
[mruby.git] / src / numeric.c
blobb898fd0b594feb691817acd510a2e51e2487d17e
1 /*
2 ** numeric.c - Numeric, Integer, Float, Fixnum class
3 **
4 ** See Copyright Notice in mruby.h
5 */
7 #ifndef MRB_WITHOUT_FLOAT
8 #include <float.h>
9 #include <math.h>
10 #endif
11 #include <limits.h>
12 #include <stdlib.h>
14 #include <mruby.h>
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
21 #ifdef MRB_USE_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"
27 #else
28 #define MRB_FLO_TO_STR_FMT "%.14g"
29 #endif
30 #endif
32 #ifndef MRB_WITHOUT_FLOAT
33 MRB_API mrb_float
34 mrb_to_flo(mrb_state *mrb, mrb_value val)
36 switch (mrb_type(val)) {
37 case MRB_TT_FIXNUM:
38 return (mrb_float)mrb_fixnum(val);
39 case MRB_TT_FLOAT:
40 break;
41 default:
42 mrb_raise(mrb, E_TYPE_ERROR, "non float value");
44 return mrb_float(val);
46 #endif
49 * call-seq:
51 * num ** other -> num
53 * Raises <code>num</code> the <code>other</code> power.
55 * 2.0**3 #=> 8.0
57 static mrb_value
58 num_pow(mrb_state *mrb, mrb_value x)
60 mrb_value y;
61 #ifndef MRB_WITHOUT_FLOAT
62 mrb_float d;
63 #endif
65 mrb_get_args(mrb, "o", &y);
66 if (mrb_fixnum_p(x) && mrb_fixnum_p(y)) {
67 /* try ipow() */
68 mrb_int base = mrb_fixnum(x);
69 mrb_int exp = mrb_fixnum(y);
70 mrb_int result = 1;
72 if (exp < 0)
73 #ifdef MRB_WITHOUT_FLOAT
74 return mrb_fixnum_value(0);
75 #else
76 goto float_pow;
77 #endif
78 for (;;) {
79 if (exp & 1) {
80 if (mrb_int_mul_overflow(result, base, &result)) {
81 #ifndef MRB_WITHOUT_FLOAT
82 goto float_pow;
83 #endif
86 exp >>= 1;
87 if (exp == 0) break;
88 if (mrb_int_mul_overflow(base, base, &base)) {
89 #ifndef MRB_WITHOUT_FLOAT
90 goto float_pow;
91 #endif
94 return mrb_fixnum_value(result);
96 #ifdef MRB_WITHOUT_FLOAT
97 mrb_raise(mrb, E_TYPE_ERROR, "non fixnum value");
98 #else
99 float_pow:
100 d = pow(mrb_to_flo(mrb, x), mrb_to_flo(mrb, y));
101 return mrb_float_value(mrb, d);
102 #endif
105 /* 15.2.8.3.4 */
106 /* 15.2.9.3.4 */
108 * call-seq:
109 * num / other -> num
111 * Performs division: the class of the resulting object depends on
112 * the class of <code>num</code> and on the magnitude of the
113 * result.
116 mrb_value
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));
124 #else
125 return mrb_float_value(mrb, mrb_to_flo(mrb, x) / mrb_to_flo(mrb, y));
126 #endif
129 /* 15.2.9.3.19(x) */
131 * call-seq:
132 * num.quo(numeric) -> real
134 * Returns most exact division.
137 static mrb_value
138 num_div(mrb_state *mrb, mrb_value x)
140 #ifdef MRB_WITHOUT_FLOAT
141 mrb_value y;
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));
148 #else
149 mrb_float y;
151 mrb_get_args(mrb, "f", &y);
152 return mrb_float_value(mrb, mrb_to_flo(mrb, x) / y);
153 #endif
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
163 * representation.
166 /* 15.2.9.3.16(x) */
168 * call-seq:
169 * flt.to_s -> string
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>".
177 static mrb_value
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);
186 /* 15.2.9.3.2 */
188 * call-seq:
189 * float - other -> float
191 * Returns a new float which is the difference of <code>float</code>
192 * and <code>other</code>.
195 static mrb_value
196 flo_minus(mrb_state *mrb, mrb_value x)
198 mrb_value y;
200 mrb_get_args(mrb, "o", &y);
201 return mrb_float_value(mrb, mrb_float(x) - mrb_to_flo(mrb, y));
204 /* 15.2.9.3.3 */
206 * call-seq:
207 * float * other -> float
209 * Returns a new float which is the product of <code>float</code>
210 * and <code>other</code>.
213 static mrb_value
214 flo_mul(mrb_state *mrb, mrb_value x)
216 mrb_value y;
218 mrb_get_args(mrb, "o", &y);
219 return mrb_float_value(mrb, mrb_float(x) * mrb_to_flo(mrb, y));
222 static void
223 flodivmod(mrb_state *mrb, mrb_float x, mrb_float y, mrb_float *divp, mrb_float *modp)
225 mrb_float div;
226 mrb_float mod;
228 if (y == 0.0) {
229 if (x > 0.0) div = INFINITY;
230 else if (x < 0.0) div = -INFINITY;
231 else div = NAN; /* x == 0.0 */
232 mod = NAN;
234 else {
235 mod = fmod(x, y);
236 if (isinf(x) && isfinite(y))
237 div = x;
238 else
239 div = (x - mod) / y;
240 if (y*mod < 0) {
241 mod += y;
242 div -= 1.0;
246 if (modp) *modp = mod;
247 if (divp) *divp = div;
250 /* 15.2.9.3.5 */
252 * call-seq:
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
262 static mrb_value
263 flo_mod(mrb_state *mrb, mrb_value x)
265 mrb_value y;
266 mrb_float mod;
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);
273 #endif
275 /* 15.2.8.3.16 */
277 * call-seq:
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.
283 * 1 == 1.0 #=> true
284 * 1.eql?(1.0) #=> false
285 * (1.0).eql?(1.0) #=> true
287 static mrb_value
288 fix_eql(mrb_state *mrb, mrb_value x)
290 mrb_value y;
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
298 static mrb_value
299 flo_eql(mrb_state *mrb, mrb_value x)
301 mrb_value y;
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));
308 /* 15.2.9.3.7 */
310 * call-seq:
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>.
317 * 1.0 == 1 #=> true
321 static mrb_value
322 flo_eq(mrb_state *mrb, mrb_value x)
324 mrb_value y;
325 mrb_get_args(mrb, "o", &y);
327 switch (mrb_type(y)) {
328 case MRB_TT_FIXNUM:
329 return mrb_bool_value(mrb_float(x) == (mrb_float)mrb_fixnum(y));
330 case MRB_TT_FLOAT:
331 return mrb_bool_value(mrb_float(x) == mrb_float(y));
332 default:
333 return mrb_false_value();
337 static int64_t
338 value_int64(mrb_state *mrb, mrb_value x)
340 switch (mrb_type(x)) {
341 case MRB_TT_FIXNUM:
342 return (int64_t)mrb_fixnum(x);
343 break;
344 case MRB_TT_FLOAT:
345 return (int64_t)mrb_float(x);
346 default:
347 mrb_raise(mrb, E_TYPE_ERROR, "cannot convert to Integer");
348 break;
350 /* not reached */
351 return 0;
354 static mrb_value
355 int64_value(mrb_state *mrb, int64_t v)
357 if (FIXABLE(v)) {
358 return mrb_fixnum_value((mrb_int)v);
360 return mrb_float_value(mrb, (mrb_float)v);
363 static mrb_value
364 flo_rev(mrb_state *mrb, mrb_value x)
366 int64_t v1;
367 mrb_get_args(mrb, "");
368 v1 = (int64_t)mrb_float(x);
369 return int64_value(mrb, ~v1);
372 static mrb_value
373 flo_and(mrb_state *mrb, mrb_value x)
375 mrb_value y;
376 int64_t v1, v2;
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);
384 static mrb_value
385 flo_or(mrb_state *mrb, mrb_value x)
387 mrb_value y;
388 int64_t v1, v2;
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);
396 static mrb_value
397 flo_xor(mrb_state *mrb, mrb_value x)
399 mrb_value y;
400 int64_t v1, v2;
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);
408 static mrb_value
409 flo_shift(mrb_state *mrb, mrb_value x, mrb_int width)
411 mrb_float val;
413 if (width == 0) {
414 return x;
416 val = mrb_float(x);
417 if (width < 0) {
418 while (width++) {
419 val /= 2;
421 #if defined(_ISOC99_SOURCE)
422 val = trunc(val);
423 #else
424 if (val > 0){
425 val = floor(val);
426 } else {
427 val = ceil(val);
429 #endif
430 if (val == 0 && mrb_float(x) < 0) {
431 return mrb_fixnum_value(-1);
434 else {
435 while (width--) {
436 val *= 2;
439 if (FIXABLE_FLOAT(val)) {
440 return mrb_fixnum_value((mrb_int)val);
442 return mrb_float_value(mrb, val);
445 static mrb_value
446 flo_lshift(mrb_state *mrb, mrb_value x)
448 mrb_int width;
450 mrb_get_args(mrb, "i", &width);
451 return flo_shift(mrb, x, -width);
454 static mrb_value
455 flo_rshift(mrb_state *mrb, mrb_value x)
457 mrb_int width;
459 mrb_get_args(mrb, "i", &width);
460 return flo_shift(mrb, x, width);
463 /* 15.2.9.3.13 */
465 * call-seq:
466 * flt.to_f -> self
468 * As <code>flt</code> is already a float, returns +self+.
471 static mrb_value
472 flo_to_f(mrb_state *mrb, mrb_value num)
474 return num;
477 /* 15.2.9.3.11 */
479 * call-seq:
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
490 static mrb_value
491 flo_infinite_p(mrb_state *mrb, mrb_value num)
493 mrb_float value = mrb_float(num);
495 if (isinf(value)) {
496 return mrb_fixnum_value(value < 0 ? -1 : 1);
498 return mrb_nil_value();
501 /* 15.2.9.3.9 */
503 * call-seq:
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>).
512 static mrb_value
513 flo_finite_p(mrb_state *mrb, mrb_value num)
515 return mrb_bool_value(isfinite(mrb_float(num)));
518 void
519 mrb_check_num_exact(mrb_state *mrb, mrb_float num)
521 if (isinf(num)) {
522 mrb_raise(mrb, E_FLOATDOMAIN_ERROR, num < 0 ? "-Infinity" : "Infinity");
524 if (isnan(num)) {
525 mrb_raise(mrb, E_FLOATDOMAIN_ERROR, "NaN");
529 /* 15.2.9.3.10 */
531 * call-seq:
532 * flt.floor -> integer
534 * Returns the largest integer less than or equal to <i>flt</i>.
536 * 1.2.floor #=> 1
537 * 2.0.floor #=> 2
538 * (-1.2).floor #=> -2
539 * (-2.0).floor #=> -2
542 static mrb_value
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);
554 /* 15.2.9.3.8 */
556 * call-seq:
557 * flt.ceil -> integer
559 * Returns the smallest <code>Integer</code> greater than or equal to
560 * <i>flt</i>.
562 * 1.2.ceil #=> 2
563 * 2.0.ceil #=> 2
564 * (-1.2).ceil #=> -1
565 * (-2.0).ceil #=> -2
568 static mrb_value
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);
580 /* 15.2.9.3.12 */
582 * call-seq:
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
587 * is more than zero.
589 * 1.4.round #=> 1
590 * 1.5.round #=> 2
591 * 1.6.round #=> 2
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
611 static mrb_value
612 flo_round(mrb_state *mrb, mrb_value num)
614 double number, f;
615 mrb_int ndigits = 0;
616 mrb_int i;
618 mrb_get_args(mrb, "|i", &ndigits);
619 number = mrb_float(num);
621 if (0 < ndigits && (isinf(number) || isnan(number))) {
622 return num;
624 mrb_check_num_exact(mrb, number);
626 f = 1.0;
627 i = ndigits >= 0 ? ndigits : -ndigits;
628 while (--i >= 0)
629 f = f*10.0;
631 if (isinf(f)) {
632 if (ndigits < 0) number = 0;
634 else {
635 double d;
637 if (ndigits < 0) number /= f;
638 else number *= f;
640 /* home-made inline implementation of round(3) */
641 if (number > 0.0) {
642 d = floor(number);
643 number = d + (number - d >= 0.5);
645 else if (number < 0.0) {
646 d = ceil(number);
647 number = d - (d - number >= 0.5);
650 if (ndigits < 0) number *= f;
651 else number /= f;
654 if (ndigits > 0) {
655 if (!isfinite(number)) return num;
656 return mrb_float_value(mrb, number);
658 return mrb_fixnum_value((mrb_int)number);
661 /* 15.2.9.3.14 */
662 /* 15.2.9.3.15 */
664 * call-seq:
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>.
672 static mrb_value
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);
687 static mrb_value
688 flo_nan_p(mrb_state *mrb, mrb_value num)
690 return mrb_bool_value(isnan(mrb_float(num)));
692 #endif
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>.
704 * call-seq:
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.
712 static mrb_value
713 int_to_i(mrb_state *mrb, mrb_value num)
715 return num;
718 mrb_value
719 mrb_fixnum_mul(mrb_state *mrb, mrb_value x, mrb_value y)
721 mrb_int a;
723 a = mrb_fixnum(x);
724 if (mrb_fixnum_p(y)) {
725 mrb_int b, c;
727 if (a == 0) return x;
728 b = mrb_fixnum(y);
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);
732 #endif
734 return mrb_fixnum_value(c);
736 #ifdef MRB_WITHOUT_FLOAT
737 mrb_raise(mrb, E_TYPE_ERROR, "non fixnum value");
738 #else
739 return mrb_float_value(mrb, (mrb_float)a * mrb_to_flo(mrb, y));
740 #endif
743 /* 15.2.8.3.3 */
745 * call-seq:
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
750 * result.
753 static mrb_value
754 fix_mul(mrb_state *mrb, mrb_value x)
756 mrb_value y;
758 mrb_get_args(mrb, "o", &y);
759 return mrb_fixnum_mul(mrb, x, y);
762 static void
763 fixdivmod(mrb_state *mrb, mrb_int x, mrb_int y, mrb_int *divp, mrb_int *modp)
765 mrb_int div, mod;
767 /* TODO: add mrb_assert(y != 0) to make sure */
769 if (y < 0) {
770 if (x < 0)
771 div = -x / -y;
772 else
773 div = - (x / -y);
775 else {
776 if (x < 0)
777 div = - (-x / y);
778 else
779 div = x / y;
781 mod = x - div*y;
782 if ((mod < 0 && y > 0) || (mod > 0 && y < 0)) {
783 mod += y;
784 div -= 1;
786 if (divp) *divp = div;
787 if (modp) *modp = mod;
790 /* 15.2.8.3.5 */
792 * call-seq:
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.
800 static mrb_value
801 fix_mod(mrb_state *mrb, mrb_value x)
803 mrb_value y;
804 mrb_int a;
806 mrb_get_args(mrb, "o", &y);
807 a = mrb_fixnum(x);
808 if (mrb_fixnum_p(y)) {
809 mrb_int b, mod;
811 if ((b=mrb_fixnum(y)) == 0) {
812 #ifdef MRB_WITHOUT_FLOAT
813 /* ZeroDivisionError */
814 return mrb_fixnum_value(0);
815 #else
816 return mrb_float_value(mrb, NAN);
817 #endif
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");
824 #else
825 else {
826 mrb_float mod;
828 flodivmod(mrb, (mrb_float)a, mrb_to_flo(mrb, y), 0, &mod);
829 return mrb_float_value(mrb, mod);
831 #endif
835 * call-seq:
836 * fix.divmod(numeric) -> array
838 * See <code>Numeric#divmod</code>.
840 static mrb_value
841 fix_divmod(mrb_state *mrb, mrb_value x)
843 mrb_value y;
845 mrb_get_args(mrb, "o", &y);
847 if (mrb_fixnum_p(y)) {
848 mrb_int div, mod;
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));
853 #else
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));
858 #endif
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");
865 #else
866 else {
867 mrb_float div, mod;
868 mrb_value a, b;
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);
875 #endif
878 #ifndef MRB_WITHOUT_FLOAT
879 static mrb_value
880 flo_divmod(mrb_state *mrb, mrb_value x)
882 mrb_value y;
883 mrb_float div, mod;
884 mrb_value a, b;
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);
893 #endif
895 /* 15.2.8.3.7 */
897 * call-seq:
898 * fix == other -> true or false
900 * Return <code>true</code> if <code>fix</code> equals <code>other</code>
901 * numerically.
903 * 1 == 2 #=> false
904 * 1 == 1.0 #=> true
907 static mrb_value
908 fix_equal(mrb_state *mrb, mrb_value x)
910 mrb_value y;
912 mrb_get_args(mrb, "o", &y);
913 switch (mrb_type(y)) {
914 case MRB_TT_FIXNUM:
915 return mrb_bool_value(mrb_fixnum(x) == mrb_fixnum(y));
916 #ifndef MRB_WITHOUT_FLOAT
917 case MRB_TT_FLOAT:
918 return mrb_bool_value((mrb_float)mrb_fixnum(x) == mrb_float(y));
919 #endif
920 default:
921 return mrb_false_value();
925 /* 15.2.8.3.8 */
927 * call-seq:
928 * ~fix -> integer
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)
936 static mrb_value
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));\
947 } while(0)
948 #else
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)));\
955 } while(0)
956 #endif
958 /* 15.2.8.3.9 */
960 * call-seq:
961 * fix & integer -> integer_result
963 * Bitwise AND.
966 static mrb_value
967 fix_and(mrb_state *mrb, mrb_value x)
969 mrb_value y;
971 mrb_get_args(mrb, "o", &y);
972 bit_op(x, y, and, &);
975 /* 15.2.8.3.10 */
977 * call-seq:
978 * fix | integer -> integer_result
980 * Bitwise OR.
983 static mrb_value
984 fix_or(mrb_state *mrb, mrb_value x)
986 mrb_value y;
988 mrb_get_args(mrb, "o", &y);
989 bit_op(x, y, or, |);
992 /* 15.2.8.3.11 */
994 * call-seq:
995 * fix ^ integer -> integer_result
997 * Bitwise EXCLUSIVE OR.
1000 static mrb_value
1001 fix_xor(mrb_state *mrb, mrb_value x)
1003 mrb_value y;
1005 mrb_get_args(mrb, "o", &y);
1006 bit_op(x, y, or, ^);
1009 #define NUMERIC_SHIFT_WIDTH_MAX (MRB_INT_BIT-1)
1011 static mrb_value
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);
1017 #else
1018 return mrb_float_value(mrb, INFINITY);
1019 #endif
1021 if (val > 0) {
1022 if ((width > NUMERIC_SHIFT_WIDTH_MAX) ||
1023 (val > (MRB_INT_MAX >> width))) {
1024 #ifdef MRB_WITHOUT_FLOAT
1025 return mrb_fixnum_value(-1);
1026 #else
1027 goto bit_overflow;
1028 #endif
1030 return mrb_fixnum_value(val << width);
1032 else {
1033 if ((width > NUMERIC_SHIFT_WIDTH_MAX) ||
1034 (val < (MRB_INT_MIN >> width))) {
1035 #ifdef MRB_WITHOUT_FLOAT
1036 return mrb_fixnum_value(0);
1037 #else
1038 goto bit_overflow;
1039 #endif
1041 return mrb_fixnum_value(val * ((mrb_int)1 << width));
1044 #ifndef MRB_WITHOUT_FLOAT
1045 bit_overflow:
1047 mrb_float f = (mrb_float)val;
1048 while (width--) {
1049 f *= 2;
1051 return mrb_float_value(mrb, f);
1053 #endif
1056 static mrb_value
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) {
1063 if (val < 0) {
1064 return mrb_fixnum_value(-1);
1066 return mrb_fixnum_value(0);
1068 return mrb_fixnum_value(val >> width);
1071 /* 15.2.8.3.12 */
1073 * call-seq:
1074 * fix << count -> integer or float
1076 * Shifts _fix_ left _count_ positions (right if _count_ is negative).
1079 static mrb_value
1080 fix_lshift(mrb_state *mrb, mrb_value x)
1082 mrb_int width, val;
1084 mrb_get_args(mrb, "i", &width);
1085 if (width == 0) {
1086 return x;
1088 val = mrb_fixnum(x);
1089 if (val == 0) return x;
1090 if (width < 0) {
1091 return rshift(val, -width);
1093 return lshift(mrb, val, width);
1096 /* 15.2.8.3.13 */
1098 * call-seq:
1099 * fix >> count -> integer or float
1101 * Shifts _fix_ right _count_ positions (left if _count_ is negative).
1104 static mrb_value
1105 fix_rshift(mrb_state *mrb, mrb_value x)
1107 mrb_int width, val;
1109 mrb_get_args(mrb, "i", &width);
1110 if (width == 0) {
1111 return x;
1113 val = mrb_fixnum(x);
1114 if (val == 0) return x;
1115 if (width < 0) {
1116 return lshift(mrb, val, -width);
1118 return rshift(val, width);
1121 /* 15.2.8.3.23 */
1123 * call-seq:
1124 * fix.to_f -> float
1126 * Converts <i>fix</i> to a <code>Float</code>.
1130 #ifndef MRB_WITHOUT_FLOAT
1131 static mrb_value
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 /* ------------------------------------------------------------------------*/
1151 MRB_API mrb_value
1152 mrb_flo_to_fixnum(mrb_state *mrb, mrb_value x)
1154 mrb_int z = 0;
1156 if (!mrb_float_p(x)) {
1157 mrb_raise(mrb, E_TYPE_ERROR, "non float value");
1158 z = 0; /* not reached. just suppress warnings. */
1160 else {
1161 mrb_float d = mrb_float(x);
1163 if (isinf(d)) {
1164 mrb_raise(mrb, E_FLOATDOMAIN_ERROR, d < 0 ? "-Infinity" : "Infinity");
1166 if (isnan(d)) {
1167 mrb_raise(mrb, E_FLOATDOMAIN_ERROR, "NaN");
1169 if (FIXABLE_FLOAT(d)) {
1170 z = (mrb_int)d;
1172 else {
1173 mrb_raisef(mrb, E_ARGUMENT_ERROR, "number (%S) too big for integer", x);
1176 return mrb_fixnum_value(z);
1178 #endif
1180 mrb_value
1181 mrb_fixnum_plus(mrb_state *mrb, mrb_value x, mrb_value y)
1183 mrb_int a;
1185 a = mrb_fixnum(x);
1186 if (mrb_fixnum_p(y)) {
1187 mrb_int b, c;
1189 if (a == 0) return y;
1190 b = mrb_fixnum(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);
1194 #endif
1196 return mrb_fixnum_value(c);
1198 #ifdef MRB_WITHOUT_FLOAT
1199 mrb_raise(mrb, E_TYPE_ERROR, "non fixnum value");
1200 #else
1201 return mrb_float_value(mrb, (mrb_float)a + mrb_to_flo(mrb, y));
1202 #endif
1205 /* 15.2.8.3.1 */
1207 * call-seq:
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
1212 * result.
1214 static mrb_value
1215 fix_plus(mrb_state *mrb, mrb_value self)
1217 mrb_value other;
1219 mrb_get_args(mrb, "o", &other);
1220 return mrb_fixnum_plus(mrb, self, other);
1223 mrb_value
1224 mrb_fixnum_minus(mrb_state *mrb, mrb_value x, mrb_value y)
1226 mrb_int a;
1228 a = mrb_fixnum(x);
1229 if (mrb_fixnum_p(y)) {
1230 mrb_int b, c;
1232 b = mrb_fixnum(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);
1236 #endif
1238 return mrb_fixnum_value(c);
1240 #ifdef MRB_WITHOUT_FLOAT
1241 mrb_raise(mrb, E_TYPE_ERROR, "non fixnum value");
1242 #else
1243 return mrb_float_value(mrb, (mrb_float)a - mrb_to_flo(mrb, y));
1244 #endif
1247 /* 15.2.8.3.2 */
1248 /* 15.2.8.3.16 */
1250 * call-seq:
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
1255 * result.
1257 static mrb_value
1258 fix_minus(mrb_state *mrb, mrb_value self)
1260 mrb_value other;
1262 mrb_get_args(mrb, "o", &other);
1263 return mrb_fixnum_minus(mrb, self, other);
1267 MRB_API mrb_value
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));
1278 if (val == 0) {
1279 *--b = '0';
1281 else if (val < 0) {
1282 do {
1283 *--b = mrb_digitmap[-(val % base)];
1284 } while (val /= base);
1285 *--b = '-';
1287 else {
1288 do {
1289 *--b = mrb_digitmap[(int)(val % base)];
1290 } while (val /= base);
1293 return mrb_str_new(mrb, b, buf + sizeof(buf) - b);
1296 /* 15.2.8.3.25 */
1298 * call-seq:
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"
1312 static mrb_value
1313 fix_to_s(mrb_state *mrb, mrb_value self)
1315 mrb_int base = 10;
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) */
1322 static mrb_int
1323 cmpnum(mrb_state *mrb, mrb_value v1, mrb_value v2)
1325 #ifdef MRB_WITHOUT_FLOAT
1326 mrb_int x, y;
1327 #else
1328 mrb_float x, y;
1329 #endif
1331 #ifdef MRB_WITHOUT_FLOAT
1332 x = mrb_fixnum(v1);
1333 #else
1334 x = mrb_to_flo(mrb, v1);
1335 #endif
1336 switch (mrb_type(v2)) {
1337 case MRB_TT_FIXNUM:
1338 #ifdef MRB_WITHOUT_FLOAT
1339 y = mrb_fixnum(v2);
1340 #else
1341 y = (mrb_float)mrb_fixnum(v2);
1342 #endif
1343 break;
1344 #ifndef MRB_WITHOUT_FLOAT
1345 case MRB_TT_FLOAT:
1346 y = mrb_float(v2);
1347 break;
1348 #endif
1349 default:
1350 return -2;
1352 if (x > y)
1353 return 1;
1354 else {
1355 if (x < y)
1356 return -1;
1357 return 0;
1361 /* 15.2.9.3.6 */
1363 * call-seq:
1364 * self.f <=> other.f => -1, 0, +1
1365 * < => -1
1366 * = => 0
1367 * > => +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>.
1372 static mrb_value
1373 num_cmp(mrb_state *mrb, mrb_value self)
1375 mrb_value other;
1376 mrb_int n;
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);
1384 static void
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)));
1392 static mrb_value
1393 num_lt(mrb_state *mrb, mrb_value self)
1395 mrb_value other;
1396 mrb_int n;
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();
1405 static mrb_value
1406 num_le(mrb_state *mrb, mrb_value self)
1408 mrb_value other;
1409 mrb_int n;
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();
1418 static mrb_value
1419 num_gt(mrb_state *mrb, mrb_value self)
1421 mrb_value other;
1422 mrb_int n;
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();
1431 static mrb_value
1432 num_ge(mrb_state *mrb, mrb_value self)
1434 mrb_value other;
1435 mrb_int n;
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();
1444 static mrb_value
1445 num_finite_p(mrb_state *mrb, mrb_value self)
1447 mrb_get_args(mrb, "");
1448 return mrb_true_value();
1451 static mrb_value
1452 num_infinite_p(mrb_state *mrb, mrb_value self)
1454 mrb_get_args(mrb, "");
1455 return mrb_false_value();
1458 /* 15.2.9.3.1 */
1460 * call-seq:
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
1467 static mrb_value
1468 flo_plus(mrb_state *mrb, mrb_value x)
1470 mrb_value y;
1472 mrb_get_args(mrb, "o", &y);
1473 return mrb_float_value(mrb, mrb_float(x) + mrb_to_flo(mrb, y));
1475 #endif
1477 /* ------------------------------------------------------------------------*/
1478 void
1479 mrb_init_numeric(mrb_state *mrb)
1481 struct RClass *numeric, *integer, *fixnum;
1482 #ifndef MRB_WITHOUT_FLOAT
1483 struct RClass *fl;
1484 #endif
1486 /* Numeric Class */
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());
1500 /* Integer Class */
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) */
1511 #endif
1513 /* Fixnum Class */
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 */
1529 #endif
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
1535 /* Float Class */
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());
1566 #ifdef INFINITY
1567 mrb_define_const(mrb, fl, "INFINITY", mrb_float_value(mrb, INFINITY));
1568 #endif
1569 #ifdef NAN
1570 mrb_define_const(mrb, fl, "NAN", mrb_float_value(mrb, NAN));
1571 #endif
1572 #endif
1573 mrb_define_module(mrb, "Integral");