numeric.c
DEFINITIONS
This source file includes following functions.
- rb_num_zerodiv
- num_coerce
- coerce_body
- coerce_rescue
- do_coerce
- rb_num_coerce_bin
- num_become
- num_uplus
- num_uminus
- num_div
- num_divmod
- num_modulo
- num_remainder
- num_int_p
- num_abs
- num_zero_p
- num_nonzero_p
- num_to_int
- rb_float_new
- flo_to_s
- flo_coerce
- flo_uminus
- flo_plus
- flo_minus
- flo_mul
- flo_div
- flodivmod
- flo_mod
- flo_divmod
- flo_pow
- num_eql
- num_equal
- flo_eq
- flo_hash
- rb_dbl_cmp
- flo_cmp
- flo_gt
- flo_ge
- flo_lt
- flo_le
- flo_eql
- flo_to_f
- flo_abs
- flo_zero_p
- flo_is_nan_p
- flo_is_infinite_p
- flo_is_finite_p
- flo_floor
- flo_ceil
- flo_round
- flo_truncate
- num_floor
- num_ceil
- num_round
- num_truncate
- num_step
- rb_num2long
- rb_num2ulong
- rb_num2int
- rb_fix2int
- rb_num2int
- rb_fix2int
- rb_num2fix
- rb_num2ll
- rb_num2ull
- int_to_i
- int_int_p
- int_succ
- int_chr
- rb_fix_induced_from
- rb_int_induced_from
- rb_flo_induced_from
- fix_uminus
- rb_fix2str
- fix_to_s
- fix_plus
- fix_minus
- fix_mul
- fixdivmod
- fix_div
- fix_mod
- fix_divmod
- fix_pow
- fix_equal
- fix_cmp
- fix_gt
- fix_ge
- fix_lt
- fix_le
- fix_rev
- fix_and
- fix_or
- fix_xor
- fix_lshift
- fix_rshift
- fix_aref
- fix_to_f
- fix_abs
- fix_id2name
- fix_size
- int_upto
- int_downto
- int_dotimes
- fix_zero_p
- Init_Numeric
1
2
3
4
5
6
7
8
9
10
11
12
13 #include "ruby.h"
14 #include <math.h>
15 #include <stdio.h>
16 #if defined(__FreeBSD__) && __FreeBSD__ < 4
17 #include <floatingpoint.h>
18 #endif
19
20 static ID id_coerce, id_to_i, id_div;
21
22 VALUE rb_cNumeric;
23 VALUE rb_cFloat;
24 VALUE rb_cInteger;
25 VALUE rb_cFixnum;
26
27 VALUE rb_eZeroDivError;
28 VALUE rb_eFloatDomainError;
29
30 void
31 rb_num_zerodiv()
32 {
33 rb_raise(rb_eZeroDivError, "divided by 0");
34 }
35
36 static VALUE
37 num_coerce(x, y)
38 VALUE x, y;
39 {
40 if (CLASS_OF(x) == CLASS_OF(y))
41 return rb_assoc_new(y, x);
42 return rb_assoc_new(rb_Float(y), rb_Float(x));
43 }
44
45 static VALUE
46 coerce_body(x)
47 VALUE *x;
48 {
49 return rb_funcall(x[1], id_coerce, 1, x[0]);
50 }
51
52 static VALUE
53 coerce_rescue(x)
54 VALUE *x;
55 {
56 rb_raise(rb_eTypeError, "%s can't be coerced into %s",
57 rb_special_const_p(x[1])?
58 RSTRING(rb_inspect(x[1]))->ptr:
59 rb_class2name(CLASS_OF(x[1])),
60 rb_class2name(CLASS_OF(x[0])));
61 return Qnil;
62 }
63
64 static void
65 do_coerce(x, y)
66 VALUE *x, *y;
67 {
68 VALUE ary;
69 VALUE a[2];
70
71 a[0] = *x; a[1] = *y;
72
73 ary = rb_rescue(coerce_body, (VALUE)a, coerce_rescue, (VALUE)a);
74 if (TYPE(ary) != T_ARRAY || RARRAY(ary)->len != 2) {
75 rb_raise(rb_eTypeError, "coerce must return [x, y]");
76 }
77
78 *x = RARRAY(ary)->ptr[0];
79 *y = RARRAY(ary)->ptr[1];
80 }
81
82 VALUE
83 rb_num_coerce_bin(x, y)
84 VALUE x, y;
85 {
86 do_coerce(&x, &y);
87 return rb_funcall(x, rb_frame_last_func(), 1, y);
88 }
89
90 static VALUE
91 num_become(x, y)
92 VALUE x, y;
93 {
94
95 rb_raise(rb_eTypeError, "can't copy %s", rb_class2name(CLASS_OF(x)));
96 return Qnil;
97 }
98
99 static VALUE
100 num_uplus(num)
101 VALUE num;
102 {
103 return num;
104 }
105
106 static VALUE
107 num_uminus(num)
108 VALUE num;
109 {
110 VALUE zero;
111
112 zero = INT2FIX(0);
113 do_coerce(&zero, &num);
114
115 return rb_funcall(zero, '-', 1, num);
116 }
117
118 static VALUE
119 num_div(x, y)
120 VALUE x, y;
121 {
122 return rb_funcall(x, id_div, 1, y);
123 }
124
125 static VALUE
126 num_divmod(x, y)
127 VALUE x, y;
128 {
129 VALUE div, mod;
130
131 div = rb_funcall(x, id_div, 1, y);
132 if (TYPE(div) == T_FLOAT) {
133 double d = floor(RFLOAT(div)->value);
134
135 if (RFLOAT(div)->value > d) {
136 div = rb_float_new(d);
137 }
138 }
139 mod = rb_funcall(x, '%', 1, y);
140 return rb_assoc_new(div, mod);
141 }
142
143 static VALUE
144 num_modulo(x, y)
145 VALUE x, y;
146 {
147 return rb_funcall(x, '%', 1, y);
148 }
149
150 static VALUE
151 num_remainder(x, y)
152 VALUE x, y;
153 {
154 VALUE z = rb_funcall(x, '%', 1, y);
155
156 if ((!rb_equal(z, INT2FIX(0))) &&
157 ((RTEST(rb_funcall(x, '<', 1, INT2FIX(0))) &&
158 RTEST(rb_funcall(y, '>', 1, INT2FIX(0)))) ||
159 (RTEST(rb_funcall(x, '>', 1, INT2FIX(0))) &&
160 RTEST(rb_funcall(y, '<', 1, INT2FIX(0)))))) {
161 return rb_funcall(z, '-', 1, y);
162 }
163 return z;
164 }
165
166 static VALUE
167 num_int_p(num)
168 VALUE num;
169 {
170 return Qfalse;
171 }
172
173 static VALUE
174 num_abs(num)
175 VALUE num;
176 {
177 if (RTEST(rb_funcall(num, '<', 1, INT2FIX(0)))) {
178 return rb_funcall(num, rb_intern("-@"), 0);
179 }
180 return num;
181 }
182
183 static VALUE
184 num_zero_p(num)
185 VALUE num;
186 {
187 if (rb_equal(num, INT2FIX(0))) {
188 return Qtrue;
189 }
190 return Qfalse;
191 }
192
193 static VALUE
194 num_nonzero_p(num)
195 VALUE num;
196 {
197 if (RTEST(rb_funcall(num, rb_intern("zero?"), 0, 0))) {
198 return Qnil;
199 }
200 return num;
201 }
202
203 static VALUE
204 num_to_int(num)
205 VALUE num;
206 {
207 return rb_funcall(num, id_to_i, 0, 0);
208 }
209
210 VALUE
211 rb_float_new(d)
212 double d;
213 {
214 NEWOBJ(flt, struct RFloat);
215 OBJSETUP(flt, rb_cFloat, T_FLOAT);
216
217 flt->value = d;
218 return (VALUE)flt;
219 }
220
221 static VALUE
222 flo_to_s(flt)
223 VALUE flt;
224 {
225 char buf[24];
226 char *fmt = "%.16g";
227 double value = RFLOAT(flt)->value;
228 double avalue, d1, d2;
229
230 if (isinf(value))
231 return rb_str_new2(value < 0 ? "-Infinity" : "Infinity");
232 else if(isnan(value))
233 return rb_str_new2("NaN");
234
235 avalue = fabs(value);
236 if (avalue == 0.0) {
237 fmt = "%.1f";
238 }
239 else if (avalue < 1.0e-3) {
240 d1 = avalue;
241 while (d1 < 1.0) d1 *= 10.0;
242 d1 = modf(d1, &d2);
243 if (d1 == 0) fmt = "%.1e";
244 }
245 else if (avalue >= 1.0e15) {
246 d1 = avalue;
247 while (d1 > 10.0) d1 /= 10.0;
248 d1 = modf(d1, &d2);
249 if (d1 == 0) fmt = "%.1e";
250 else fmt = "%.16e";
251 }
252 else if ((d1 = modf(value, &d2)) == 0) {
253 fmt = "%.1f";
254 }
255 sprintf(buf, fmt, value);
256
257 return rb_str_new2(buf);
258 }
259
260 static VALUE
261 flo_coerce(x, y)
262 VALUE x, y;
263 {
264 return rb_assoc_new(rb_Float(y), x);
265 }
266
267 static VALUE
268 flo_uminus(flt)
269 VALUE flt;
270 {
271 return rb_float_new(-RFLOAT(flt)->value);
272 }
273
274 static VALUE
275 flo_plus(x, y)
276 VALUE x, y;
277 {
278 switch (TYPE(y)) {
279 case T_FIXNUM:
280 return rb_float_new(RFLOAT(x)->value + (double)FIX2LONG(y));
281 case T_BIGNUM:
282 return rb_float_new(RFLOAT(x)->value + rb_big2dbl(y));
283 case T_FLOAT:
284 return rb_float_new(RFLOAT(x)->value + RFLOAT(y)->value);
285 default:
286 return rb_num_coerce_bin(x, y);
287 }
288 }
289
290 static VALUE
291 flo_minus(x, y)
292 VALUE x, y;
293 {
294 switch (TYPE(y)) {
295 case T_FIXNUM:
296 return rb_float_new(RFLOAT(x)->value - (double)FIX2LONG(y));
297 case T_BIGNUM:
298 return rb_float_new(RFLOAT(x)->value - rb_big2dbl(y));
299 case T_FLOAT:
300 return rb_float_new(RFLOAT(x)->value - RFLOAT(y)->value);
301 default:
302 return rb_num_coerce_bin(x, y);
303 }
304 }
305
306 static VALUE
307 flo_mul(x, y)
308 VALUE x, y;
309 {
310 switch (TYPE(y)) {
311 case T_FIXNUM:
312 return rb_float_new(RFLOAT(x)->value * (double)FIX2LONG(y));
313 case T_BIGNUM:
314 return rb_float_new(RFLOAT(x)->value * rb_big2dbl(y));
315 case T_FLOAT:
316 return rb_float_new(RFLOAT(x)->value * RFLOAT(y)->value);
317 default:
318 return rb_num_coerce_bin(x, y);
319 }
320 }
321
322 static VALUE
323 flo_div(x, y)
324 VALUE x, y;
325 {
326 long f_y;
327 double d;
328
329 switch (TYPE(y)) {
330 case T_FIXNUM:
331 f_y = FIX2LONG(y);
332 return rb_float_new(RFLOAT(x)->value / (double)f_y);
333 case T_BIGNUM:
334 d = rb_big2dbl(y);
335 return rb_float_new(RFLOAT(x)->value / d);
336 case T_FLOAT:
337 return rb_float_new(RFLOAT(x)->value / RFLOAT(y)->value);
338 default:
339 return rb_num_coerce_bin(x, y);
340 }
341 }
342
343 static void
344 flodivmod(x, y, divp, modp)
345 double x, y;
346 double *divp, *modp;
347 {
348 double div, mod;
349
350 #ifdef HAVE_FMOD
351 mod = fmod(x, y);
352 #else
353 {
354 double z;
355
356 modf(x/y, &z);
357 mod = x - z * y;
358 }
359 #endif
360 div = (x - mod) / y;
361 if (y*mod < 0) {
362 mod += y;
363 div -= 1.0;
364 }
365 if (modp) *modp = mod;
366 if (divp) *divp = div;
367 }
368
369 static VALUE
370 flo_mod(x, y)
371 VALUE x, y;
372 {
373 double fy, mod;
374
375 switch (TYPE(y)) {
376 case T_FIXNUM:
377 fy = (double)FIX2LONG(y);
378 break;
379 case T_BIGNUM:
380 fy = rb_big2dbl(y);
381 break;
382 case T_FLOAT:
383 fy = RFLOAT(y)->value;
384 break;
385 default:
386 return rb_num_coerce_bin(x, y);
387 }
388 flodivmod(RFLOAT(x)->value, fy, 0, &mod);
389 return rb_float_new(mod);
390 }
391
392 static VALUE
393 flo_divmod(x, y)
394 VALUE x, y;
395 {
396 double fy, div, mod;
397
398 switch (TYPE(y)) {
399 case T_FIXNUM:
400 fy = (double)FIX2LONG(y);
401 break;
402 case T_BIGNUM:
403 fy = rb_big2dbl(y);
404 break;
405 case T_FLOAT:
406 fy = RFLOAT(y)->value;
407 break;
408 default:
409 return rb_num_coerce_bin(x, y);
410 }
411 flodivmod(RFLOAT(x)->value, fy, &div, &mod);
412 return rb_assoc_new(rb_float_new(div), rb_float_new(mod));
413 }
414
415 static VALUE
416 flo_pow(x, y)
417 VALUE x, y;
418 {
419 switch (TYPE(y)) {
420 case T_FIXNUM:
421 return rb_float_new(pow(RFLOAT(x)->value, (double)FIX2LONG(y)));
422 case T_BIGNUM:
423 return rb_float_new(pow(RFLOAT(x)->value, rb_big2dbl(y)));
424 case T_FLOAT:
425 return rb_float_new(pow(RFLOAT(x)->value, RFLOAT(y)->value));
426 default:
427 return rb_num_coerce_bin(x, y);
428 }
429 }
430
431 static VALUE
432 num_eql(x, y)
433 VALUE x, y;
434 {
435 if (TYPE(x) != TYPE(y)) return Qfalse;
436
437 return rb_equal(x, y);
438 }
439
440 static VALUE
441 num_equal(x, y)
442 VALUE x, y;
443 {
444 return rb_equal(y, x);
445 }
446
447 static VALUE
448 flo_eq(x, y)
449 VALUE x, y;
450 {
451 switch (TYPE(y)) {
452 case T_FIXNUM:
453 if (RFLOAT(x)->value == FIX2LONG(y)) return Qtrue;
454 return Qfalse;
455 case T_BIGNUM:
456 return (RFLOAT(x)->value == rb_big2dbl(y))?Qtrue:Qfalse;
457 case T_FLOAT:
458 return (RFLOAT(x)->value == RFLOAT(y)->value)?Qtrue:Qfalse;
459 default:
460 return num_equal(x, y);
461 }
462 }
463
464 static VALUE
465 flo_hash(num)
466 VALUE num;
467 {
468 double d;
469 char *c;
470 int i, hash;
471
472 d = RFLOAT(num)->value;
473 if (d == 0) d = fabs(d);
474 c = (char*)&d;
475 for (hash=0, i=0; i<sizeof(double);i++) {
476 hash += c[i] * 971;
477 }
478 if (hash < 0) hash = -hash;
479 return INT2FIX(hash);
480 }
481
482 VALUE
483 rb_dbl_cmp(a, b)
484 double a, b;
485 {
486 if (a == b) return INT2FIX(0);
487 if (a > b) return INT2FIX(1);
488 if (a < b) return INT2FIX(-1);
489 rb_raise(rb_eFloatDomainError, "comparing NaN");
490 }
491
492 static VALUE
493 flo_cmp(x, y)
494 VALUE x, y;
495 {
496 double a, b;
497
498 a = RFLOAT(x)->value;
499 switch (TYPE(y)) {
500 case T_FIXNUM:
501 b = (double)FIX2LONG(y);
502 break;
503
504 case T_BIGNUM:
505 b = rb_big2dbl(y);
506 break;
507
508 case T_FLOAT:
509 b = RFLOAT(y)->value;
510 break;
511
512 default:
513 return rb_num_coerce_bin(x, y);
514 }
515 return rb_dbl_cmp(a, b);
516 }
517
518 static VALUE
519 flo_gt(x, y)
520 VALUE x, y;
521 {
522 double a, b;
523
524 a = RFLOAT(x)->value;
525 switch (TYPE(y)) {
526 case T_FIXNUM:
527 b = (double)FIX2LONG(y);
528 break;
529
530 case T_BIGNUM:
531 b = rb_big2dbl(y);
532 break;
533
534 case T_FLOAT:
535 b = RFLOAT(y)->value;
536 break;
537
538 default:
539 return rb_num_coerce_bin(x, y);
540 }
541 return (a > b)?Qtrue:Qfalse;
542 }
543
544 static VALUE
545 flo_ge(x, y)
546 VALUE x, y;
547 {
548 double a, b;
549
550 a = RFLOAT(x)->value;
551 switch (TYPE(y)) {
552 case T_FIXNUM:
553 b = (double)FIX2LONG(y);
554 break;
555
556 case T_BIGNUM:
557 b = rb_big2dbl(y);
558 break;
559
560 case T_FLOAT:
561 b = RFLOAT(y)->value;
562 break;
563
564 default:
565 return rb_num_coerce_bin(x, y);
566 }
567 return (a >= b)?Qtrue:Qfalse;
568 }
569
570 static VALUE
571 flo_lt(x, y)
572 VALUE x, y;
573 {
574 double a, b;
575
576 a = RFLOAT(x)->value;
577 switch (TYPE(y)) {
578 case T_FIXNUM:
579 b = (double)FIX2LONG(y);
580 break;
581
582 case T_BIGNUM:
583 b = rb_big2dbl(y);
584 break;
585
586 case T_FLOAT:
587 b = RFLOAT(y)->value;
588 break;
589
590 default:
591 return rb_num_coerce_bin(x, y);
592 }
593 return (a < b)?Qtrue:Qfalse;
594 }
595
596 static VALUE
597 flo_le(x, y)
598 VALUE x, y;
599 {
600 double a, b;
601
602 a = RFLOAT(x)->value;
603 switch (TYPE(y)) {
604 case T_FIXNUM:
605 b = (double)FIX2LONG(y);
606 break;
607
608 case T_BIGNUM:
609 b = rb_big2dbl(y);
610 break;
611
612 case T_FLOAT:
613 b = RFLOAT(y)->value;
614 break;
615
616 default:
617 return rb_num_coerce_bin(x, y);
618 }
619 return (a <= b)?Qtrue:Qfalse;
620 }
621
622 static VALUE
623 flo_eql(x, y)
624 VALUE x, y;
625 {
626 if (TYPE(y) == T_FLOAT && RFLOAT(x)->value == RFLOAT(y)->value) {
627 return Qtrue;
628 }
629 return Qfalse;
630 }
631
632 static VALUE
633 flo_to_f(num)
634 VALUE num;
635 {
636 return num;
637 }
638
639 static VALUE
640 flo_abs(flt)
641 VALUE flt;
642 {
643 double val = fabs(RFLOAT(flt)->value);
644 return rb_float_new(val);
645 }
646
647 static VALUE
648 flo_zero_p(num)
649 VALUE num;
650 {
651 if (RFLOAT(num)->value == 0.0) {
652 return Qtrue;
653 }
654 return Qfalse;
655 }
656
657 static VALUE
658 flo_is_nan_p(num)
659 VALUE num;
660 {
661
662 double value = RFLOAT(num)->value;
663
664 return isnan(value) ? Qtrue : Qfalse;
665 }
666
667 static VALUE
668 flo_is_infinite_p(num)
669 VALUE num;
670 {
671 double value = RFLOAT(num)->value;
672
673 if (isinf(value)) {
674 return INT2FIX( value < 0 ? -1 : 1 );
675 }
676
677 return Qnil;
678 }
679
680 static VALUE
681 flo_is_finite_p(num)
682 VALUE num;
683 {
684 double value = RFLOAT(num)->value;
685
686 if (isinf(value) || isnan(value))
687 return Qfalse;
688
689 return Qtrue;
690 }
691
692
693 static VALUE
694 flo_floor(num)
695 VALUE num;
696 {
697 double f = floor(RFLOAT(num)->value);
698 long val;
699
700 if (!FIXABLE(f)) {
701 return rb_dbl2big(f);
702 }
703 val = f;
704 return LONG2FIX(val);
705 }
706
707 static VALUE
708 flo_ceil(num)
709 VALUE num;
710 {
711 double f = ceil(RFLOAT(num)->value);
712 long val;
713
714 if (!FIXABLE(f)) {
715 return rb_dbl2big(f);
716 }
717 val = f;
718 return LONG2FIX(val);
719 }
720
721 static VALUE
722 flo_round(num)
723 VALUE num;
724 {
725 double f = RFLOAT(num)->value;
726 long val;
727
728 if (f > 0.0) f = floor(f+0.5);
729 if (f < 0.0) f = ceil(f-0.5);
730
731 if (!FIXABLE(f)) {
732 return rb_dbl2big(f);
733 }
734 val = f;
735 return LONG2FIX(val);
736 }
737
738 static VALUE
739 flo_truncate(num)
740 VALUE num;
741 {
742 double f = RFLOAT(num)->value;
743 long val;
744
745 if (f > 0.0) f = floor(f);
746 if (f < 0.0) f = ceil(f);
747
748 if (!FIXABLE(f)) {
749 return rb_dbl2big(f);
750 }
751 val = f;
752 return LONG2FIX(val);
753 }
754
755 static VALUE
756 num_floor(num)
757 VALUE num;
758 {
759 return flo_floor(rb_Float(num));
760 }
761
762 static VALUE
763 num_ceil(num)
764 VALUE num;
765 {
766 return flo_ceil(rb_Float(num));
767 }
768
769 static VALUE
770 num_round(num)
771 VALUE num;
772 {
773 return flo_round(rb_Float(num));
774 }
775
776 static VALUE
777 num_truncate(num)
778 VALUE num;
779 {
780 return flo_truncate(rb_Float(num));
781 }
782
783 static VALUE
784 num_step(argc, argv, from)
785 int argc;
786 VALUE *argv;
787 VALUE from;
788 {
789 VALUE to, step;
790
791 if (rb_scan_args(argc, argv, "11", &to, &step) == 1) {
792 step = INT2FIX(1);
793 }
794 else if (rb_equal(step, INT2FIX(0))) {
795 rb_raise(rb_eArgError, "step cannot be 0");
796 }
797
798 if (FIXNUM_P(from) && FIXNUM_P(to) && FIXNUM_P(step)) {
799 long i, end, diff;
800
801 i = FIX2LONG(from);
802 end = FIX2LONG(to);
803 diff = FIX2LONG(step);
804
805 if (diff > 0) {
806 while (i <= end) {
807 rb_yield(LONG2FIX(i));
808 i += diff;
809 }
810 }
811 else {
812 while (i >= end) {
813 rb_yield(LONG2FIX(i));
814 i += diff;
815 }
816 }
817 }
818 else if (TYPE(from) == T_FLOAT || TYPE(to) == T_FLOAT || TYPE(step) == T_FLOAT) {
819 const double epsilon = 2.2204460492503131E-16;
820 double beg = NUM2DBL(from);
821 double end = NUM2DBL(to);
822 double unit = NUM2DBL(step);
823 double n = (end - beg)/unit;
824 long i;
825
826 n = floor(n + n*epsilon) + 1;
827 for (i=0; i<n; i++) {
828 rb_yield(rb_float_new(i*unit+beg));
829 }
830 }
831 else {
832 VALUE i = from;
833 ID cmp;
834
835 if (RTEST(rb_funcall(step, '>', 1, INT2FIX(0)))) {
836 cmp = '>';
837 }
838 else {
839 cmp = '<';
840 }
841 for (;;) {
842 if (RTEST(rb_funcall(i, cmp, 1, to))) break;
843 rb_yield(i);
844 i = rb_funcall(i, '+', 1, step);
845 }
846 }
847 return from;
848 }
849
850 long
851 rb_num2long(val)
852 VALUE val;
853 {
854 if (NIL_P(val)) {
855 rb_raise(rb_eTypeError, "no implicit conversion from nil to integer");
856 }
857
858 if (FIXNUM_P(val)) return FIX2LONG(val);
859
860 switch (TYPE(val)) {
861 case T_FLOAT:
862 if (RFLOAT(val)->value <= (double)LONG_MAX
863 && RFLOAT(val)->value >= (double)LONG_MIN) {
864 return (long)(RFLOAT(val)->value);
865 }
866 else {
867 char buf[24];
868 char *s;
869
870 sprintf(buf, "%-.10g", RFLOAT(val)->value);
871 if (s = strchr(buf, ' ')) *s = '\0';
872 rb_raise(rb_eRangeError, "float %s out of range of integer", buf);
873 }
874
875 case T_BIGNUM:
876 return rb_big2long(val);
877
878 default:
879 val = rb_to_int(val);
880 return NUM2LONG(val);
881 }
882 }
883
884 unsigned long
885 rb_num2ulong(val)
886 VALUE val;
887 {
888 if (TYPE(val) == T_BIGNUM) {
889 return rb_big2ulong(val);
890 }
891 return (unsigned long)rb_num2long(val);
892 }
893
894 #if SIZEOF_INT < SIZEOF_LONG
895 int
896 rb_num2int(val)
897 VALUE val;
898 {
899 long num = rb_num2long(val);
900
901 if (num < INT_MIN || INT_MAX < num) {
902 rb_raise(rb_eRangeError, "integer %ld too big to convert to `int'", num);
903 }
904 return (int)num;
905 }
906
907 int
908 rb_fix2int(val)
909 VALUE val;
910 {
911 long num = FIXNUM_P(val)?FIX2LONG(val):rb_num2long(val);
912
913 if (num < INT_MIN || INT_MAX < num) {
914 rb_raise(rb_eRangeError, "integer %ld too big to convert to `int'", num);
915 }
916 return (int)num;
917 }
918 #else
919 int
920 rb_num2int(val)
921 VALUE val;
922 {
923 return rb_num2long(val);
924 }
925
926 int
927 rb_fix2int(val)
928 VALUE val;
929 {
930 return FIX2INT(val);
931 }
932 #endif
933
934 VALUE
935 rb_num2fix(val)
936 VALUE val;
937 {
938 long v;
939
940 if (FIXNUM_P(val)) return val;
941
942 v = rb_num2long(val);
943 if (!FIXABLE(v))
944 rb_raise(rb_eRangeError, "integer %ld out of range of fixnum", v);
945 return LONG2FIX(v);
946 }
947
948 #if HAVE_LONG_LONG
949
950 LONG_LONG
951 rb_num2ll(val)
952 VALUE val;
953 {
954 if (NIL_P(val)) {
955 rb_raise(rb_eTypeError, "no implicit conversion from nil");
956 }
957
958 if (FIXNUM_P(val)) return (LONG_LONG)FIX2LONG(val);
959
960 switch (TYPE(val)) {
961 case T_FLOAT:
962 if (RFLOAT(val)->value <= (double)LLONG_MAX
963 && RFLOAT(val)->value >= (double)LLONG_MIN) {
964 return (LONG_LONG)(RFLOAT(val)->value);
965 }
966 else {
967 char buf[24];
968 char *s;
969
970 sprintf(buf, "%-.10g", RFLOAT(val)->value);
971 if (s = strchr(buf, ' ')) *s = '\0';
972 rb_raise(rb_eRangeError, "float %s out of range of long long", buf);
973 }
974
975 case T_BIGNUM:
976 return rb_big2ll(val);
977
978 case T_STRING:
979 rb_raise(rb_eTypeError, "no implicit conversion from string");
980 return Qnil;
981
982 case T_TRUE:
983 case T_FALSE:
984 rb_raise(rb_eTypeError, "no implicit conversion from boolean");
985 return Qnil;
986
987 default:
988 val = rb_to_int(val);
989 return NUM2LL(val);
990 }
991 }
992
993 unsigned LONG_LONG
994 rb_num2ull(val)
995 VALUE val;
996 {
997 if (TYPE(val) == T_BIGNUM) {
998 return rb_big2ull(val);
999 }
1000 return (unsigned LONG_LONG)rb_num2ll(val);
1001 }
1002
1003 #endif
1004
1005 static VALUE
1006 int_to_i(num)
1007 VALUE num;
1008 {
1009 return num;
1010 }
1011
1012 static VALUE
1013 int_int_p(num)
1014 VALUE num;
1015 {
1016 return Qtrue;
1017 }
1018
1019 static VALUE
1020 int_succ(num)
1021 VALUE num;
1022 {
1023 if (FIXNUM_P(num)) {
1024 long i = FIX2LONG(num) + 1;
1025 return LONG2NUM(i);
1026 }
1027 return rb_funcall(num, '+', 1, INT2FIX(1));
1028 }
1029
1030 static VALUE
1031 int_chr(num)
1032 VALUE num;
1033 {
1034 char c;
1035 long i = NUM2LONG(num);
1036
1037 if (i < 0 || 0xff < i)
1038 rb_raise(rb_eRangeError, "%ld out of char range", i);
1039 c = i;
1040 return rb_str_new(&c, 1);
1041 }
1042
1043 static VALUE
1044 rb_fix_induced_from(klass, x)
1045 VALUE klass, x;
1046 {
1047 return rb_num2fix(x);
1048 }
1049
1050 static VALUE
1051 rb_int_induced_from(klass, x)
1052 VALUE klass, x;
1053 {
1054 switch (TYPE(x)) {
1055 case T_FIXNUM:
1056 case T_BIGNUM:
1057 return x;
1058 case T_FLOAT:
1059 return rb_funcall(x, id_to_i, 0);
1060 default:
1061 rb_raise(rb_eTypeError, "failed to convert %s into Integer",
1062 rb_class2name(CLASS_OF(x)));
1063 }
1064 }
1065
1066 static VALUE
1067 rb_flo_induced_from(klass, x)
1068 VALUE klass, x;
1069 {
1070 switch (TYPE(x)) {
1071 case T_FIXNUM:
1072 case T_BIGNUM:
1073 return rb_funcall(x, rb_intern("to_f"), 0);
1074 case T_FLOAT:
1075 return x;
1076 default:
1077 rb_raise(rb_eTypeError, "failed to convert %s into Float",
1078 rb_class2name(CLASS_OF(x)));
1079 }
1080 }
1081
1082 static VALUE
1083 fix_uminus(num)
1084 VALUE num;
1085 {
1086 return LONG2NUM(-FIX2LONG(num));
1087 }
1088
1089 VALUE
1090 rb_fix2str(x, base)
1091 VALUE x;
1092 int base;
1093 {
1094 char fmt[4], buf[22], *b = buf;
1095 long val = FIX2LONG(x);
1096
1097 fmt[0] = '%'; fmt[1] = 'l'; fmt[3] = '\0';
1098 if (base == 10) fmt[2] = 'd';
1099 else if (base == 16) fmt[2] = 'x';
1100 else if (base == 8) fmt[2] = 'o';
1101 else rb_raise(rb_eArgError, "illegal radix %d", base);
1102 if (val < 0) {
1103 val = -val;
1104 *b++ = '-';
1105 }
1106
1107 sprintf(b, fmt, val);
1108 return rb_str_new2(buf);
1109 }
1110
1111 static VALUE
1112 fix_to_s(argc, argv, x)
1113 int argc;
1114 VALUE *argv;
1115 VALUE x;
1116 {
1117 VALUE b;
1118 int base;
1119
1120 rb_scan_args(argc, argv, "01", &b);
1121 if (argc == 0) base = 10;
1122 else base = NUM2INT(b);
1123
1124 if (base == 2) {
1125
1126 return rb_big2str(rb_int2big(FIX2INT(x)), 2);
1127 }
1128 return rb_fix2str(x, base);
1129 }
1130
1131 static VALUE
1132 fix_plus(x, y)
1133 VALUE x, y;
1134 {
1135 if (FIXNUM_P(y)) {
1136 long a, b, c;
1137 VALUE r;
1138
1139 a = FIX2LONG(x);
1140 b = FIX2LONG(y);
1141 c = a + b;
1142 r = LONG2FIX(c);
1143
1144 if (FIX2LONG(r) != c) {
1145 r = rb_big_plus(rb_int2big(a), rb_int2big(b));
1146 }
1147 return r;
1148 }
1149 if (TYPE(y) == T_FLOAT) {
1150 return rb_float_new((double)FIX2LONG(x) + RFLOAT(y)->value);
1151 }
1152 return rb_num_coerce_bin(x, y);
1153 }
1154
1155 static VALUE
1156 fix_minus(x, y)
1157 VALUE x, y;
1158 {
1159 if (FIXNUM_P(y)) {
1160 long a, b, c;
1161 VALUE r;
1162
1163 a = FIX2LONG(x);
1164 b = FIX2LONG(y);
1165 c = a - b;
1166 r = LONG2FIX(c);
1167
1168 if (FIX2LONG(r) != c) {
1169 r = rb_big_minus(rb_int2big(a), rb_int2big(b));
1170 }
1171 return r;
1172 }
1173 if (TYPE(y) == T_FLOAT) {
1174 return rb_float_new((double)FIX2LONG(x) - RFLOAT(y)->value);
1175 }
1176 return rb_num_coerce_bin(x, y);
1177 }
1178
1179 static VALUE
1180 fix_mul(x, y)
1181 VALUE x, y;
1182 {
1183 if (FIXNUM_P(y)) {
1184 long a, b, c;
1185 VALUE r;
1186
1187 a = FIX2LONG(x);
1188 if (a == 0) return x;
1189
1190 b = FIX2LONG(y);
1191 c = a * b;
1192 r = LONG2FIX(c);
1193
1194 if (FIX2LONG(r) != c || c/a != b) {
1195 r = rb_big_mul(rb_int2big(a), rb_int2big(b));
1196 }
1197 return r;
1198 }
1199 if (TYPE(y) == T_FLOAT) {
1200 return rb_float_new((double)FIX2LONG(x) * RFLOAT(y)->value);
1201 }
1202 return rb_num_coerce_bin(x, y);
1203 }
1204
1205 static void
1206 fixdivmod(x, y, divp, modp)
1207 long x, y;
1208 long *divp, *modp;
1209 {
1210 long div, mod;
1211
1212 if (y == 0) rb_num_zerodiv();
1213 if (y < 0) {
1214 if (x < 0)
1215 div = -x / -y;
1216 else
1217 div = - (x / -y);
1218 }
1219 else {
1220 if (x < 0)
1221 div = - (-x / y);
1222 else
1223 div = x / y;
1224 }
1225 mod = x - div*y;
1226 if ((mod < 0 && y > 0) || (mod > 0 && y < 0)) {
1227 mod += y;
1228 div -= 1;
1229 }
1230 if (divp) *divp = div;
1231 if (modp) *modp = mod;
1232 }
1233
1234 static VALUE
1235 fix_div(x, y)
1236 VALUE x, y;
1237 {
1238 if (FIXNUM_P(y)) {
1239 long div;
1240
1241 fixdivmod(FIX2LONG(x), FIX2LONG(y), &div, 0);
1242 return LONG2NUM(div);
1243 }
1244 return rb_num_coerce_bin(x, y);
1245 }
1246
1247 static VALUE
1248 fix_mod(x, y)
1249 VALUE x, y;
1250 {
1251 if (FIXNUM_P(y)) {
1252 long mod;
1253
1254 fixdivmod(FIX2LONG(x), FIX2LONG(y), 0, &mod);
1255 return LONG2NUM(mod);
1256 }
1257 return rb_num_coerce_bin(x, y);
1258 }
1259
1260 static VALUE
1261 fix_divmod(x, y)
1262 VALUE x, y;
1263 {
1264 if (FIXNUM_P(y)) {
1265 long div, mod;
1266
1267 fixdivmod(FIX2LONG(x), FIX2LONG(y), &div, &mod);
1268
1269 return rb_assoc_new(LONG2NUM(div), LONG2NUM(mod));
1270 }
1271 return rb_num_coerce_bin(x, y);
1272 }
1273
1274 static VALUE
1275 fix_pow(x, y)
1276 VALUE x, y;
1277 {
1278 if (FIXNUM_P(y)) {
1279 long a, b;
1280
1281 b = FIX2LONG(y);
1282 if (b == 0) return INT2FIX(1);
1283 if (b == 1) return x;
1284 a = FIX2LONG(x);
1285 if (b > 0) {
1286 return rb_big_pow(rb_int2big(a), y);
1287 }
1288 return rb_float_new(pow((double)a, (double)b));
1289 }
1290 return rb_num_coerce_bin(x, y);
1291 }
1292
1293 static VALUE
1294 fix_equal(x, y)
1295 VALUE x, y;
1296 {
1297 if (FIXNUM_P(y)) {
1298 return (FIX2LONG(x) == FIX2LONG(y))?Qtrue:Qfalse;
1299 }
1300 else {
1301 return num_equal(x, y);
1302 }
1303 }
1304
1305 static VALUE
1306 fix_cmp(x, y)
1307 VALUE x, y;
1308 {
1309 if (FIXNUM_P(y)) {
1310 long a = FIX2LONG(x), b = FIX2LONG(y);
1311
1312 if (a == b) return INT2FIX(0);
1313 if (a > b) return INT2FIX(1);
1314 return INT2FIX(-1);
1315 }
1316 else {
1317 return rb_num_coerce_bin(x, y);
1318 }
1319 }
1320
1321 static VALUE
1322 fix_gt(x, y)
1323 VALUE x, y;
1324 {
1325 if (FIXNUM_P(y)) {
1326 long a = FIX2LONG(x), b = FIX2LONG(y);
1327
1328 if (a > b) return Qtrue;
1329 return Qfalse;
1330 }
1331 else {
1332 return rb_num_coerce_bin(x, y);
1333 }
1334 }
1335
1336 static VALUE
1337 fix_ge(x, y)
1338 VALUE x, y;
1339 {
1340 if (FIXNUM_P(y)) {
1341 long a = FIX2LONG(x), b = FIX2LONG(y);
1342
1343 if (a >= b) return Qtrue;
1344 return Qfalse;
1345 }
1346 else {
1347 return rb_num_coerce_bin(x, y);
1348 }
1349 }
1350
1351 static VALUE
1352 fix_lt(x, y)
1353 VALUE x, y;
1354 {
1355 if (FIXNUM_P(y)) {
1356 long a = FIX2LONG(x), b = FIX2LONG(y);
1357
1358 if (a < b) return Qtrue;
1359 return Qfalse;
1360 }
1361 else {
1362 return rb_num_coerce_bin(x, y);
1363 }
1364 }
1365
1366 static VALUE
1367 fix_le(x, y)
1368 VALUE x, y;
1369 {
1370 if (FIXNUM_P(y)) {
1371 long a = FIX2LONG(x), b = FIX2LONG(y);
1372
1373 if (a <= b) return Qtrue;
1374 return Qfalse;
1375 }
1376 else {
1377 return rb_num_coerce_bin(x, y);
1378 }
1379 }
1380
1381 static VALUE
1382 fix_rev(num)
1383 VALUE num;
1384 {
1385 long val = FIX2LONG(num);
1386
1387 val = ~val;
1388 return LONG2NUM(val);
1389 }
1390
1391 static VALUE
1392 fix_and(x, y)
1393 VALUE x, y;
1394 {
1395 long val;
1396
1397 if (TYPE(y) == T_BIGNUM) {
1398 return rb_big_and(y, x);
1399 }
1400 val = FIX2LONG(x) & NUM2LONG(y);
1401 return LONG2NUM(val);
1402 }
1403
1404 static VALUE
1405 fix_or(x, y)
1406 VALUE x, y;
1407 {
1408 long val;
1409
1410 if (TYPE(y) == T_BIGNUM) {
1411 return rb_big_or(y, x);
1412 }
1413 val = FIX2LONG(x) | NUM2LONG(y);
1414 return LONG2NUM(val);
1415 }
1416
1417 static VALUE
1418 fix_xor(x, y)
1419 VALUE x, y;
1420 {
1421 long val;
1422
1423 if (TYPE(y) == T_BIGNUM) {
1424 return rb_big_xor(y, x);
1425 }
1426 val = FIX2LONG(x) ^ NUM2LONG(y);
1427 return LONG2NUM(val);
1428 }
1429
1430 static VALUE fix_rshift _((VALUE, VALUE));
1431
1432 static VALUE
1433 fix_lshift(x, y)
1434 VALUE x, y;
1435 {
1436 long val, width;
1437
1438 val = NUM2LONG(x);
1439 width = NUM2LONG(y);
1440 if (width < 0)
1441 return fix_rshift(x, LONG2FIX(-width));
1442 if (width > (sizeof(VALUE)*CHAR_BIT-1)
1443 || ((unsigned long)val)>>(sizeof(VALUE)*CHAR_BIT-1-width) > 0) {
1444 return rb_big_lshift(rb_int2big(val), y);
1445 }
1446 val = val << width;
1447 return LONG2NUM(val);
1448 }
1449
1450 static VALUE
1451 fix_rshift(x, y)
1452 VALUE x, y;
1453 {
1454 long i, val;
1455
1456 i = NUM2LONG(y);
1457 if (i < 0)
1458 return fix_lshift(x, LONG2FIX(-i));
1459 if (i == 0) return x;
1460 val = FIX2LONG(x);
1461 if (i >= sizeof(long)*CHAR_BIT-1) {
1462 if (val < 0) return INT2FIX(-1);
1463 return INT2FIX(0);
1464 }
1465 val = RSHIFT(val, i);
1466 return LONG2FIX(val);
1467 }
1468
1469 static VALUE
1470 fix_aref(fix, idx)
1471 VALUE fix, idx;
1472 {
1473 long val = FIX2LONG(fix);
1474 long i;
1475
1476 if (TYPE(idx) == T_BIGNUM) {
1477 idx = rb_big_norm(idx);
1478 if (!FIXNUM_P(idx)) {
1479 if (!RBIGNUM(idx)->sign || val >= 0)
1480 return INT2FIX(0);
1481 return INT2FIX(1);
1482 }
1483 }
1484 i = NUM2LONG(idx);
1485
1486 if (i < 0) return INT2FIX(0);
1487 if (sizeof(VALUE)*CHAR_BIT-1 < i) {
1488 if (val < 0) return INT2FIX(1);
1489 return INT2FIX(0);
1490 }
1491 if (val & (1L<<i))
1492 return INT2FIX(1);
1493 return INT2FIX(0);
1494 }
1495
1496 static VALUE
1497 fix_to_f(num)
1498 VALUE num;
1499 {
1500 double val;
1501
1502 val = (double)FIX2LONG(num);
1503
1504 return rb_float_new(val);
1505 }
1506
1507 static VALUE
1508 fix_abs(fix)
1509 VALUE fix;
1510 {
1511 long i = FIX2LONG(fix);
1512
1513 if (i < 0) i = -i;
1514
1515 return LONG2NUM(i);
1516 }
1517
1518 static VALUE
1519 fix_id2name(fix)
1520 VALUE fix;
1521 {
1522 char *name = rb_id2name(FIX2UINT(fix));
1523 if (name) return rb_str_new2(name);
1524 return Qnil;
1525 }
1526
1527 static VALUE
1528 fix_size(fix)
1529 VALUE fix;
1530 {
1531 return INT2FIX(sizeof(long));
1532 }
1533
1534 static VALUE
1535 int_upto(from, to)
1536 VALUE from, to;
1537 {
1538 if (FIXNUM_P(from) && FIXNUM_P(to)) {
1539 long i, end;
1540
1541 end = FIX2LONG(to);
1542 for (i = FIX2LONG(from); i <= end; i++) {
1543 rb_yield(LONG2FIX(i));
1544 }
1545 }
1546 else {
1547 VALUE i = from;
1548
1549 for (;;) {
1550 if (RTEST(rb_funcall(i, '>', 1, to))) break;
1551 rb_yield(i);
1552 i = rb_funcall(i, '+', 1, INT2FIX(1));
1553 }
1554 }
1555 return from;
1556 }
1557
1558 static VALUE
1559 int_downto(from, to)
1560 VALUE from, to;
1561 {
1562 if (FIXNUM_P(from) && FIXNUM_P(to)) {
1563 long i, end;
1564
1565 end = FIX2LONG(to);
1566 for (i=FIX2LONG(from); i >= end; i--) {
1567 rb_yield(LONG2FIX(i));
1568 }
1569 }
1570 else {
1571 VALUE i = from;
1572
1573 for (;;) {
1574 if (RTEST(rb_funcall(i, '<', 1, to))) break;
1575 rb_yield(i);
1576 i = rb_funcall(i, '-', 1, INT2FIX(1));
1577 }
1578 }
1579 return from;
1580 }
1581
1582 static VALUE
1583 int_dotimes(num)
1584 VALUE num;
1585 {
1586 if (FIXNUM_P(num)) {
1587 long i, end;
1588
1589 end = FIX2LONG(num);
1590 for (i=0; i<end; i++) {
1591 rb_yield(LONG2FIX(i));
1592 }
1593 }
1594 else {
1595 VALUE i = INT2FIX(0);
1596
1597 for (;;) {
1598 if (!RTEST(rb_funcall(i, '<', 1, num))) break;
1599 rb_yield(i);
1600 i = rb_funcall(i, '+', 1, INT2FIX(1));
1601 }
1602 }
1603 return num;
1604 }
1605
1606 static VALUE
1607 fix_zero_p(num)
1608 VALUE num;
1609 {
1610 if (FIX2LONG(num) == 0) {
1611 return Qtrue;
1612 }
1613 return Qfalse;
1614 }
1615
1616 void
1617 Init_Numeric()
1618 {
1619 #if defined(__FreeBSD__) && __FreeBSD__ < 4
1620
1621 fpsetmask(fpgetmask() & ~(FP_X_DZ|FP_X_INV|FP_X_OFL));
1622 #endif
1623 id_coerce = rb_intern("coerce");
1624 id_to_i = rb_intern("to_i");
1625 id_div = rb_intern("div");
1626
1627 rb_eZeroDivError = rb_define_class("ZeroDivisionError", rb_eStandardError);
1628 rb_eFloatDomainError = rb_define_class("FloatDomainError", rb_eRangeError);
1629 rb_cNumeric = rb_define_class("Numeric", rb_cObject);
1630
1631 rb_include_module(rb_cNumeric, rb_mComparable);
1632 rb_define_method(rb_cNumeric, "coerce", num_coerce, 1);
1633 rb_define_method(rb_cNumeric, "become", num_become, 1);
1634
1635 rb_define_method(rb_cNumeric, "+@", num_uplus, 0);
1636 rb_define_method(rb_cNumeric, "-@", num_uminus, 0);
1637 rb_define_method(rb_cNumeric, "===", num_equal, 1);
1638 rb_define_method(rb_cNumeric, "eql?", num_eql, 1);
1639 rb_define_method(rb_cNumeric, "/", num_div, 1);
1640 rb_define_method(rb_cNumeric, "divmod", num_divmod, 1);
1641 rb_define_method(rb_cNumeric, "modulo", num_modulo, 1);
1642 rb_define_method(rb_cNumeric, "remainder", num_remainder, 1);
1643 rb_define_method(rb_cNumeric, "abs", num_abs, 0);
1644 rb_define_method(rb_cNumeric, "to_int", num_to_int, 0);
1645
1646 rb_define_method(rb_cNumeric, "integer?", num_int_p, 0);
1647 rb_define_method(rb_cNumeric, "zero?", num_zero_p, 0);
1648 rb_define_method(rb_cNumeric, "nonzero?", num_nonzero_p, 0);
1649
1650 rb_define_method(rb_cNumeric, "floor", num_floor, 0);
1651 rb_define_method(rb_cNumeric, "ceil", num_ceil, 0);
1652 rb_define_method(rb_cNumeric, "round", num_round, 0);
1653 rb_define_method(rb_cNumeric, "truncate", num_truncate, 0);
1654 rb_define_method(rb_cNumeric, "step", num_step, -1);
1655
1656 rb_cInteger = rb_define_class("Integer", rb_cNumeric);
1657 rb_undef_method(CLASS_OF(rb_cInteger), "allocate");
1658 rb_undef_method(CLASS_OF(rb_cInteger), "new");
1659
1660 rb_define_method(rb_cInteger, "integer?", int_int_p, 0);
1661 rb_define_method(rb_cInteger, "upto", int_upto, 1);
1662 rb_define_method(rb_cInteger, "downto", int_downto, 1);
1663 rb_define_method(rb_cInteger, "times", int_dotimes, 0);
1664 rb_include_module(rb_cInteger, rb_mPrecision);
1665 rb_define_method(rb_cInteger, "succ", int_succ, 0);
1666 rb_define_method(rb_cInteger, "next", int_succ, 0);
1667 rb_define_method(rb_cInteger, "chr", int_chr, 0);
1668 rb_define_method(rb_cInteger, "to_i", int_to_i, 0);
1669 rb_define_method(rb_cInteger, "to_int", int_to_i, 0);
1670 rb_define_method(rb_cInteger, "floor", int_to_i, 0);
1671 rb_define_method(rb_cInteger, "ceil", int_to_i, 0);
1672 rb_define_method(rb_cInteger, "round", int_to_i, 0);
1673 rb_define_method(rb_cInteger, "truncate", int_to_i, 0);
1674
1675 rb_cFixnum = rb_define_class("Fixnum", rb_cInteger);
1676 rb_include_module(rb_cFixnum, rb_mPrecision);
1677 rb_define_singleton_method(rb_cFixnum, "induced_from", rb_fix_induced_from, 1);
1678 rb_define_singleton_method(rb_cInteger, "induced_from", rb_int_induced_from, 1);
1679
1680 rb_define_method(rb_cFixnum, "to_s", fix_to_s, -1);
1681
1682 rb_define_method(rb_cFixnum, "id2name", fix_id2name, 0);
1683
1684 rb_define_method(rb_cFixnum, "-@", fix_uminus, 0);
1685 rb_define_method(rb_cFixnum, "+", fix_plus, 1);
1686 rb_define_method(rb_cFixnum, "-", fix_minus, 1);
1687 rb_define_method(rb_cFixnum, "*", fix_mul, 1);
1688 rb_define_method(rb_cFixnum, "/", fix_div, 1);
1689 rb_define_method(rb_cFixnum, "div", fix_div, 1);
1690 rb_define_method(rb_cFixnum, "%", fix_mod, 1);
1691 rb_define_method(rb_cFixnum, "modulo", fix_mod, 1);
1692 rb_define_method(rb_cFixnum, "divmod", fix_divmod, 1);
1693 rb_define_method(rb_cFixnum, "**", fix_pow, 1);
1694
1695 rb_define_method(rb_cFixnum, "abs", fix_abs, 0);
1696
1697 rb_define_method(rb_cFixnum, "==", fix_equal, 1);
1698 rb_define_method(rb_cFixnum, "<=>", fix_cmp, 1);
1699 rb_define_method(rb_cFixnum, ">", fix_gt, 1);
1700 rb_define_method(rb_cFixnum, ">=", fix_ge, 1);
1701 rb_define_method(rb_cFixnum, "<", fix_lt, 1);
1702 rb_define_method(rb_cFixnum, "<=", fix_le, 1);
1703
1704 rb_define_method(rb_cFixnum, "~", fix_rev, 0);
1705 rb_define_method(rb_cFixnum, "&", fix_and, 1);
1706 rb_define_method(rb_cFixnum, "|", fix_or, 1);
1707 rb_define_method(rb_cFixnum, "^", fix_xor, 1);
1708 rb_define_method(rb_cFixnum, "[]", fix_aref, 1);
1709
1710 rb_define_method(rb_cFixnum, "<<", fix_lshift, 1);
1711 rb_define_method(rb_cFixnum, ">>", fix_rshift, 1);
1712
1713 rb_define_method(rb_cFixnum, "to_f", fix_to_f, 0);
1714 rb_define_method(rb_cFixnum, "size", fix_size, 0);
1715 rb_define_method(rb_cFixnum, "zero?", fix_zero_p, 0);
1716
1717 rb_cFloat = rb_define_class("Float", rb_cNumeric);
1718
1719 rb_undef_method(CLASS_OF(rb_cFloat), "allocate");
1720 rb_undef_method(CLASS_OF(rb_cFloat), "new");
1721
1722 rb_define_singleton_method(rb_cFloat, "induced_from", rb_flo_induced_from, 1);
1723 rb_include_module(rb_cFloat, rb_mPrecision);
1724
1725 rb_define_method(rb_cFloat, "to_s", flo_to_s, 0);
1726 rb_define_method(rb_cFloat, "coerce", flo_coerce, 1);
1727 rb_define_method(rb_cFloat, "-@", flo_uminus, 0);
1728 rb_define_method(rb_cFloat, "+", flo_plus, 1);
1729 rb_define_method(rb_cFloat, "-", flo_minus, 1);
1730 rb_define_method(rb_cFloat, "*", flo_mul, 1);
1731 rb_define_method(rb_cFloat, "/", flo_div, 1);
1732 rb_define_method(rb_cFloat, "%", flo_mod, 1);
1733 rb_define_method(rb_cFloat, "modulo", flo_mod, 1);
1734 rb_define_method(rb_cFloat, "divmod", flo_divmod, 1);
1735 rb_define_method(rb_cFloat, "**", flo_pow, 1);
1736 rb_define_method(rb_cFloat, "==", flo_eq, 1);
1737 rb_define_method(rb_cFloat, "<=>", flo_cmp, 1);
1738 rb_define_method(rb_cFloat, ">", flo_gt, 1);
1739 rb_define_method(rb_cFloat, ">=", flo_ge, 1);
1740 rb_define_method(rb_cFloat, "<", flo_lt, 1);
1741 rb_define_method(rb_cFloat, "<=", flo_le, 1);
1742 rb_define_method(rb_cFloat, "eql?", flo_eql, 1);
1743 rb_define_method(rb_cFloat, "hash", flo_hash, 0);
1744 rb_define_method(rb_cFloat, "to_f", flo_to_f, 0);
1745 rb_define_method(rb_cFloat, "abs", flo_abs, 0);
1746 rb_define_method(rb_cFloat, "zero?", flo_zero_p, 0);
1747
1748 rb_define_method(rb_cFloat, "to_i", flo_truncate, 0);
1749 rb_define_method(rb_cFloat, "to_int", flo_truncate, 0);
1750 rb_define_method(rb_cFloat, "floor", flo_floor, 0);
1751 rb_define_method(rb_cFloat, "ceil", flo_ceil, 0);
1752 rb_define_method(rb_cFloat, "round", flo_round, 0);
1753 rb_define_method(rb_cFloat, "truncate", flo_truncate, 0);
1754
1755 rb_define_method(rb_cFloat, "nan?", flo_is_nan_p, 0);
1756 rb_define_method(rb_cFloat, "infinite?", flo_is_infinite_p, 0);
1757 rb_define_method(rb_cFloat, "finite?", flo_is_finite_p, 0);
1758 }
1759