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 
* callseq:

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 
* callseq:


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 
* callseq:

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 
* callseq:


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 
* callseq:


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 
* callseq:

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 
* callseq:

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 


