27 |
27 |
|
28 |
28 |
#define GMP_GCD_DIGITS 1
|
29 |
29 |
|
|
30 |
#define INT_POSITIVE_P(x) (FIXNUM_P(x) ? ((SIGNED_VALUE)(x) > (SIGNED_VALUE)INT2FIX(0)) : BIGNUM_POSITIVE_P(x))
|
|
31 |
#define INT_NEGATIVE_P(x) (FIXNUM_P(x) ? ((SIGNED_VALUE)(x) < 0) : BIGNUM_NEGATIVE_P(x))
|
|
32 |
#define INT_ZERO_P(x) (FIXNUM_P(x) ? (FIX2LONG(x) == 0) : rb_bigzero_p(x))
|
|
33 |
|
30 |
34 |
VALUE rb_cRational;
|
31 |
35 |
|
32 |
|
static ID id_abs, id_cmp, id_convert, id_eqeq_p, id_expt, id_fdiv,
|
33 |
|
id_idiv, id_integer_p, id_negate, id_to_f,
|
34 |
|
id_to_i, id_truncate, id_i_num, id_i_den;
|
|
36 |
static ID id_abs, id_eqeq_p, id_idiv, id_integer_p, id_negate, id_to_i,
|
|
37 |
id_i_num, id_i_den;
|
35 |
38 |
|
36 |
39 |
#define f_boolcast(x) ((x) ? Qtrue : Qfalse)
|
37 |
40 |
#define f_inspect rb_inspect
|
... | ... | |
69 |
72 |
}
|
70 |
73 |
|
71 |
74 |
inline static VALUE
|
72 |
|
f_cmp(VALUE x, VALUE y)
|
73 |
|
{
|
74 |
|
if (FIXNUM_P(x) && FIXNUM_P(y)) {
|
75 |
|
long c = FIX2LONG(x) - FIX2LONG(y);
|
76 |
|
if (c > 0)
|
77 |
|
c = 1;
|
78 |
|
else if (c < 0)
|
79 |
|
c = -1;
|
80 |
|
return INT2FIX(c);
|
81 |
|
}
|
82 |
|
return rb_funcall(x, id_cmp, 1, y);
|
83 |
|
}
|
84 |
|
|
85 |
|
inline static VALUE
|
86 |
75 |
f_div(VALUE x, VALUE y)
|
87 |
76 |
{
|
88 |
77 |
if (FIXNUM_P(y) && FIX2LONG(y) == 1)
|
89 |
78 |
return x;
|
|
79 |
if (FIXNUM_P(x) || RB_TYPE_P(x, T_BIGNUM))
|
|
80 |
return rb_int_div(x, y);
|
90 |
81 |
return rb_funcall(x, '/', 1, y);
|
91 |
82 |
}
|
92 |
83 |
|
... | ... | |
120 |
111 |
}
|
121 |
112 |
else if (ix == 1)
|
122 |
113 |
return y;
|
|
114 |
return rb_int_mul(x, y);
|
123 |
115 |
}
|
|
116 |
else if (RB_TYPE_P(x, T_BIGNUM))
|
|
117 |
return rb_int_mul(x, y);
|
124 |
118 |
return rb_funcall(x, '*', 1, y);
|
125 |
119 |
}
|
126 |
120 |
|
... | ... | |
132 |
126 |
return rb_funcall(x, '-', 1, y);
|
133 |
127 |
}
|
134 |
128 |
|
135 |
|
fun1(abs)
|
|
129 |
inline static VALUE
|
|
130 |
f_abs(VALUE x)
|
|
131 |
{
|
|
132 |
if (FIXNUM_P(x) || RB_TYPE_P(x, T_BIGNUM))
|
|
133 |
return rb_int_abs(x);
|
|
134 |
return rb_funcall(x, id_abs, 0);
|
|
135 |
}
|
|
136 |
|
136 |
137 |
fun1(integer_p)
|
137 |
138 |
fun1(negate)
|
138 |
139 |
|
... | ... | |
143 |
144 |
return rb_str_to_inum(x, 10, 0);
|
144 |
145 |
return rb_funcall(x, id_to_i, 0);
|
145 |
146 |
}
|
146 |
|
inline static VALUE
|
147 |
|
f_to_f(VALUE x)
|
148 |
|
{
|
149 |
|
if (RB_TYPE_P(x, T_STRING))
|
150 |
|
return DBL2NUM(rb_str_to_dbl(x, 0));
|
151 |
|
return rb_funcall(x, id_to_f, 0);
|
152 |
|
}
|
153 |
147 |
|
154 |
148 |
inline static VALUE
|
155 |
149 |
f_eqeq_p(VALUE x, VALUE y)
|
... | ... | |
159 |
153 |
return rb_funcall(x, id_eqeq_p, 1, y);
|
160 |
154 |
}
|
161 |
155 |
|
162 |
|
fun2(expt)
|
163 |
|
fun2(fdiv)
|
164 |
156 |
fun2(idiv)
|
165 |
157 |
|
166 |
|
#define f_expt10(x) f_expt(INT2FIX(10), x)
|
167 |
|
|
168 |
|
inline static VALUE
|
169 |
|
f_negative_p(VALUE x)
|
170 |
|
{
|
171 |
|
if (FIXNUM_P(x))
|
172 |
|
return f_boolcast(FIX2LONG(x) < 0);
|
173 |
|
return rb_funcall(x, '<', 1, ZERO);
|
174 |
|
}
|
175 |
|
|
176 |
|
#define f_positive_p(x) (!f_negative_p(x))
|
|
158 |
#define f_expt10(x) rb_int_pow(INT2FIX(10), x)
|
177 |
159 |
|
178 |
160 |
inline static VALUE
|
179 |
161 |
f_zero_p(VALUE x)
|
... | ... | |
327 |
309 |
if (FIXNUM_P(x) && FIXNUM_P(y))
|
328 |
310 |
return LONG2NUM(i_gcd(FIX2LONG(x), FIX2LONG(y)));
|
329 |
311 |
|
330 |
|
if (f_negative_p(x))
|
331 |
|
x = f_negate(x);
|
332 |
|
if (f_negative_p(y))
|
333 |
|
y = f_negate(y);
|
|
312 |
if (INT_NEGATIVE_P(x))
|
|
313 |
x = rb_int_uminus(x);
|
|
314 |
if (INT_NEGATIVE_P(y))
|
|
315 |
y = rb_int_uminus(y);
|
334 |
316 |
|
335 |
|
if (f_zero_p(x))
|
|
317 |
if (INT_ZERO_P(x))
|
336 |
318 |
return y;
|
337 |
|
if (f_zero_p(y))
|
|
319 |
if (INT_ZERO_P(y))
|
338 |
320 |
return x;
|
339 |
321 |
|
340 |
322 |
for (;;) {
|
... | ... | |
345 |
327 |
return LONG2NUM(i_gcd(FIX2LONG(x), FIX2LONG(y)));
|
346 |
328 |
}
|
347 |
329 |
z = x;
|
348 |
|
x = f_mod(y, x);
|
|
330 |
x = rb_int_modulo(y, x);
|
349 |
331 |
y = z;
|
350 |
332 |
}
|
351 |
333 |
/* NOTREACHED */
|
... | ... | |
389 |
371 |
inline static VALUE
|
390 |
372 |
f_lcm(VALUE x, VALUE y)
|
391 |
373 |
{
|
392 |
|
if (f_zero_p(x) || f_zero_p(y))
|
|
374 |
if (INT_ZERO_P(x) || INT_ZERO_P(y))
|
393 |
375 |
return ZERO;
|
394 |
376 |
return f_abs(f_mul(f_div(x, f_gcd(x, y)), y));
|
395 |
377 |
}
|
... | ... | |
420 |
402 |
return nurat_s_new_internal(klass, ZERO, ONE);
|
421 |
403 |
}
|
422 |
404 |
|
423 |
|
#define rb_raise_zerodiv() rb_raise(rb_eZeroDivError, "divided by 0")
|
424 |
|
|
425 |
405 |
#if 0
|
426 |
406 |
static VALUE
|
427 |
407 |
nurat_s_new_bang(int argc, VALUE *argv, VALUE klass)
|
... | ... | |
440 |
420 |
if (!k_integer_p(den))
|
441 |
421 |
den = f_to_i(den);
|
442 |
422 |
|
443 |
|
switch (FIX2INT(f_cmp(den, ZERO))) {
|
|
423 |
switch (FIX2INT(rb_int_cmp(den, ZERO))) {
|
444 |
424 |
case -1:
|
445 |
425 |
num = f_negate(num);
|
446 |
426 |
den = f_negate(den);
|
447 |
427 |
break;
|
448 |
428 |
case 0:
|
449 |
|
rb_raise_zerodiv();
|
|
429 |
rb_num_zerodiv();
|
450 |
430 |
break;
|
451 |
431 |
}
|
452 |
432 |
break;
|
... | ... | |
499 |
479 |
{
|
500 |
480 |
VALUE gcd;
|
501 |
481 |
|
502 |
|
switch (FIX2INT(f_cmp(den, ZERO))) {
|
|
482 |
switch (FIX2INT(rb_int_cmp(den, ZERO))) {
|
503 |
483 |
case -1:
|
504 |
484 |
num = f_negate(num);
|
505 |
485 |
den = f_negate(den);
|
506 |
486 |
break;
|
507 |
487 |
case 0:
|
508 |
|
rb_raise_zerodiv();
|
|
488 |
rb_num_zerodiv();
|
509 |
489 |
break;
|
510 |
490 |
}
|
511 |
491 |
|
... | ... | |
523 |
503 |
inline static VALUE
|
524 |
504 |
nurat_s_canonicalize_internal_no_reduce(VALUE klass, VALUE num, VALUE den)
|
525 |
505 |
{
|
526 |
|
switch (FIX2INT(f_cmp(den, ZERO))) {
|
|
506 |
switch (FIX2INT(rb_int_cmp(den, ZERO))) {
|
527 |
507 |
case -1:
|
528 |
508 |
num = f_negate(num);
|
529 |
509 |
den = f_negate(den);
|
530 |
510 |
break;
|
531 |
511 |
case 0:
|
532 |
|
rb_raise_zerodiv();
|
|
512 |
rb_num_zerodiv();
|
533 |
513 |
break;
|
534 |
514 |
}
|
535 |
515 |
|
... | ... | |
575 |
555 |
return nurat_s_canonicalize_internal_no_reduce(klass, x, y);
|
576 |
556 |
}
|
577 |
557 |
|
|
558 |
static VALUE nurat_s_convert(int argc, VALUE *argv, VALUE klass);
|
578 |
559 |
/*
|
579 |
560 |
* call-seq:
|
580 |
561 |
* Rational(x[, y]) -> numeric
|
... | ... | |
605 |
586 |
static VALUE
|
606 |
587 |
nurat_f_rational(int argc, VALUE *argv, VALUE klass)
|
607 |
588 |
{
|
608 |
|
return rb_funcall2(rb_cRational, id_convert, argc, argv);
|
|
589 |
return nurat_s_convert(argc, argv, rb_cRational);
|
609 |
590 |
}
|
610 |
591 |
|
611 |
592 |
/*
|
... | ... | |
645 |
626 |
return dat->den;
|
646 |
627 |
}
|
647 |
628 |
|
|
629 |
/*
|
|
630 |
* call-seq:
|
|
631 |
* -rat -> rational
|
|
632 |
*
|
|
633 |
* Negates +rat+.
|
|
634 |
*/
|
|
635 |
static VALUE
|
|
636 |
nurat_negate(VALUE self)
|
|
637 |
{
|
|
638 |
get_dat1(self);
|
|
639 |
return f_rational_new2(CLASS_OF(self), rb_int_uminus(dat->num), dat->den);
|
|
640 |
}
|
|
641 |
|
648 |
642 |
#ifndef NDEBUG
|
649 |
643 |
#define f_imul f_imul_orig
|
650 |
644 |
#endif
|
... | ... | |
699 |
693 |
VALUE c;
|
700 |
694 |
|
701 |
695 |
if (k == '+')
|
702 |
|
c = f_add(a, b);
|
|
696 |
c = rb_int_plus(a, b);
|
703 |
697 |
else
|
704 |
|
c = f_sub(a, b);
|
|
698 |
c = rb_int_minus(a, b);
|
705 |
699 |
|
706 |
|
b = f_idiv(aden, g);
|
|
700 |
b = rb_int_idiv(aden, g);
|
707 |
701 |
g = f_gcd(c, g);
|
708 |
|
num = f_idiv(c, g);
|
709 |
|
a = f_idiv(bden, g);
|
710 |
|
den = f_mul(a, b);
|
|
702 |
num = rb_int_idiv(c, g);
|
|
703 |
a = rb_int_idiv(bden, g);
|
|
704 |
den = rb_int_mul(a, b);
|
711 |
705 |
}
|
712 |
706 |
else {
|
713 |
707 |
VALUE g = f_gcd(aden, bden);
|
714 |
|
VALUE a = f_mul(anum, f_idiv(bden, g));
|
715 |
|
VALUE b = f_mul(bnum, f_idiv(aden, g));
|
|
708 |
VALUE a = rb_int_mul(anum, rb_int_idiv(bden, g));
|
|
709 |
VALUE b = rb_int_mul(bnum, rb_int_idiv(aden, g));
|
716 |
710 |
VALUE c;
|
717 |
711 |
|
718 |
712 |
if (k == '+')
|
719 |
|
c = f_add(a, b);
|
|
713 |
c = rb_int_plus(a, b);
|
720 |
714 |
else
|
721 |
|
c = f_sub(a, b);
|
|
715 |
c = rb_int_minus(a, b);
|
722 |
716 |
|
723 |
|
b = f_idiv(aden, g);
|
|
717 |
b = rb_int_idiv(aden, g);
|
724 |
718 |
g = f_gcd(c, g);
|
725 |
|
num = f_idiv(c, g);
|
726 |
|
a = f_idiv(bden, g);
|
727 |
|
den = f_mul(a, b);
|
|
719 |
num = rb_int_idiv(c, g);
|
|
720 |
a = rb_int_idiv(bden, g);
|
|
721 |
den = rb_int_mul(a, b);
|
728 |
722 |
}
|
729 |
723 |
return f_rational_new_no_reduce2(CLASS_OF(self), num, den);
|
730 |
724 |
}
|
731 |
725 |
|
|
726 |
static VALUE nurat_to_f(VALUE self);
|
732 |
727 |
/*
|
733 |
728 |
* call-seq:
|
734 |
729 |
* rat + numeric -> numeric
|
... | ... | |
748 |
743 |
{
|
749 |
744 |
get_dat1(self);
|
750 |
745 |
|
751 |
|
return f_addsub(self,
|
752 |
|
dat->num, dat->den,
|
753 |
|
other, ONE, '+');
|
|
746 |
return f_rational_new_no_reduce2(CLASS_OF(self),
|
|
747 |
rb_int_plus(dat->num, rb_int_mul(other, dat->den)),
|
|
748 |
dat->den);
|
754 |
749 |
}
|
755 |
750 |
}
|
756 |
751 |
else if (RB_TYPE_P(other, T_FLOAT)) {
|
757 |
|
return f_add(f_to_f(self), other);
|
|
752 |
return DBL2NUM(RFLOAT_VALUE(nurat_to_f(self)) + RFLOAT_VALUE(other));
|
758 |
753 |
}
|
759 |
754 |
else if (RB_TYPE_P(other, T_RATIONAL)) {
|
760 |
755 |
{
|
... | ... | |
789 |
784 |
{
|
790 |
785 |
get_dat1(self);
|
791 |
786 |
|
792 |
|
return f_addsub(self,
|
793 |
|
dat->num, dat->den,
|
794 |
|
other, ONE, '-');
|
|
787 |
return f_rational_new_no_reduce2(CLASS_OF(self),
|
|
788 |
rb_int_minus(dat->num, rb_int_mul(other, dat->den)),
|
|
789 |
dat->den);
|
795 |
790 |
}
|
796 |
791 |
}
|
797 |
792 |
else if (RB_TYPE_P(other, T_FLOAT)) {
|
798 |
|
return f_sub(f_to_f(self), other);
|
|
793 |
return DBL2NUM(RFLOAT_VALUE(nurat_to_f(self)) - RFLOAT_VALUE(other));
|
799 |
794 |
}
|
800 |
795 |
else if (RB_TYPE_P(other, T_RATIONAL)) {
|
801 |
796 |
{
|
... | ... | |
819 |
814 |
if (k == '/') {
|
820 |
815 |
VALUE t;
|
821 |
816 |
|
822 |
|
if (f_negative_p(bnum)) {
|
823 |
|
anum = f_negate(anum);
|
824 |
|
bnum = f_negate(bnum);
|
|
817 |
if (INT_NEGATIVE_P(bnum)) {
|
|
818 |
anum = rb_int_uminus(anum);
|
|
819 |
bnum = rb_int_uminus(bnum);
|
825 |
820 |
}
|
826 |
821 |
t = bnum;
|
827 |
822 |
bnum = bden;
|
... | ... | |
844 |
839 |
VALUE g1 = f_gcd(anum, bden);
|
845 |
840 |
VALUE g2 = f_gcd(aden, bnum);
|
846 |
841 |
|
847 |
|
num = f_mul(f_idiv(anum, g1), f_idiv(bnum, g2));
|
848 |
|
den = f_mul(f_idiv(aden, g2), f_idiv(bden, g1));
|
|
842 |
num = rb_int_mul(rb_int_idiv(anum, g1), rb_int_idiv(bnum, g2));
|
|
843 |
den = rb_int_mul(rb_int_idiv(aden, g2), rb_int_idiv(bden, g1));
|
849 |
844 |
}
|
850 |
845 |
return f_rational_new_no_reduce2(CLASS_OF(self), num, den);
|
851 |
846 |
}
|
... | ... | |
875 |
870 |
}
|
876 |
871 |
}
|
877 |
872 |
else if (RB_TYPE_P(other, T_FLOAT)) {
|
878 |
|
return f_mul(f_to_f(self), other);
|
|
873 |
return DBL2NUM(RFLOAT_VALUE(nurat_to_f(self)) * RFLOAT_VALUE(other));
|
879 |
874 |
}
|
880 |
875 |
else if (RB_TYPE_P(other, T_RATIONAL)) {
|
881 |
876 |
{
|
... | ... | |
909 |
904 |
{
|
910 |
905 |
if (RB_TYPE_P(other, T_FIXNUM) || RB_TYPE_P(other, T_BIGNUM)) {
|
911 |
906 |
if (f_zero_p(other))
|
912 |
|
rb_raise_zerodiv();
|
|
907 |
rb_num_zerodiv();
|
913 |
908 |
{
|
914 |
909 |
get_dat1(self);
|
915 |
910 |
|
... | ... | |
919 |
914 |
}
|
920 |
915 |
}
|
921 |
916 |
else if (RB_TYPE_P(other, T_FLOAT))
|
922 |
|
return rb_funcall(f_to_f(self), '/', 1, other);
|
|
917 |
return DBL2NUM(RFLOAT_VALUE(nurat_to_f(self)) / RFLOAT_VALUE(other));
|
923 |
918 |
else if (RB_TYPE_P(other, T_RATIONAL)) {
|
924 |
919 |
if (f_zero_p(other))
|
925 |
|
rb_raise_zerodiv();
|
|
920 |
rb_num_zerodiv();
|
926 |
921 |
{
|
927 |
922 |
get_dat2(self, other);
|
928 |
923 |
|
... | ... | |
953 |
948 |
static VALUE
|
954 |
949 |
nurat_fdiv(VALUE self, VALUE other)
|
955 |
950 |
{
|
|
951 |
VALUE div;
|
956 |
952 |
if (f_zero_p(other))
|
957 |
|
return f_div(self, f_to_f(other));
|
958 |
|
return f_to_f(f_div(self, other));
|
|
953 |
return DBL2NUM(RFLOAT_VALUE(nurat_to_f(self)) / 0.0);
|
|
954 |
if (FIXNUM_P(other) && FIX2LONG(other) == 1)
|
|
955 |
return nurat_to_f(self);
|
|
956 |
div = nurat_div(self, other);
|
|
957 |
if (RB_TYPE_P(div, T_RATIONAL))
|
|
958 |
return nurat_to_f(div);
|
|
959 |
if (RB_TYPE_P(div, T_FLOAT))
|
|
960 |
return div;
|
|
961 |
return rb_funcall(div, rb_intern("to_f"), 0);
|
959 |
962 |
}
|
960 |
963 |
|
961 |
964 |
inline static VALUE
|
... | ... | |
1004 |
1007 |
return f_rational_new_bang1(CLASS_OF(self), INT2FIX(f_odd_p(other) ? -1 : 1));
|
1005 |
1008 |
}
|
1006 |
1009 |
else if (f_zero_p(dat->num)) {
|
1007 |
|
if (FIX2INT(f_cmp(other, ZERO)) == -1) {
|
1008 |
|
rb_raise_zerodiv();
|
|
1010 |
if (FIX2INT(rb_int_cmp(ZERO, other)) == 1) {
|
|
1011 |
rb_num_zerodiv();
|
1009 |
1012 |
}
|
1010 |
1013 |
else {
|
1011 |
1014 |
return f_rational_new_bang1(CLASS_OF(self), ZERO);
|
... | ... | |
1021 |
1024 |
|
1022 |
1025 |
get_dat1(self);
|
1023 |
1026 |
|
1024 |
|
switch (FIX2INT(f_cmp(other, ZERO))) {
|
|
1027 |
switch (FIX2INT(rb_int_cmp(other, ZERO))) {
|
1025 |
1028 |
case 1:
|
1026 |
|
num = f_expt(dat->num, other);
|
1027 |
|
den = f_expt(dat->den, other);
|
|
1029 |
num = rb_int_pow(dat->num, other);
|
|
1030 |
den = rb_int_pow(dat->den, other);
|
1028 |
1031 |
break;
|
1029 |
1032 |
case -1:
|
1030 |
|
num = f_expt(dat->den, f_negate(other));
|
1031 |
|
den = f_expt(dat->num, f_negate(other));
|
|
1033 |
num = rb_int_pow(dat->den, rb_int_uminus(other));
|
|
1034 |
den = rb_int_pow(dat->num, rb_int_uminus(other));
|
1032 |
1035 |
break;
|
1033 |
1036 |
default:
|
1034 |
1037 |
num = ONE;
|
... | ... | |
1040 |
1043 |
}
|
1041 |
1044 |
else if (RB_TYPE_P(other, T_BIGNUM)) {
|
1042 |
1045 |
rb_warn("in a**b, b may be too big");
|
1043 |
|
return f_expt(f_to_f(self), other);
|
|
1046 |
return rb_float_pow(nurat_to_f(self), other);
|
1044 |
1047 |
}
|
1045 |
1048 |
else if (RB_TYPE_P(other, T_FLOAT) || RB_TYPE_P(other, T_RATIONAL)) {
|
1046 |
|
return f_expt(f_to_f(self), other);
|
|
1049 |
return rb_float_pow(nurat_to_f(self), other);
|
1047 |
1050 |
}
|
1048 |
1051 |
else {
|
1049 |
|
return rb_num_coerce_bin(self, other, id_expt);
|
|
1052 |
return rb_num_coerce_bin(self, other, rb_intern("**"));
|
1050 |
1053 |
}
|
1051 |
1054 |
}
|
1052 |
1055 |
|
... | ... | |
1072 |
1075 |
get_dat1(self);
|
1073 |
1076 |
|
1074 |
1077 |
if (FIXNUM_P(dat->den) && FIX2LONG(dat->den) == 1)
|
1075 |
|
return f_cmp(dat->num, other); /* c14n */
|
1076 |
|
return f_cmp(self, f_rational_new_bang1(CLASS_OF(self), other));
|
|
1078 |
return rb_int_cmp(dat->num, other); /* c14n */
|
|
1079 |
other = f_rational_new_bang1(CLASS_OF(self), other);
|
1077 |
1080 |
}
|
1078 |
1081 |
}
|
1079 |
|
else if (RB_TYPE_P(other, T_FLOAT)) {
|
1080 |
|
return f_cmp(f_to_f(self), other);
|
|
1082 |
if (RB_TYPE_P(other, T_FLOAT)) {
|
|
1083 |
return rb_dbl_cmp(RFLOAT_VALUE(nurat_to_f(self)), RFLOAT_VALUE(other));
|
1081 |
1084 |
}
|
1082 |
1085 |
else if (RB_TYPE_P(other, T_RATIONAL)) {
|
1083 |
1086 |
{
|
... | ... | |
1091 |
1094 |
num2 = f_imul(FIX2LONG(bdat->num), FIX2LONG(adat->den));
|
1092 |
1095 |
}
|
1093 |
1096 |
else {
|
1094 |
|
num1 = f_mul(adat->num, bdat->den);
|
1095 |
|
num2 = f_mul(bdat->num, adat->den);
|
|
1097 |
num1 = rb_int_mul(adat->num, bdat->den);
|
|
1098 |
num2 = rb_int_mul(bdat->num, adat->den);
|
1096 |
1099 |
}
|
1097 |
|
return f_cmp(f_sub(num1, num2), ZERO);
|
|
1100 |
return rb_int_cmp(rb_int_minus(num1, num2), ZERO);
|
1098 |
1101 |
}
|
1099 |
1102 |
}
|
1100 |
1103 |
else {
|
1101 |
|
return rb_num_coerce_cmp(self, other, id_cmp);
|
|
1104 |
return rb_num_coerce_cmp(self, other, rb_intern("<=>"));
|
1102 |
1105 |
}
|
1103 |
1106 |
}
|
1104 |
1107 |
|
... | ... | |
1121 |
1124 |
{
|
1122 |
1125 |
get_dat1(self);
|
1123 |
1126 |
|
1124 |
|
if (f_zero_p(dat->num) && f_zero_p(other))
|
|
1127 |
if (INT_ZERO_P(dat->num) && INT_ZERO_P(other))
|
1125 |
1128 |
return Qtrue;
|
1126 |
1129 |
|
1127 |
1130 |
if (!FIXNUM_P(dat->den))
|
1128 |
1131 |
return Qfalse;
|
1129 |
1132 |
if (FIX2LONG(dat->den) != 1)
|
1130 |
1133 |
return Qfalse;
|
1131 |
|
if (f_eqeq_p(dat->num, other))
|
1132 |
|
return Qtrue;
|
1133 |
|
return Qfalse;
|
|
1134 |
return rb_int_equal(dat->num, other);
|
1134 |
1135 |
}
|
1135 |
1136 |
}
|
1136 |
1137 |
else if (RB_TYPE_P(other, T_FLOAT)) {
|
1137 |
|
return f_eqeq_p(f_to_f(self), other);
|
|
1138 |
return f_boolcast(rb_dbl_cmp(RFLOAT_VALUE(nurat_to_f(self)), RFLOAT_VALUE(other))
|
|
1139 |
== INT2FIX(0));
|
1138 |
1140 |
}
|
1139 |
1141 |
else if (RB_TYPE_P(other, T_RATIONAL)) {
|
1140 |
1142 |
{
|
1141 |
1143 |
get_dat2(self, other);
|
1142 |
1144 |
|
1143 |
|
if (f_zero_p(adat->num) && f_zero_p(bdat->num))
|
|
1145 |
if (INT_ZERO_P(adat->num) && INT_ZERO_P(bdat->num))
|
1144 |
1146 |
return Qtrue;
|
1145 |
1147 |
|
1146 |
|
return f_boolcast(f_eqeq_p(adat->num, bdat->num) &&
|
1147 |
|
f_eqeq_p(adat->den, bdat->den));
|
|
1148 |
return f_boolcast(rb_int_equal(adat->num, bdat->num) &&
|
|
1149 |
rb_int_equal(adat->den, bdat->den));
|
1148 |
1150 |
}
|
1149 |
1151 |
}
|
1150 |
1152 |
else {
|
... | ... | |
1160 |
1162 |
return rb_assoc_new(f_rational_new_bang1(CLASS_OF(self), other), self);
|
1161 |
1163 |
}
|
1162 |
1164 |
else if (RB_TYPE_P(other, T_FLOAT)) {
|
1163 |
|
return rb_assoc_new(other, f_to_f(self));
|
|
1165 |
return rb_assoc_new(other, nurat_to_f(self));
|
1164 |
1166 |
}
|
1165 |
1167 |
else if (RB_TYPE_P(other, T_RATIONAL)) {
|
1166 |
1168 |
return rb_assoc_new(other, self);
|
... | ... | |
1211 |
1213 |
}
|
1212 |
1214 |
#endif
|
1213 |
1215 |
|
|
1216 |
/*
|
|
1217 |
* call-seq:
|
|
1218 |
* rat.positive? -> true or false
|
|
1219 |
*
|
|
1220 |
* Returns +true+ if +rat+ is greater than 0.
|
|
1221 |
*/
|
|
1222 |
static VALUE
|
|
1223 |
nurat_positive_p(VALUE self)
|
|
1224 |
{
|
|
1225 |
get_dat1(self);
|
|
1226 |
return f_boolcast(INT_POSITIVE_P(dat->num));
|
|
1227 |
}
|
|
1228 |
|
|
1229 |
/*
|
|
1230 |
* call-seq:
|
|
1231 |
* rat.negative? -> true or false
|
|
1232 |
*
|
|
1233 |
* Returns +true+ if +rat+ is less than 0.
|
|
1234 |
*/
|
|
1235 |
static VALUE
|
|
1236 |
nurat_negative_p(VALUE self)
|
|
1237 |
{
|
|
1238 |
get_dat1(self);
|
|
1239 |
return f_boolcast(INT_NEGATIVE_P(dat->num));
|
|
1240 |
}
|
|
1241 |
|
1214 |
1242 |
static VALUE
|
1215 |
1243 |
nurat_floor(VALUE self)
|
1216 |
1244 |
{
|
1217 |
1245 |
get_dat1(self);
|
1218 |
|
return f_idiv(dat->num, dat->den);
|
|
1246 |
return rb_int_idiv(dat->num, dat->den);
|
1219 |
1247 |
}
|
1220 |
1248 |
|
1221 |
1249 |
static VALUE
|
1222 |
1250 |
nurat_ceil(VALUE self)
|
1223 |
1251 |
{
|
1224 |
1252 |
get_dat1(self);
|
1225 |
|
return f_negate(f_idiv(f_negate(dat->num), dat->den));
|
|
1253 |
return rb_int_uminus(rb_int_idiv(rb_int_uminus(dat->num), dat->den));
|
1226 |
1254 |
}
|
1227 |
1255 |
|
1228 |
1256 |
/*
|
... | ... | |
1244 |
1272 |
nurat_truncate(VALUE self)
|
1245 |
1273 |
{
|
1246 |
1274 |
get_dat1(self);
|
1247 |
|
if (f_negative_p(dat->num))
|
1248 |
|
return f_negate(f_idiv(f_negate(dat->num), dat->den));
|
1249 |
|
return f_idiv(dat->num, dat->den);
|
|
1275 |
if (INT_NEGATIVE_P(dat->num))
|
|
1276 |
return rb_int_uminus(rb_int_idiv(rb_int_uminus(dat->num), dat->den));
|
|
1277 |
return rb_int_idiv(dat->num, dat->den);
|
1250 |
1278 |
}
|
1251 |
1279 |
|
1252 |
1280 |
static VALUE
|
... | ... | |
1258 |
1286 |
|
1259 |
1287 |
num = dat->num;
|
1260 |
1288 |
den = dat->den;
|
1261 |
|
neg = f_negative_p(num);
|
|
1289 |
neg = INT_NEGATIVE_P(num);
|
1262 |
1290 |
|
1263 |
1291 |
if (neg)
|
1264 |
|
num = f_negate(num);
|
|
1292 |
num = rb_int_uminus(num);
|
1265 |
1293 |
|
1266 |
|
num = f_add(f_mul(num, TWO), den);
|
1267 |
|
den = f_mul(den, TWO);
|
1268 |
|
num = f_idiv(num, den);
|
|
1294 |
num = rb_int_plus(rb_int_mul(num, TWO), den);
|
|
1295 |
den = rb_int_mul(den, TWO);
|
|
1296 |
num = rb_int_idiv(num, den);
|
1269 |
1297 |
|
1270 |
1298 |
if (neg)
|
1271 |
|
num = f_negate(num);
|
|
1299 |
num = rb_int_uminus(num);
|
1272 |
1300 |
|
1273 |
1301 |
return num;
|
1274 |
1302 |
}
|
... | ... | |
1287 |
1315 |
rb_raise(rb_eTypeError, "not an integer");
|
1288 |
1316 |
|
1289 |
1317 |
b = f_expt10(n);
|
1290 |
|
s = f_mul(self, b);
|
|
1318 |
s = nurat_mul(self, b);
|
1291 |
1319 |
|
1292 |
1320 |
if (k_float_p(s)) {
|
1293 |
|
if (f_lt_p(n, ZERO))
|
|
1321 |
if (INT_NEGATIVE_P(n))
|
1294 |
1322 |
return ZERO;
|
1295 |
1323 |
return self;
|
1296 |
1324 |
}
|
... | ... | |
1301 |
1329 |
|
1302 |
1330 |
s = (*func)(s);
|
1303 |
1331 |
|
1304 |
|
s = f_div(f_rational_new_bang1(CLASS_OF(self), s), b);
|
|
1332 |
s = nurat_div(f_rational_new_bang1(CLASS_OF(self), s), b);
|
1305 |
1333 |
|
1306 |
|
if (f_lt_p(n, ONE))
|
1307 |
|
s = f_to_i(s);
|
|
1334 |
if (RB_TYPE_P(s, T_RATIONAL) && FIX2INT(rb_int_cmp(n, ONE)) < 0)
|
|
1335 |
s = nurat_truncate(s);
|
1308 |
1336 |
|
1309 |
1337 |
return s;
|
1310 |
1338 |
}
|
... | ... | |
1421 |
1449 |
nurat_to_f(VALUE self)
|
1422 |
1450 |
{
|
1423 |
1451 |
get_dat1(self);
|
1424 |
|
return f_fdiv(dat->num, dat->den);
|
|
1452 |
return rb_int_fdiv(dat->num, dat->den);
|
1425 |
1453 |
}
|
1426 |
1454 |
|
1427 |
1455 |
/*
|
... | ... | |
1557 |
1585 |
if (argc == 0)
|
1558 |
1586 |
return self;
|
1559 |
1587 |
|
1560 |
|
if (f_negative_p(self))
|
1561 |
|
return f_negate(nurat_rationalize(argc, argv, f_abs(self)));
|
|
1588 |
if (nurat_negative_p(self))
|
|
1589 |
return nurat_negate(nurat_rationalize(argc, argv, nurat_negate(self)));
|
1562 |
1590 |
|
1563 |
1591 |
rb_scan_args(argc, argv, "01", &e);
|
1564 |
1592 |
e = f_abs(e);
|
... | ... | |
1681 |
1709 |
if (RARRAY_LEN(a) != 2)
|
1682 |
1710 |
rb_raise(rb_eArgError, "marshaled rational must have an array whose length is 2 but %ld", RARRAY_LEN(a));
|
1683 |
1711 |
if (f_zero_p(RARRAY_AREF(a, 1)))
|
1684 |
|
rb_raise_zerodiv();
|
|
1712 |
rb_num_zerodiv();
|
1685 |
1713 |
|
1686 |
1714 |
rb_ivar_set(self, id_i_num, RARRAY_AREF(a, 0));
|
1687 |
1715 |
rb_ivar_set(self, id_i_den, RARRAY_AREF(a, 1));
|
... | ... | |
1763 |
1791 |
return nurat_s_canonicalize_internal(rb_cRational, x, y);
|
1764 |
1792 |
}
|
1765 |
1793 |
|
1766 |
|
static VALUE nurat_s_convert(int argc, VALUE *argv, VALUE klass);
|
1767 |
|
|
1768 |
1794 |
VALUE
|
1769 |
1795 |
rb_Rational(VALUE x, VALUE y)
|
1770 |
1796 |
{
|
... | ... | |
1832 |
1858 |
numeric_quo(VALUE x, VALUE y)
|
1833 |
1859 |
{
|
1834 |
1860 |
if (RB_TYPE_P(y, T_FLOAT)) {
|
1835 |
|
return f_fdiv(x, y);
|
|
1861 |
return rb_funcall(x, rb_intern("fdiv"), 1, y);
|
1836 |
1862 |
}
|
1837 |
1863 |
|
1838 |
1864 |
#ifdef CANON
|
... | ... | |
1844 |
1870 |
{
|
1845 |
1871 |
x = rb_convert_type(x, T_RATIONAL, "Rational", "to_r");
|
1846 |
1872 |
}
|
1847 |
|
return rb_funcall(x, '/', 1, y);
|
|
1873 |
return nurat_div(x, y);
|
1848 |
1874 |
}
|
1849 |
1875 |
|
1850 |
1876 |
|
... | ... | |
1872 |
1898 |
return INT2FIX(1);
|
1873 |
1899 |
}
|
1874 |
1900 |
|
|
1901 |
static VALUE float_to_r(VALUE self);
|
1875 |
1902 |
/*
|
1876 |
1903 |
* call-seq:
|
1877 |
1904 |
* flo.numerator -> integer
|
... | ... | |
1888 |
1915 |
double d = RFLOAT_VALUE(self);
|
1889 |
1916 |
if (isinf(d) || isnan(d))
|
1890 |
1917 |
return self;
|
1891 |
|
return rb_call_super(0, 0);
|
|
1918 |
return nurat_numerator(float_to_r(self));
|
1892 |
1919 |
}
|
1893 |
1920 |
|
1894 |
1921 |
/*
|
... | ... | |
1906 |
1933 |
double d = RFLOAT_VALUE(self);
|
1907 |
1934 |
if (isinf(d) || isnan(d))
|
1908 |
1935 |
return INT2FIX(1);
|
1909 |
|
return rb_call_super(0, 0);
|
|
1936 |
return nurat_denominator(float_to_r(self));
|
1910 |
1937 |
}
|
1911 |
1938 |
|
1912 |
1939 |
/*
|
... | ... | |
1988 |
2015 |
}
|
1989 |
2016 |
#endif
|
1990 |
2017 |
|
1991 |
|
#define id_lshift rb_intern("<<")
|
1992 |
|
#define f_lshift(x,n) rb_funcall((x), id_lshift, 1, (n))
|
1993 |
|
|
1994 |
2018 |
/*
|
1995 |
2019 |
* call-seq:
|
1996 |
2020 |
* flt.to_r -> rational
|
... | ... | |
2018 |
2042 |
long ln = FIX2LONG(n);
|
2019 |
2043 |
|
2020 |
2044 |
if (ln == 0)
|
2021 |
|
return f_to_r(f);
|
|
2045 |
return rb_rational_new1(f);
|
2022 |
2046 |
if (ln > 0)
|
2023 |
|
return f_to_r(f_lshift(f, n));
|
|
2047 |
return rb_rational_new1(rb_int_lshift(f, n));
|
2024 |
2048 |
ln = -ln;
|
2025 |
|
return rb_rational_new2(f, f_lshift(ONE, INT2FIX(ln)));
|
|
2049 |
return rb_rational_new2(f, rb_int_lshift(ONE, INT2FIX(ln)));
|
2026 |
2050 |
}
|
2027 |
2051 |
#else
|
2028 |
|
return f_to_r(f_mul(f, f_expt(INT2FIX(FLT_RADIX), n)));
|
|
2052 |
f = rb_int_mul(f, rb_int_pow(INT2FIX(FLT_RADIX), n));
|
|
2053 |
if (RB_TYPE_P(f, T_RATIONAL))
|
|
2054 |
return f;
|
|
2055 |
return rb_rational_new1(f);
|
2029 |
2056 |
#endif
|
2030 |
2057 |
}
|
2031 |
2058 |
|
... | ... | |
2039 |
2066 |
b = f_add(flt, e);
|
2040 |
2067 |
|
2041 |
2068 |
if (f_eqeq_p(a, b))
|
2042 |
|
return f_to_r(flt);
|
|
2069 |
return float_to_r(flt);
|
2043 |
2070 |
|
2044 |
2071 |
nurat_rationalize_internal(a, b, &p, &q);
|
2045 |
2072 |
return rb_rational_new2(p, q);
|
... | ... | |
2051 |
2078 |
VALUE a, b, f, n, p, q;
|
2052 |
2079 |
|
2053 |
2080 |
float_decode_internal(flt, &f, &n);
|
2054 |
|
if (f_zero_p(f) || f_positive_p(n))
|
2055 |
|
return rb_rational_new1(f_lshift(f, n));
|
|
2081 |
if (INT_ZERO_P(f) || FIX2INT(n) >= 0)
|
|
2082 |
return rb_rational_new1(rb_int_lshift(f, n));
|
2056 |
2083 |
|
2057 |
2084 |
#if FLT_RADIX == 2
|
2058 |
2085 |
{
|
2059 |
2086 |
VALUE two_times_f, den;
|
2060 |
2087 |
|
2061 |
|
two_times_f = f_mul(TWO, f);
|
2062 |
|
den = f_lshift(ONE, f_sub(ONE, n));
|
|
2088 |
two_times_f = rb_int_mul(TWO, f);
|
|
2089 |
den = rb_int_lshift(ONE, rb_int_minus(ONE, n));
|
2063 |
2090 |
|
2064 |
|
a = rb_rational_new2(f_sub(two_times_f, ONE), den);
|
2065 |
|
b = rb_rational_new2(f_add(two_times_f, ONE), den);
|
|
2091 |
a = rb_rational_new2(rb_int_minus(two_times_f, ONE), den);
|
|
2092 |
b = rb_rational_new2(rb_int_plus(two_times_f, ONE), den);
|
2066 |
2093 |
}
|
2067 |
2094 |
#else
|
2068 |
2095 |
{
|
2069 |
2096 |
VALUE radix_times_f, den;
|
2070 |
2097 |
|
2071 |
|
radix_times_f = f_mul(INT2FIX(FLT_RADIX), f);
|
2072 |
|
den = f_expt(INT2FIX(FLT_RADIX), f_sub(ONE, n));
|
|
2098 |
radix_times_f = rb_int_mul(INT2FIX(FLT_RADIX), f);
|
|
2099 |
den = rb_int_pow(INT2FIX(FLT_RADIX), rb_int_minus(ONE, n));
|
2073 |
2100 |
|
2074 |
|
a = rb_rational_new2(f_sub(radix_times_f, INT2FIX(FLT_RADIX - 1)), den);
|
2075 |
|
b = rb_rational_new2(f_add(radix_times_f, INT2FIX(FLT_RADIX - 1)), den);
|
|
2101 |
a = rb_rational_new2(rb_int_minus(radix_times_f, INT2FIX(FLT_RADIX - 1)), den);
|
|
2102 |
b = rb_rational_new2(rb_int_plus(radix_times_f, INT2FIX(FLT_RADIX - 1)), den);
|
2076 |
2103 |
}
|
2077 |
2104 |
#endif
|
2078 |
2105 |
|
2079 |
|
if (f_eqeq_p(a, b))
|
2080 |
|
return f_to_r(flt);
|
|
2106 |
if (nurat_eqeq_p(a, b))
|
|
2107 |
return float_to_r(flt);
|
2081 |
2108 |
|
2082 |
2109 |
nurat_rationalize_internal(a, b, &p, &q);
|
2083 |
2110 |
return rb_rational_new2(p, q);
|
... | ... | |
2101 |
2128 |
float_rationalize(int argc, VALUE *argv, VALUE self)
|
2102 |
2129 |
{
|
2103 |
2130 |
VALUE e;
|
|
2131 |
double d = RFLOAT_VALUE(self);
|
2104 |
2132 |
|
2105 |
|
if (f_negative_p(self))
|
2106 |
|
return f_negate(float_rationalize(argc, argv, f_abs(self)));
|
|
2133 |
if (d < 0.0)
|
|
2134 |
return nurat_negate(float_rationalize(argc, argv, DBL2NUM(-d)));
|
2107 |
2135 |
|
2108 |
2136 |
rb_scan_args(argc, argv, "01", &e);
|
2109 |
2137 |
|
... | ... | |
2214 |
2242 |
return 0;
|
2215 |
2243 |
{
|
2216 |
2244 |
VALUE l = f_expt10(INT2NUM(count));
|
2217 |
|
*num = f_mul(*num, l);
|
2218 |
|
*num = f_add(*num, fp);
|
2219 |
|
*num = f_div(*num, l);
|
|
2245 |
#ifdef CANON
|
|
2246 |
if (canonicalization) {
|
|
2247 |
*num = rb_int_mul(*num, l);
|
|
2248 |
*num = rb_int_plus(*num, fp);
|
|
2249 |
*num = rb_rational_new2(*num, l);
|
|
2250 |
}
|
|
2251 |
else
|
|
2252 |
#endif
|
|
2253 |
{
|
|
2254 |
*num = nurat_mul(*num, l);
|
|
2255 |
*num = rb_rational_plus(*num, fp);
|
|
2256 |
*num = nurat_div(*num, l);
|
|
2257 |
}
|
2220 |
2258 |
}
|
2221 |
2259 |
}
|
2222 |
2260 |
|
... | ... | |
2228 |
2266 |
if (!read_digits(s, strict, &exp, NULL))
|
2229 |
2267 |
return 0;
|
2230 |
2268 |
if (expsign == '-')
|
2231 |
|
exp = f_negate(exp);
|
|
2269 |
exp = rb_int_uminus(exp);
|
2232 |
2270 |
}
|
2233 |
2271 |
|
2234 |
2272 |
if (numsign == '-')
|
2235 |
|
*num = f_negate(*num);
|
|
2273 |
*num = nurat_negate(*num);
|
2236 |
2274 |
if (!NIL_P(exp)) {
|
2237 |
2275 |
VALUE l = f_expt10(exp);
|
2238 |
|
*num = f_mul(*num, l);
|
|
2276 |
*num = nurat_mul(*num, l);
|
2239 |
2277 |
}
|
2240 |
2278 |
return 1;
|
2241 |
2279 |
}
|
... | ... | |
2262 |
2300 |
if (!read_den(s, strict, &den))
|
2263 |
2301 |
return 0;
|
2264 |
2302 |
if (!(FIXNUM_P(den) && FIX2LONG(den) == 1))
|
2265 |
|
*num = f_div(*num, den);
|
|
2303 |
*num = nurat_div(*num, den);
|
2266 |
2304 |
}
|
2267 |
2305 |
return 1;
|
2268 |
2306 |
}
|
... | ... | |
2418 |
2456 |
rb_match_busy(backref);
|
2419 |
2457 |
|
2420 |
2458 |
if (RB_TYPE_P(a1, T_FLOAT)) {
|
2421 |
|
a1 = f_to_r(a1);
|
|
2459 |
a1 = float_to_r(a1);
|
2422 |
2460 |
}
|
2423 |
2461 |
else if (RB_TYPE_P(a1, T_STRING)) {
|
2424 |
2462 |
a1 = string_to_r_strict(a1);
|
2425 |
2463 |
}
|
2426 |
2464 |
|
2427 |
2465 |
if (RB_TYPE_P(a2, T_FLOAT)) {
|
2428 |
|
a2 = f_to_r(a2);
|
|
2466 |
a2 = float_to_r(a2);
|
2429 |
2467 |
}
|
2430 |
2468 |
else if (RB_TYPE_P(a2, T_STRING)) {
|
2431 |
2469 |
a2 = string_to_r_strict(a2);
|
... | ... | |
2507 |
2545 |
assert(fprintf(stderr, "assert() is now active\n"));
|
2508 |
2546 |
|
2509 |
2547 |
id_abs = rb_intern("abs");
|
2510 |
|
id_cmp = rb_intern("<=>");
|
2511 |
|
id_convert = rb_intern("convert");
|
2512 |
2548 |
id_eqeq_p = rb_intern("==");
|
2513 |
|
id_expt = rb_intern("**");
|
2514 |
|
id_fdiv = rb_intern("fdiv");
|
2515 |
2549 |
id_idiv = rb_intern("div");
|
2516 |
2550 |
id_integer_p = rb_intern("integer?");
|
2517 |
2551 |
id_negate = rb_intern("-@");
|
2518 |
|
id_to_f = rb_intern("to_f");
|
2519 |
2552 |
id_to_i = rb_intern("to_i");
|
2520 |
|
id_truncate = rb_intern("truncate");
|
2521 |
2553 |
id_i_num = rb_intern("@numerator");
|
2522 |
2554 |
id_i_den = rb_intern("@denominator");
|
2523 |
2555 |
|
... | ... | |
2538 |
2570 |
rb_define_method(rb_cRational, "numerator", nurat_numerator, 0);
|
2539 |
2571 |
rb_define_method(rb_cRational, "denominator", nurat_denominator, 0);
|
2540 |
2572 |
|
|
2573 |
rb_define_method(rb_cRational, "-@", nurat_negate, 0);
|
2541 |
2574 |
rb_define_method(rb_cRational, "+", rb_rational_plus, 1);
|
2542 |
2575 |
rb_define_method(rb_cRational, "-", nurat_sub, 1);
|
2543 |
2576 |
rb_define_method(rb_cRational, "*", nurat_mul, 1);
|
... | ... | |
2559 |
2592 |
rb_define_method(rb_cRational, "rational?", nurat_true, 0);
|
2560 |
2593 |
rb_define_method(rb_cRational, "exact?", nurat_true, 0);
|
2561 |
2594 |
#endif
|
|
2595 |
rb_define_method(rb_cRational, "positive?", nurat_positive_p, 0);
|
|
2596 |
rb_define_method(rb_cRational, "negative?", nurat_negative_p, 0);
|
2562 |
2597 |
|
2563 |
2598 |
rb_define_method(rb_cRational, "floor", nurat_floor_n, -1);
|
2564 |
2599 |
rb_define_method(rb_cRational, "ceil", nurat_ceil_n, -1);
|
2565 |
|
-
|