Ruby  2.0.0p481(2014-05-08revision45883)
rational.c
Go to the documentation of this file.
00001 /*
00002   rational.c: Coded by Tadayoshi Funaba 2008-2012
00003 
00004   This implementation is based on Keiju Ishitsuka's Rational library
00005   which is written in ruby.
00006 */
00007 
00008 #include "ruby.h"
00009 #include "internal.h"
00010 #include <math.h>
00011 #include <float.h>
00012 
00013 #ifdef HAVE_IEEEFP_H
00014 #include <ieeefp.h>
00015 #endif
00016 
00017 #define NDEBUG
00018 #include <assert.h>
00019 
00020 #define ZERO INT2FIX(0)
00021 #define ONE INT2FIX(1)
00022 #define TWO INT2FIX(2)
00023 
00024 VALUE rb_cRational;
00025 
00026 static ID id_abs, id_cmp, id_convert, id_eqeq_p, id_expt, id_fdiv,
00027     id_floor, id_idiv, id_inspect, id_integer_p, id_negate, id_to_f,
00028     id_to_i, id_to_s, id_truncate, id_i_num, id_i_den;
00029 
00030 #define f_boolcast(x) ((x) ? Qtrue : Qfalse)
00031 
00032 #define binop(n,op) \
00033 inline static VALUE \
00034 f_##n(VALUE x, VALUE y)\
00035 {\
00036   return rb_funcall(x, (op), 1, y);\
00037 }
00038 
00039 #define fun1(n) \
00040 inline static VALUE \
00041 f_##n(VALUE x)\
00042 {\
00043     return rb_funcall(x, id_##n, 0);\
00044 }
00045 
00046 #define fun2(n) \
00047 inline static VALUE \
00048 f_##n(VALUE x, VALUE y)\
00049 {\
00050     return rb_funcall(x, id_##n, 1, y);\
00051 }
00052 
00053 inline static VALUE
00054 f_add(VALUE x, VALUE y)
00055 {
00056     if (FIXNUM_P(y) && FIX2LONG(y) == 0)
00057         return x;
00058     else if (FIXNUM_P(x) && FIX2LONG(x) == 0)
00059         return y;
00060     return rb_funcall(x, '+', 1, y);
00061 }
00062 
00063 inline static VALUE
00064 f_cmp(VALUE x, VALUE y)
00065 {
00066     if (FIXNUM_P(x) && FIXNUM_P(y)) {
00067         long c = FIX2LONG(x) - FIX2LONG(y);
00068         if (c > 0)
00069             c = 1;
00070         else if (c < 0)
00071             c = -1;
00072         return INT2FIX(c);
00073     }
00074     return rb_funcall(x, id_cmp, 1, y);
00075 }
00076 
00077 inline static VALUE
00078 f_div(VALUE x, VALUE y)
00079 {
00080     if (FIXNUM_P(y) && FIX2LONG(y) == 1)
00081         return x;
00082     return rb_funcall(x, '/', 1, y);
00083 }
00084 
00085 inline static VALUE
00086 f_gt_p(VALUE x, VALUE y)
00087 {
00088     if (FIXNUM_P(x) && FIXNUM_P(y))
00089         return f_boolcast(FIX2LONG(x) > FIX2LONG(y));
00090     return rb_funcall(x, '>', 1, y);
00091 }
00092 
00093 inline static VALUE
00094 f_lt_p(VALUE x, VALUE y)
00095 {
00096     if (FIXNUM_P(x) && FIXNUM_P(y))
00097         return f_boolcast(FIX2LONG(x) < FIX2LONG(y));
00098     return rb_funcall(x, '<', 1, y);
00099 }
00100 
00101 binop(mod, '%')
00102 
00103 inline static VALUE
00104 f_mul(VALUE x, VALUE y)
00105 {
00106     if (FIXNUM_P(y)) {
00107         long iy = FIX2LONG(y);
00108         if (iy == 0) {
00109             if (FIXNUM_P(x) || RB_TYPE_P(x, T_BIGNUM))
00110                 return ZERO;
00111         }
00112         else if (iy == 1)
00113             return x;
00114     }
00115     else if (FIXNUM_P(x)) {
00116         long ix = FIX2LONG(x);
00117         if (ix == 0) {
00118             if (FIXNUM_P(y) || RB_TYPE_P(y, T_BIGNUM))
00119                 return ZERO;
00120         }
00121         else if (ix == 1)
00122             return y;
00123     }
00124     return rb_funcall(x, '*', 1, y);
00125 }
00126 
00127 inline static VALUE
00128 f_sub(VALUE x, VALUE y)
00129 {
00130     if (FIXNUM_P(y) && FIX2LONG(y) == 0)
00131         return x;
00132     return rb_funcall(x, '-', 1, y);
00133 }
00134 
00135 fun1(abs)
00136 fun1(floor)
00137 fun1(inspect)
00138 fun1(integer_p)
00139 fun1(negate)
00140 
00141 inline static VALUE
00142 f_to_i(VALUE x)
00143 {
00144     if (RB_TYPE_P(x, T_STRING))
00145         return rb_str_to_inum(x, 10, 0);
00146     return rb_funcall(x, id_to_i, 0);
00147 }
00148 inline static VALUE
00149 f_to_f(VALUE x)
00150 {
00151     if (RB_TYPE_P(x, T_STRING))
00152         return DBL2NUM(rb_str_to_dbl(x, 0));
00153     return rb_funcall(x, id_to_f, 0);
00154 }
00155 
00156 fun1(to_s)
00157 fun1(truncate)
00158 
00159 inline static VALUE
00160 f_eqeq_p(VALUE x, VALUE y)
00161 {
00162     if (FIXNUM_P(x) && FIXNUM_P(y))
00163         return f_boolcast(FIX2LONG(x) == FIX2LONG(y));
00164     return rb_funcall(x, id_eqeq_p, 1, y);
00165 }
00166 
00167 fun2(expt)
00168 fun2(fdiv)
00169 fun2(idiv)
00170 
00171 #define f_expt10(x) f_expt(INT2FIX(10), x)
00172 
00173 inline static VALUE
00174 f_negative_p(VALUE x)
00175 {
00176     if (FIXNUM_P(x))
00177         return f_boolcast(FIX2LONG(x) < 0);
00178     return rb_funcall(x, '<', 1, ZERO);
00179 }
00180 
00181 #define f_positive_p(x) (!f_negative_p(x))
00182 
00183 inline static VALUE
00184 f_zero_p(VALUE x)
00185 {
00186     switch (TYPE(x)) {
00187       case T_FIXNUM:
00188         return f_boolcast(FIX2LONG(x) == 0);
00189       case T_BIGNUM:
00190         return Qfalse;
00191       case T_RATIONAL:
00192       {
00193           VALUE num = RRATIONAL(x)->num;
00194 
00195           return f_boolcast(FIXNUM_P(num) && FIX2LONG(num) == 0);
00196       }
00197     }
00198     return rb_funcall(x, id_eqeq_p, 1, ZERO);
00199 }
00200 
00201 #define f_nonzero_p(x) (!f_zero_p(x))
00202 
00203 inline static VALUE
00204 f_one_p(VALUE x)
00205 {
00206     switch (TYPE(x)) {
00207       case T_FIXNUM:
00208         return f_boolcast(FIX2LONG(x) == 1);
00209       case T_BIGNUM:
00210         return Qfalse;
00211       case T_RATIONAL:
00212       {
00213           VALUE num = RRATIONAL(x)->num;
00214           VALUE den = RRATIONAL(x)->den;
00215 
00216           return f_boolcast(FIXNUM_P(num) && FIX2LONG(num) == 1 &&
00217                             FIXNUM_P(den) && FIX2LONG(den) == 1);
00218       }
00219     }
00220     return rb_funcall(x, id_eqeq_p, 1, ONE);
00221 }
00222 
00223 inline static VALUE
00224 f_minus_one_p(VALUE x)
00225 {
00226     switch (TYPE(x)) {
00227       case T_FIXNUM:
00228         return f_boolcast(FIX2LONG(x) == -1);
00229       case T_BIGNUM:
00230         return Qfalse;
00231       case T_RATIONAL:
00232       {
00233           VALUE num = RRATIONAL(x)->num;
00234           VALUE den = RRATIONAL(x)->den;
00235 
00236           return f_boolcast(FIXNUM_P(num) && FIX2LONG(num) == -1 &&
00237                             FIXNUM_P(den) && FIX2LONG(den) == 1);
00238       }
00239     }
00240     return rb_funcall(x, id_eqeq_p, 1, INT2FIX(-1));
00241 }
00242 
00243 inline static VALUE
00244 f_kind_of_p(VALUE x, VALUE c)
00245 {
00246     return rb_obj_is_kind_of(x, c);
00247 }
00248 
00249 inline static VALUE
00250 k_numeric_p(VALUE x)
00251 {
00252     return f_kind_of_p(x, rb_cNumeric);
00253 }
00254 
00255 inline static VALUE
00256 k_integer_p(VALUE x)
00257 {
00258     return f_kind_of_p(x, rb_cInteger);
00259 }
00260 
00261 inline static VALUE
00262 k_float_p(VALUE x)
00263 {
00264     return f_kind_of_p(x, rb_cFloat);
00265 }
00266 
00267 inline static VALUE
00268 k_rational_p(VALUE x)
00269 {
00270     return f_kind_of_p(x, rb_cRational);
00271 }
00272 
00273 #define k_exact_p(x) (!k_float_p(x))
00274 #define k_inexact_p(x) k_float_p(x)
00275 
00276 #define k_exact_zero_p(x) (k_exact_p(x) && f_zero_p(x))
00277 #define k_exact_one_p(x) (k_exact_p(x) && f_one_p(x))
00278 
00279 #ifndef NDEBUG
00280 #define f_gcd f_gcd_orig
00281 #endif
00282 
00283 inline static long
00284 i_gcd(long x, long y)
00285 {
00286     if (x < 0)
00287         x = -x;
00288     if (y < 0)
00289         y = -y;
00290 
00291     if (x == 0)
00292         return y;
00293     if (y == 0)
00294         return x;
00295 
00296     while (x > 0) {
00297         long t = x;
00298         x = y % x;
00299         y = t;
00300     }
00301     return y;
00302 }
00303 
00304 inline static VALUE
00305 f_gcd(VALUE x, VALUE y)
00306 {
00307     VALUE z;
00308 
00309     if (FIXNUM_P(x) && FIXNUM_P(y))
00310         return LONG2NUM(i_gcd(FIX2LONG(x), FIX2LONG(y)));
00311 
00312     if (f_negative_p(x))
00313         x = f_negate(x);
00314     if (f_negative_p(y))
00315         y = f_negate(y);
00316 
00317     if (f_zero_p(x))
00318         return y;
00319     if (f_zero_p(y))
00320         return x;
00321 
00322     for (;;) {
00323         if (FIXNUM_P(x)) {
00324             if (FIX2LONG(x) == 0)
00325                 return y;
00326             if (FIXNUM_P(y))
00327                 return LONG2NUM(i_gcd(FIX2LONG(x), FIX2LONG(y)));
00328         }
00329         z = x;
00330         x = f_mod(y, x);
00331         y = z;
00332     }
00333     /* NOTREACHED */
00334 }
00335 
00336 #ifndef NDEBUG
00337 #undef f_gcd
00338 
00339 inline static VALUE
00340 f_gcd(VALUE x, VALUE y)
00341 {
00342     VALUE r = f_gcd_orig(x, y);
00343     if (f_nonzero_p(r)) {
00344         assert(f_zero_p(f_mod(x, r)));
00345         assert(f_zero_p(f_mod(y, r)));
00346     }
00347     return r;
00348 }
00349 #endif
00350 
00351 inline static VALUE
00352 f_lcm(VALUE x, VALUE y)
00353 {
00354     if (f_zero_p(x) || f_zero_p(y))
00355         return ZERO;
00356     return f_abs(f_mul(f_div(x, f_gcd(x, y)), y));
00357 }
00358 
00359 #define get_dat1(x) \
00360     struct RRational *dat;\
00361     dat = ((struct RRational *)(x))
00362 
00363 #define get_dat2(x,y) \
00364     struct RRational *adat, *bdat;\
00365     adat = ((struct RRational *)(x));\
00366     bdat = ((struct RRational *)(y))
00367 
00368 inline static VALUE
00369 nurat_s_new_internal(VALUE klass, VALUE num, VALUE den)
00370 {
00371     NEWOBJ_OF(obj, struct RRational, klass, T_RATIONAL);
00372 
00373     obj->num = num;
00374     obj->den = den;
00375 
00376     return (VALUE)obj;
00377 }
00378 
00379 static VALUE
00380 nurat_s_alloc(VALUE klass)
00381 {
00382     return nurat_s_new_internal(klass, ZERO, ONE);
00383 }
00384 
00385 #define rb_raise_zerodiv() rb_raise(rb_eZeroDivError, "divided by 0")
00386 
00387 #if 0
00388 static VALUE
00389 nurat_s_new_bang(int argc, VALUE *argv, VALUE klass)
00390 {
00391     VALUE num, den;
00392 
00393     switch (rb_scan_args(argc, argv, "11", &num, &den)) {
00394       case 1:
00395         if (!k_integer_p(num))
00396             num = f_to_i(num);
00397         den = ONE;
00398         break;
00399       default:
00400         if (!k_integer_p(num))
00401             num = f_to_i(num);
00402         if (!k_integer_p(den))
00403             den = f_to_i(den);
00404 
00405         switch (FIX2INT(f_cmp(den, ZERO))) {
00406           case -1:
00407             num = f_negate(num);
00408             den = f_negate(den);
00409             break;
00410           case 0:
00411             rb_raise_zerodiv();
00412             break;
00413         }
00414         break;
00415     }
00416 
00417     return nurat_s_new_internal(klass, num, den);
00418 }
00419 #endif
00420 
00421 inline static VALUE
00422 f_rational_new_bang1(VALUE klass, VALUE x)
00423 {
00424     return nurat_s_new_internal(klass, x, ONE);
00425 }
00426 
00427 inline static VALUE
00428 f_rational_new_bang2(VALUE klass, VALUE x, VALUE y)
00429 {
00430     assert(f_positive_p(y));
00431     assert(f_nonzero_p(y));
00432     return nurat_s_new_internal(klass, x, y);
00433 }
00434 
00435 #ifdef CANONICALIZATION_FOR_MATHN
00436 #define CANON
00437 #endif
00438 
00439 #ifdef CANON
00440 static int canonicalization = 0;
00441 
00442 RUBY_FUNC_EXPORTED void
00443 nurat_canonicalization(int f)
00444 {
00445     canonicalization = f;
00446 }
00447 #endif
00448 
00449 inline static void
00450 nurat_int_check(VALUE num)
00451 {
00452     switch (TYPE(num)) {
00453       case T_FIXNUM:
00454       case T_BIGNUM:
00455         break;
00456       default:
00457         if (!k_numeric_p(num) || !f_integer_p(num))
00458             rb_raise(rb_eTypeError, "not an integer");
00459     }
00460 }
00461 
00462 inline static VALUE
00463 nurat_int_value(VALUE num)
00464 {
00465     nurat_int_check(num);
00466     if (!k_integer_p(num))
00467         num = f_to_i(num);
00468     return num;
00469 }
00470 
00471 inline static VALUE
00472 nurat_s_canonicalize_internal(VALUE klass, VALUE num, VALUE den)
00473 {
00474     VALUE gcd;
00475 
00476     switch (FIX2INT(f_cmp(den, ZERO))) {
00477       case -1:
00478         num = f_negate(num);
00479         den = f_negate(den);
00480         break;
00481       case 0:
00482         rb_raise_zerodiv();
00483         break;
00484     }
00485 
00486     gcd = f_gcd(num, den);
00487     num = f_idiv(num, gcd);
00488     den = f_idiv(den, gcd);
00489 
00490 #ifdef CANON
00491     if (f_one_p(den) && canonicalization)
00492         return num;
00493 #endif
00494     return nurat_s_new_internal(klass, num, den);
00495 }
00496 
00497 inline static VALUE
00498 nurat_s_canonicalize_internal_no_reduce(VALUE klass, VALUE num, VALUE den)
00499 {
00500     switch (FIX2INT(f_cmp(den, ZERO))) {
00501       case -1:
00502         num = f_negate(num);
00503         den = f_negate(den);
00504         break;
00505       case 0:
00506         rb_raise_zerodiv();
00507         break;
00508     }
00509 
00510 #ifdef CANON
00511     if (f_one_p(den) && canonicalization)
00512         return num;
00513 #endif
00514     return nurat_s_new_internal(klass, num, den);
00515 }
00516 
00517 static VALUE
00518 nurat_s_new(int argc, VALUE *argv, VALUE klass)
00519 {
00520     VALUE num, den;
00521 
00522     switch (rb_scan_args(argc, argv, "11", &num, &den)) {
00523       case 1:
00524         num = nurat_int_value(num);
00525         den = ONE;
00526         break;
00527       default:
00528         num = nurat_int_value(num);
00529         den = nurat_int_value(den);
00530         break;
00531     }
00532 
00533     return nurat_s_canonicalize_internal(klass, num, den);
00534 }
00535 
00536 inline static VALUE
00537 f_rational_new1(VALUE klass, VALUE x)
00538 {
00539     assert(!k_rational_p(x));
00540     return nurat_s_canonicalize_internal(klass, x, ONE);
00541 }
00542 
00543 inline static VALUE
00544 f_rational_new2(VALUE klass, VALUE x, VALUE y)
00545 {
00546     assert(!k_rational_p(x));
00547     assert(!k_rational_p(y));
00548     return nurat_s_canonicalize_internal(klass, x, y);
00549 }
00550 
00551 inline static VALUE
00552 f_rational_new_no_reduce1(VALUE klass, VALUE x)
00553 {
00554     assert(!k_rational_p(x));
00555     return nurat_s_canonicalize_internal_no_reduce(klass, x, ONE);
00556 }
00557 
00558 inline static VALUE
00559 f_rational_new_no_reduce2(VALUE klass, VALUE x, VALUE y)
00560 {
00561     assert(!k_rational_p(x));
00562     assert(!k_rational_p(y));
00563     return nurat_s_canonicalize_internal_no_reduce(klass, x, y);
00564 }
00565 
00566 /*
00567  * call-seq:
00568  *    Rational(x[, y])  ->  numeric
00569  *
00570  * Returns x/y;
00571  *
00572  *    Rational(1, 2)   #=> (1/2)
00573  *    Rational('1/2')  #=> (1/2)
00574  *
00575  * Syntax of string form:
00576  *
00577  *   string form = extra spaces , rational , extra spaces ;
00578  *   rational = [ sign ] , unsigned rational ;
00579  *   unsigned rational = numerator | numerator , "/" , denominator ;
00580  *   numerator = integer part | fractional part | integer part , fractional part ;
00581  *   denominator = digits ;
00582  *   integer part = digits ;
00583  *   fractional part = "." , digits , [ ( "e" | "E" ) , [ sign ] , digits ] ;
00584  *   sign = "-" | "+" ;
00585  *   digits = digit , { digit | "_" , digit } ;
00586  *   digit = "0" | "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9" ;
00587  *   extra spaces = ? \s* ? ;
00588  *
00589  * See String#to_r.
00590  */
00591 static VALUE
00592 nurat_f_rational(int argc, VALUE *argv, VALUE klass)
00593 {
00594     return rb_funcall2(rb_cRational, id_convert, argc, argv);
00595 }
00596 
00597 /*
00598  * call-seq:
00599  *    rat.numerator  ->  integer
00600  *
00601  * Returns the numerator.
00602  *
00603  *    Rational(7).numerator        #=> 7
00604  *    Rational(7, 1).numerator     #=> 7
00605  *    Rational(9, -4).numerator    #=> -9
00606  *    Rational(-2, -10).numerator  #=> 1
00607  */
00608 static VALUE
00609 nurat_numerator(VALUE self)
00610 {
00611     get_dat1(self);
00612     return dat->num;
00613 }
00614 
00615 /*
00616  * call-seq:
00617  *    rat.denominator  ->  integer
00618  *
00619  * Returns the denominator (always positive).
00620  *
00621  *    Rational(7).denominator             #=> 1
00622  *    Rational(7, 1).denominator          #=> 1
00623  *    Rational(9, -4).denominator         #=> 4
00624  *    Rational(-2, -10).denominator       #=> 5
00625  *    rat.numerator.gcd(rat.denominator)  #=> 1
00626  */
00627 static VALUE
00628 nurat_denominator(VALUE self)
00629 {
00630     get_dat1(self);
00631     return dat->den;
00632 }
00633 
00634 #ifndef NDEBUG
00635 #define f_imul f_imul_orig
00636 #endif
00637 
00638 inline static VALUE
00639 f_imul(long a, long b)
00640 {
00641     VALUE r;
00642 
00643     if (a == 0 || b == 0)
00644         return ZERO;
00645     else if (a == 1)
00646         return LONG2NUM(b);
00647     else if (b == 1)
00648         return LONG2NUM(a);
00649 
00650     if (MUL_OVERFLOW_LONG_P(a, b))
00651         r = rb_big_mul(rb_int2big(a), rb_int2big(b));
00652     else
00653         r = LONG2NUM(a * b);
00654     return r;
00655 }
00656 
00657 #ifndef NDEBUG
00658 #undef f_imul
00659 
00660 inline static VALUE
00661 f_imul(long x, long y)
00662 {
00663     VALUE r = f_imul_orig(x, y);
00664     assert(f_eqeq_p(r, f_mul(LONG2NUM(x), LONG2NUM(y))));
00665     return r;
00666 }
00667 #endif
00668 
00669 inline static VALUE
00670 f_addsub(VALUE self, VALUE anum, VALUE aden, VALUE bnum, VALUE bden, int k)
00671 {
00672     VALUE num, den;
00673 
00674     if (FIXNUM_P(anum) && FIXNUM_P(aden) &&
00675         FIXNUM_P(bnum) && FIXNUM_P(bden)) {
00676         long an = FIX2LONG(anum);
00677         long ad = FIX2LONG(aden);
00678         long bn = FIX2LONG(bnum);
00679         long bd = FIX2LONG(bden);
00680         long ig = i_gcd(ad, bd);
00681 
00682         VALUE g = LONG2NUM(ig);
00683         VALUE a = f_imul(an, bd / ig);
00684         VALUE b = f_imul(bn, ad / ig);
00685         VALUE c;
00686 
00687         if (k == '+')
00688             c = f_add(a, b);
00689         else
00690             c = f_sub(a, b);
00691 
00692         b = f_idiv(aden, g);
00693         g = f_gcd(c, g);
00694         num = f_idiv(c, g);
00695         a = f_idiv(bden, g);
00696         den = f_mul(a, b);
00697     }
00698     else {
00699         VALUE g = f_gcd(aden, bden);
00700         VALUE a = f_mul(anum, f_idiv(bden, g));
00701         VALUE b = f_mul(bnum, f_idiv(aden, g));
00702         VALUE c;
00703 
00704         if (k == '+')
00705             c = f_add(a, b);
00706         else
00707             c = f_sub(a, b);
00708 
00709         b = f_idiv(aden, g);
00710         g = f_gcd(c, g);
00711         num = f_idiv(c, g);
00712         a = f_idiv(bden, g);
00713         den = f_mul(a, b);
00714     }
00715     return f_rational_new_no_reduce2(CLASS_OF(self), num, den);
00716 }
00717 
00718 /*
00719  * call-seq:
00720  *    rat + numeric  ->  numeric
00721  *
00722  * Performs addition.
00723  *
00724  *    Rational(2, 3)  + Rational(2, 3)   #=> (4/3)
00725  *    Rational(900)   + Rational(1)      #=> (900/1)
00726  *    Rational(-2, 9) + Rational(-9, 2)  #=> (-85/18)
00727  *    Rational(9, 8)  + 4                #=> (41/8)
00728  *    Rational(20, 9) + 9.8              #=> 12.022222222222222
00729  */
00730 static VALUE
00731 nurat_add(VALUE self, VALUE other)
00732 {
00733     switch (TYPE(other)) {
00734       case T_FIXNUM:
00735       case T_BIGNUM:
00736         {
00737             get_dat1(self);
00738 
00739             return f_addsub(self,
00740                             dat->num, dat->den,
00741                             other, ONE, '+');
00742         }
00743       case T_FLOAT:
00744         return f_add(f_to_f(self), other);
00745       case T_RATIONAL:
00746         {
00747             get_dat2(self, other);
00748 
00749             return f_addsub(self,
00750                             adat->num, adat->den,
00751                             bdat->num, bdat->den, '+');
00752         }
00753       default:
00754         return rb_num_coerce_bin(self, other, '+');
00755     }
00756 }
00757 
00758 /*
00759  * call-seq:
00760  *    rat - numeric  ->  numeric
00761  *
00762  * Performs subtraction.
00763  *
00764  *    Rational(2, 3)  - Rational(2, 3)   #=> (0/1)
00765  *    Rational(900)   - Rational(1)      #=> (899/1)
00766  *    Rational(-2, 9) - Rational(-9, 2)  #=> (77/18)
00767  *    Rational(9, 8)  - 4                #=> (23/8)
00768  *    Rational(20, 9) - 9.8              #=> -7.577777777777778
00769  */
00770 static VALUE
00771 nurat_sub(VALUE self, VALUE other)
00772 {
00773     switch (TYPE(other)) {
00774       case T_FIXNUM:
00775       case T_BIGNUM:
00776         {
00777             get_dat1(self);
00778 
00779             return f_addsub(self,
00780                             dat->num, dat->den,
00781                             other, ONE, '-');
00782         }
00783       case T_FLOAT:
00784         return f_sub(f_to_f(self), other);
00785       case T_RATIONAL:
00786         {
00787             get_dat2(self, other);
00788 
00789             return f_addsub(self,
00790                             adat->num, adat->den,
00791                             bdat->num, bdat->den, '-');
00792         }
00793       default:
00794         return rb_num_coerce_bin(self, other, '-');
00795     }
00796 }
00797 
00798 inline static VALUE
00799 f_muldiv(VALUE self, VALUE anum, VALUE aden, VALUE bnum, VALUE bden, int k)
00800 {
00801     VALUE num, den;
00802 
00803     if (k == '/') {
00804         VALUE t;
00805 
00806         if (f_negative_p(bnum)) {
00807             anum = f_negate(anum);
00808             bnum = f_negate(bnum);
00809         }
00810         t = bnum;
00811         bnum = bden;
00812         bden = t;
00813     }
00814 
00815     if (FIXNUM_P(anum) && FIXNUM_P(aden) &&
00816         FIXNUM_P(bnum) && FIXNUM_P(bden)) {
00817         long an = FIX2LONG(anum);
00818         long ad = FIX2LONG(aden);
00819         long bn = FIX2LONG(bnum);
00820         long bd = FIX2LONG(bden);
00821         long g1 = i_gcd(an, bd);
00822         long g2 = i_gcd(ad, bn);
00823 
00824         num = f_imul(an / g1, bn / g2);
00825         den = f_imul(ad / g2, bd / g1);
00826     }
00827     else {
00828         VALUE g1 = f_gcd(anum, bden);
00829         VALUE g2 = f_gcd(aden, bnum);
00830 
00831         num = f_mul(f_idiv(anum, g1), f_idiv(bnum, g2));
00832         den = f_mul(f_idiv(aden, g2), f_idiv(bden, g1));
00833     }
00834     return f_rational_new_no_reduce2(CLASS_OF(self), num, den);
00835 }
00836 
00837 /*
00838  * call-seq:
00839  *    rat * numeric  ->  numeric
00840  *
00841  * Performs multiplication.
00842  *
00843  *    Rational(2, 3)  * Rational(2, 3)   #=> (4/9)
00844  *    Rational(900)   * Rational(1)      #=> (900/1)
00845  *    Rational(-2, 9) * Rational(-9, 2)  #=> (1/1)
00846  *    Rational(9, 8)  * 4                #=> (9/2)
00847  *    Rational(20, 9) * 9.8              #=> 21.77777777777778
00848  */
00849 static VALUE
00850 nurat_mul(VALUE self, VALUE other)
00851 {
00852     switch (TYPE(other)) {
00853       case T_FIXNUM:
00854       case T_BIGNUM:
00855         {
00856             get_dat1(self);
00857 
00858             return f_muldiv(self,
00859                             dat->num, dat->den,
00860                             other, ONE, '*');
00861         }
00862       case T_FLOAT:
00863         return f_mul(f_to_f(self), other);
00864       case T_RATIONAL:
00865         {
00866             get_dat2(self, other);
00867 
00868             return f_muldiv(self,
00869                             adat->num, adat->den,
00870                             bdat->num, bdat->den, '*');
00871         }
00872       default:
00873         return rb_num_coerce_bin(self, other, '*');
00874     }
00875 }
00876 
00877 /*
00878  * call-seq:
00879  *    rat / numeric     ->  numeric
00880  *    rat.quo(numeric)  ->  numeric
00881  *
00882  * Performs division.
00883  *
00884  *    Rational(2, 3)  / Rational(2, 3)   #=> (1/1)
00885  *    Rational(900)   / Rational(1)      #=> (900/1)
00886  *    Rational(-2, 9) / Rational(-9, 2)  #=> (4/81)
00887  *    Rational(9, 8)  / 4                #=> (9/32)
00888  *    Rational(20, 9) / 9.8              #=> 0.22675736961451246
00889  */
00890 static VALUE
00891 nurat_div(VALUE self, VALUE other)
00892 {
00893     switch (TYPE(other)) {
00894       case T_FIXNUM:
00895       case T_BIGNUM:
00896         if (f_zero_p(other))
00897             rb_raise_zerodiv();
00898         {
00899             get_dat1(self);
00900 
00901             return f_muldiv(self,
00902                             dat->num, dat->den,
00903                             other, ONE, '/');
00904         }
00905       case T_FLOAT:
00906         {
00907             double x = RFLOAT_VALUE(other), den;
00908             get_dat1(self);
00909 
00910             if (isnan(x)) return DBL2NUM(NAN);
00911             if (isinf(x)) return INT2FIX(0);
00912             if (x != 0.0 && modf(x, &den) == 0.0) {
00913                 return rb_rational_raw2(dat->num, f_mul(rb_dbl2big(den), dat->den));
00914             }
00915         }
00916         return rb_funcall(f_to_f(self), '/', 1, other);
00917       case T_RATIONAL:
00918         if (f_zero_p(other))
00919             rb_raise_zerodiv();
00920         {
00921             get_dat2(self, other);
00922 
00923             if (f_one_p(self))
00924                 return f_rational_new_no_reduce2(CLASS_OF(self),
00925                                                  bdat->den, bdat->num);
00926 
00927             return f_muldiv(self,
00928                             adat->num, adat->den,
00929                             bdat->num, bdat->den, '/');
00930         }
00931       default:
00932         return rb_num_coerce_bin(self, other, '/');
00933     }
00934 }
00935 
00936 /*
00937  * call-seq:
00938  *    rat.fdiv(numeric)  ->  float
00939  *
00940  * Performs division and returns the value as a float.
00941  *
00942  *    Rational(2, 3).fdiv(1)       #=> 0.6666666666666666
00943  *    Rational(2, 3).fdiv(0.5)     #=> 1.3333333333333333
00944  *    Rational(2).fdiv(3)          #=> 0.6666666666666666
00945  */
00946 static VALUE
00947 nurat_fdiv(VALUE self, VALUE other)
00948 {
00949     if (f_zero_p(other))
00950         return f_div(self, f_to_f(other));
00951     return f_to_f(f_div(self, other));
00952 }
00953 
00954 inline static VALUE
00955 f_odd_p(VALUE integer)
00956 {
00957     if (rb_funcall(integer, '%', 1, INT2FIX(2)) != INT2FIX(0)) {
00958         return Qtrue;
00959     }
00960     return Qfalse;
00961 
00962 }
00963 
00964 /*
00965  * call-seq:
00966  *    rat ** numeric  ->  numeric
00967  *
00968  * Performs exponentiation.
00969  *
00970  *    Rational(2)    ** Rational(3)    #=> (8/1)
00971  *    Rational(10)   ** -2             #=> (1/100)
00972  *    Rational(10)   ** -2.0           #=> 0.01
00973  *    Rational(-4)   ** Rational(1,2)  #=> (1.2246063538223773e-16+2.0i)
00974  *    Rational(1, 2) ** 0              #=> (1/1)
00975  *    Rational(1, 2) ** 0.0            #=> 1.0
00976  */
00977 static VALUE
00978 nurat_expt(VALUE self, VALUE other)
00979 {
00980     if (k_numeric_p(other) && k_exact_zero_p(other))
00981         return f_rational_new_bang1(CLASS_OF(self), ONE);
00982 
00983     if (k_rational_p(other)) {
00984         get_dat1(other);
00985 
00986         if (f_one_p(dat->den))
00987             other = dat->num; /* c14n */
00988     }
00989 
00990     /* Deal with special cases of 0**n and 1**n */
00991     if (k_numeric_p(other) && k_exact_p(other)) {
00992         get_dat1(self);
00993         if (f_one_p(dat->den))
00994             if (f_one_p(dat->num))
00995                 return f_rational_new_bang1(CLASS_OF(self), ONE);
00996             else if (f_minus_one_p(dat->num) && k_integer_p(other))
00997                 return f_rational_new_bang1(CLASS_OF(self), INT2FIX(f_odd_p(other) ? -1 : 1));
00998             else if (f_zero_p(dat->num))
00999                 if (FIX2INT(f_cmp(other, ZERO)) == -1)
01000                     rb_raise_zerodiv();
01001                 else
01002                     return f_rational_new_bang1(CLASS_OF(self), ZERO);
01003     }
01004 
01005     /* General case */
01006     switch (TYPE(other)) {
01007       case T_FIXNUM:
01008         {
01009             VALUE num, den;
01010 
01011             get_dat1(self);
01012 
01013             switch (FIX2INT(f_cmp(other, ZERO))) {
01014               case 1:
01015                 num = f_expt(dat->num, other);
01016                 den = f_expt(dat->den, other);
01017                 break;
01018               case -1:
01019                 num = f_expt(dat->den, f_negate(other));
01020                 den = f_expt(dat->num, f_negate(other));
01021                 break;
01022               default:
01023                 num = ONE;
01024                 den = ONE;
01025                 break;
01026             }
01027             return f_rational_new2(CLASS_OF(self), num, den);
01028         }
01029       case T_BIGNUM:
01030         rb_warn("in a**b, b may be too big");
01031         /* fall through */
01032       case T_FLOAT:
01033       case T_RATIONAL:
01034         return f_expt(f_to_f(self), other);
01035       default:
01036         return rb_num_coerce_bin(self, other, id_expt);
01037     }
01038 }
01039 
01040 /*
01041  * call-seq:
01042  *    rational <=> numeric  ->  -1, 0, +1 or nil
01043  *
01044  * Performs comparison and returns -1, 0, or +1.
01045  *
01046  * +nil+ is returned if the two values are incomparable.
01047  *
01048  *    Rational(2, 3)  <=> Rational(2, 3)  #=> 0
01049  *    Rational(5)     <=> 5               #=> 0
01050  *    Rational(2,3)   <=> Rational(1,3)   #=> 1
01051  *    Rational(1,3)   <=> 1               #=> -1
01052  *    Rational(1,3)   <=> 0.3             #=> 1
01053  */
01054 static VALUE
01055 nurat_cmp(VALUE self, VALUE other)
01056 {
01057     switch (TYPE(other)) {
01058       case T_FIXNUM:
01059       case T_BIGNUM:
01060         {
01061             get_dat1(self);
01062 
01063             if (FIXNUM_P(dat->den) && FIX2LONG(dat->den) == 1)
01064                 return f_cmp(dat->num, other); /* c14n */
01065             return f_cmp(self, f_rational_new_bang1(CLASS_OF(self), other));
01066         }
01067       case T_FLOAT:
01068         return f_cmp(f_to_f(self), other);
01069       case T_RATIONAL:
01070         {
01071             VALUE num1, num2;
01072 
01073             get_dat2(self, other);
01074 
01075             if (FIXNUM_P(adat->num) && FIXNUM_P(adat->den) &&
01076                 FIXNUM_P(bdat->num) && FIXNUM_P(bdat->den)) {
01077                 num1 = f_imul(FIX2LONG(adat->num), FIX2LONG(bdat->den));
01078                 num2 = f_imul(FIX2LONG(bdat->num), FIX2LONG(adat->den));
01079             }
01080             else {
01081                 num1 = f_mul(adat->num, bdat->den);
01082                 num2 = f_mul(bdat->num, adat->den);
01083             }
01084             return f_cmp(f_sub(num1, num2), ZERO);
01085         }
01086       default:
01087         return rb_num_coerce_cmp(self, other, id_cmp);
01088     }
01089 }
01090 
01091 /*
01092  * call-seq:
01093  *    rat == object  ->  true or false
01094  *
01095  * Returns true if rat equals object numerically.
01096  *
01097  *    Rational(2, 3)  == Rational(2, 3)   #=> true
01098  *    Rational(5)     == 5                #=> true
01099  *    Rational(0)     == 0.0              #=> true
01100  *    Rational('1/3') == 0.33             #=> false
01101  *    Rational('1/2') == '1/2'            #=> false
01102  */
01103 static VALUE
01104 nurat_eqeq_p(VALUE self, VALUE other)
01105 {
01106     switch (TYPE(other)) {
01107       case T_FIXNUM:
01108       case T_BIGNUM:
01109         {
01110             get_dat1(self);
01111 
01112             if (f_zero_p(dat->num) && f_zero_p(other))
01113                 return Qtrue;
01114 
01115             if (!FIXNUM_P(dat->den))
01116                 return Qfalse;
01117             if (FIX2LONG(dat->den) != 1)
01118                 return Qfalse;
01119             if (f_eqeq_p(dat->num, other))
01120                 return Qtrue;
01121             return Qfalse;
01122         }
01123       case T_FLOAT:
01124         return f_eqeq_p(f_to_f(self), other);
01125       case T_RATIONAL:
01126         {
01127             get_dat2(self, other);
01128 
01129             if (f_zero_p(adat->num) && f_zero_p(bdat->num))
01130                 return Qtrue;
01131 
01132             return f_boolcast(f_eqeq_p(adat->num, bdat->num) &&
01133                               f_eqeq_p(adat->den, bdat->den));
01134         }
01135       default:
01136         return f_eqeq_p(other, self);
01137     }
01138 }
01139 
01140 /* :nodoc: */
01141 static VALUE
01142 nurat_coerce(VALUE self, VALUE other)
01143 {
01144     switch (TYPE(other)) {
01145       case T_FIXNUM:
01146       case T_BIGNUM:
01147         return rb_assoc_new(f_rational_new_bang1(CLASS_OF(self), other), self);
01148       case T_FLOAT:
01149         return rb_assoc_new(other, f_to_f(self));
01150       case T_RATIONAL:
01151         return rb_assoc_new(other, self);
01152       case T_COMPLEX:
01153         if (k_exact_zero_p(RCOMPLEX(other)->imag))
01154             return rb_assoc_new(f_rational_new_bang1
01155                                 (CLASS_OF(self), RCOMPLEX(other)->real), self);
01156         else
01157             return rb_assoc_new(other, rb_Complex(self, INT2FIX(0)));
01158     }
01159 
01160     rb_raise(rb_eTypeError, "%s can't be coerced into %s",
01161              rb_obj_classname(other), rb_obj_classname(self));
01162     return Qnil;
01163 }
01164 
01165 #if 0
01166 /* :nodoc: */
01167 static VALUE
01168 nurat_idiv(VALUE self, VALUE other)
01169 {
01170     return f_idiv(self, other);
01171 }
01172 
01173 /* :nodoc: */
01174 static VALUE
01175 nurat_quot(VALUE self, VALUE other)
01176 {
01177     return f_truncate(f_div(self, other));
01178 }
01179 
01180 /* :nodoc: */
01181 static VALUE
01182 nurat_quotrem(VALUE self, VALUE other)
01183 {
01184     VALUE val = f_truncate(f_div(self, other));
01185     return rb_assoc_new(val, f_sub(self, f_mul(other, val)));
01186 }
01187 #endif
01188 
01189 #if 0
01190 /* :nodoc: */
01191 static VALUE
01192 nurat_true(VALUE self)
01193 {
01194     return Qtrue;
01195 }
01196 #endif
01197 
01198 static VALUE
01199 nurat_floor(VALUE self)
01200 {
01201     get_dat1(self);
01202     return f_idiv(dat->num, dat->den);
01203 }
01204 
01205 static VALUE
01206 nurat_ceil(VALUE self)
01207 {
01208     get_dat1(self);
01209     return f_negate(f_idiv(f_negate(dat->num), dat->den));
01210 }
01211 
01212 /*
01213  * call-seq:
01214  *    rat.to_i  ->  integer
01215  *
01216  * Returns the truncated value as an integer.
01217  *
01218  * Equivalent to
01219  *    rat.truncate.
01220  *
01221  *    Rational(2, 3).to_i   #=> 0
01222  *    Rational(3).to_i      #=> 3
01223  *    Rational(300.6).to_i  #=> 300
01224  *    Rational(98,71).to_i  #=> 1
01225  *    Rational(-30,2).to_i  #=> -15
01226  */
01227 static VALUE
01228 nurat_truncate(VALUE self)
01229 {
01230     get_dat1(self);
01231     if (f_negative_p(dat->num))
01232         return f_negate(f_idiv(f_negate(dat->num), dat->den));
01233     return f_idiv(dat->num, dat->den);
01234 }
01235 
01236 static VALUE
01237 nurat_round(VALUE self)
01238 {
01239     VALUE num, den, neg;
01240 
01241     get_dat1(self);
01242 
01243     num = dat->num;
01244     den = dat->den;
01245     neg = f_negative_p(num);
01246 
01247     if (neg)
01248         num = f_negate(num);
01249 
01250     num = f_add(f_mul(num, TWO), den);
01251     den = f_mul(den, TWO);
01252     num = f_idiv(num, den);
01253 
01254     if (neg)
01255         num = f_negate(num);
01256 
01257     return num;
01258 }
01259 
01260 static VALUE
01261 f_round_common(int argc, VALUE *argv, VALUE self, VALUE (*func)(VALUE))
01262 {
01263     VALUE n, b, s;
01264 
01265     if (argc == 0)
01266         return (*func)(self);
01267 
01268     rb_scan_args(argc, argv, "01", &n);
01269 
01270     if (!k_integer_p(n))
01271         rb_raise(rb_eTypeError, "not an integer");
01272 
01273     b = f_expt10(n);
01274     s = f_mul(self, b);
01275 
01276     if (k_float_p(s)) {
01277         if (f_lt_p(n, ZERO))
01278             return ZERO;
01279         return self;
01280     }
01281 
01282     if (!k_rational_p(s)) {
01283         s = f_rational_new_bang1(CLASS_OF(self), s);
01284     }
01285 
01286     s = (*func)(s);
01287 
01288     s = f_div(f_rational_new_bang1(CLASS_OF(self), s), b);
01289 
01290     if (f_lt_p(n, ONE))
01291         s = f_to_i(s);
01292 
01293     return s;
01294 }
01295 
01296 /*
01297  * call-seq:
01298  *    rat.floor               ->  integer
01299  *    rat.floor(precision=0)  ->  rational
01300  *
01301  * Returns the truncated value (toward negative infinity).
01302  *
01303  *    Rational(3).floor      #=> 3
01304  *    Rational(2, 3).floor   #=> 0
01305  *    Rational(-3, 2).floor  #=> -1
01306  *
01307  *           decimal      -  1  2  3 . 4  5  6
01308  *                          ^  ^  ^  ^   ^  ^
01309  *          precision      -3 -2 -1  0  +1 +2
01310  *
01311  *    '%f' % Rational('-123.456').floor(+1)  #=> "-123.500000"
01312  *    '%f' % Rational('-123.456').floor(-1)  #=> "-130.000000"
01313  */
01314 static VALUE
01315 nurat_floor_n(int argc, VALUE *argv, VALUE self)
01316 {
01317     return f_round_common(argc, argv, self, nurat_floor);
01318 }
01319 
01320 /*
01321  * call-seq:
01322  *    rat.ceil               ->  integer
01323  *    rat.ceil(precision=0)  ->  rational
01324  *
01325  * Returns the truncated value (toward positive infinity).
01326  *
01327  *    Rational(3).ceil      #=> 3
01328  *    Rational(2, 3).ceil   #=> 1
01329  *    Rational(-3, 2).ceil  #=> -1
01330  *
01331  *           decimal      -  1  2  3 . 4  5  6
01332  *                          ^  ^  ^  ^   ^  ^
01333  *          precision      -3 -2 -1  0  +1 +2
01334  *
01335  *    '%f' % Rational('-123.456').ceil(+1)  #=> "-123.400000"
01336  *    '%f' % Rational('-123.456').ceil(-1)  #=> "-120.000000"
01337  */
01338 static VALUE
01339 nurat_ceil_n(int argc, VALUE *argv, VALUE self)
01340 {
01341     return f_round_common(argc, argv, self, nurat_ceil);
01342 }
01343 
01344 /*
01345  * call-seq:
01346  *    rat.truncate               ->  integer
01347  *    rat.truncate(precision=0)  ->  rational
01348  *
01349  * Returns the truncated value (toward zero).
01350  *
01351  *    Rational(3).truncate      #=> 3
01352  *    Rational(2, 3).truncate   #=> 0
01353  *    Rational(-3, 2).truncate  #=> -1
01354  *
01355  *           decimal      -  1  2  3 . 4  5  6
01356  *                          ^  ^  ^  ^   ^  ^
01357  *          precision      -3 -2 -1  0  +1 +2
01358  *
01359  *    '%f' % Rational('-123.456').truncate(+1)  #=>  "-123.400000"
01360  *    '%f' % Rational('-123.456').truncate(-1)  #=>  "-120.000000"
01361  */
01362 static VALUE
01363 nurat_truncate_n(int argc, VALUE *argv, VALUE self)
01364 {
01365     return f_round_common(argc, argv, self, nurat_truncate);
01366 }
01367 
01368 /*
01369  * call-seq:
01370  *    rat.round               ->  integer
01371  *    rat.round(precision=0)  ->  rational
01372  *
01373  * Returns the truncated value (toward the nearest integer;
01374  * 0.5 => 1; -0.5 => -1).
01375  *
01376  *    Rational(3).round      #=> 3
01377  *    Rational(2, 3).round   #=> 1
01378  *    Rational(-3, 2).round  #=> -2
01379  *
01380  *           decimal      -  1  2  3 . 4  5  6
01381  *                          ^  ^  ^  ^   ^  ^
01382  *          precision      -3 -2 -1  0  +1 +2
01383  *
01384  *    '%f' % Rational('-123.456').round(+1)  #=> "-123.500000"
01385  *    '%f' % Rational('-123.456').round(-1)  #=> "-120.000000"
01386  */
01387 static VALUE
01388 nurat_round_n(int argc, VALUE *argv, VALUE self)
01389 {
01390     return f_round_common(argc, argv, self, nurat_round);
01391 }
01392 
01393 /*
01394  * call-seq:
01395  *    rat.to_f  ->  float
01396  *
01397  * Return the value as a float.
01398  *
01399  *    Rational(2).to_f      #=> 2.0
01400  *    Rational(9, 4).to_f   #=> 2.25
01401  *    Rational(-3, 4).to_f  #=> -0.75
01402  *    Rational(20, 3).to_f  #=> 6.666666666666667
01403  */
01404 static VALUE
01405 nurat_to_f(VALUE self)
01406 {
01407     get_dat1(self);
01408     return f_fdiv(dat->num, dat->den);
01409 }
01410 
01411 /*
01412  * call-seq:
01413  *    rat.to_r  ->  self
01414  *
01415  * Returns self.
01416  *
01417  *    Rational(2).to_r      #=> (2/1)
01418  *    Rational(-8, 6).to_r  #=> (-4/3)
01419  */
01420 static VALUE
01421 nurat_to_r(VALUE self)
01422 {
01423     return self;
01424 }
01425 
01426 #define id_ceil rb_intern("ceil")
01427 #define f_ceil(x) rb_funcall((x), id_ceil, 0)
01428 
01429 #define id_quo rb_intern("quo")
01430 #define f_quo(x,y) rb_funcall((x), id_quo, 1, (y))
01431 
01432 #define f_reciprocal(x) f_quo(ONE, (x))
01433 
01434 /*
01435   The algorithm here is the method described in CLISP.  Bruno Haible has
01436   graciously given permission to use this algorithm.  He says, "You can use
01437   it, if you present the following explanation of the algorithm."
01438 
01439   Algorithm (recursively presented):
01440     If x is a rational number, return x.
01441     If x = 0.0, return 0.
01442     If x < 0.0, return (- (rationalize (- x))).
01443     If x > 0.0:
01444       Call (integer-decode-float x). It returns a m,e,s=1 (mantissa,
01445       exponent, sign).
01446       If m = 0 or e >= 0: return x = m*2^e.
01447       Search a rational number between a = (m-1/2)*2^e and b = (m+1/2)*2^e
01448       with smallest possible numerator and denominator.
01449       Note 1: If m is a power of 2, we ought to take a = (m-1/4)*2^e.
01450         But in this case the result will be x itself anyway, regardless of
01451         the choice of a. Therefore we can simply ignore this case.
01452       Note 2: At first, we need to consider the closed interval [a,b].
01453         but since a and b have the denominator 2^(|e|+1) whereas x itself
01454         has a denominator <= 2^|e|, we can restrict the search to the open
01455         interval (a,b).
01456       So, for given a and b (0 < a < b) we are searching a rational number
01457       y with a <= y <= b.
01458       Recursive algorithm fraction_between(a,b):
01459         c := (ceiling a)
01460         if c < b
01461           then return c       ; because a <= c < b, c integer
01462           else
01463             ; a is not integer (otherwise we would have had c = a < b)
01464             k := c-1          ; k = floor(a), k < a < b <= k+1
01465             return y = k + 1/fraction_between(1/(b-k), 1/(a-k))
01466                               ; note 1 <= 1/(b-k) < 1/(a-k)
01467 
01468   You can see that we are actually computing a continued fraction expansion.
01469 
01470   Algorithm (iterative):
01471     If x is rational, return x.
01472     Call (integer-decode-float x). It returns a m,e,s (mantissa,
01473       exponent, sign).
01474     If m = 0 or e >= 0, return m*2^e*s. (This includes the case x = 0.0.)
01475     Create rational numbers a := (2*m-1)*2^(e-1) and b := (2*m+1)*2^(e-1)
01476     (positive and already in lowest terms because the denominator is a
01477     power of two and the numerator is odd).
01478     Start a continued fraction expansion
01479       p[-1] := 0, p[0] := 1, q[-1] := 1, q[0] := 0, i := 0.
01480     Loop
01481       c := (ceiling a)
01482       if c >= b
01483         then k := c-1, partial_quotient(k), (a,b) := (1/(b-k),1/(a-k)),
01484              goto Loop
01485     finally partial_quotient(c).
01486     Here partial_quotient(c) denotes the iteration
01487       i := i+1, p[i] := c*p[i-1]+p[i-2], q[i] := c*q[i-1]+q[i-2].
01488     At the end, return s * (p[i]/q[i]).
01489     This rational number is already in lowest terms because
01490     p[i]*q[i-1]-p[i-1]*q[i] = (-1)^i.
01491 */
01492 
01493 static void
01494 nurat_rationalize_internal(VALUE a, VALUE b, VALUE *p, VALUE *q)
01495 {
01496     VALUE c, k, t, p0, p1, p2, q0, q1, q2;
01497 
01498     p0 = ZERO;
01499     p1 = ONE;
01500     q0 = ONE;
01501     q1 = ZERO;
01502 
01503     while (1) {
01504         c = f_ceil(a);
01505         if (f_lt_p(c, b))
01506             break;
01507         k = f_sub(c, ONE);
01508         p2 = f_add(f_mul(k, p1), p0);
01509         q2 = f_add(f_mul(k, q1), q0);
01510         t = f_reciprocal(f_sub(b, k));
01511         b = f_reciprocal(f_sub(a, k));
01512         a = t;
01513         p0 = p1;
01514         q0 = q1;
01515         p1 = p2;
01516         q1 = q2;
01517     }
01518     *p = f_add(f_mul(c, p1), p0);
01519     *q = f_add(f_mul(c, q1), q0);
01520 }
01521 
01522 /*
01523  * call-seq:
01524  *    rat.rationalize       ->  self
01525  *    rat.rationalize(eps)  ->  rational
01526  *
01527  * Returns a simpler approximation of the value if the optional
01528  * argument eps is given (rat-|eps| <= result <= rat+|eps|), self
01529  * otherwise.
01530  *
01531  *    r = Rational(5033165, 16777216)
01532  *    r.rationalize                    #=> (5033165/16777216)
01533  *    r.rationalize(Rational('0.01'))  #=> (3/10)
01534  *    r.rationalize(Rational('0.1'))   #=> (1/3)
01535  */
01536 static VALUE
01537 nurat_rationalize(int argc, VALUE *argv, VALUE self)
01538 {
01539     VALUE e, a, b, p, q;
01540 
01541     if (argc == 0)
01542         return self;
01543 
01544     if (f_negative_p(self))
01545         return f_negate(nurat_rationalize(argc, argv, f_abs(self)));
01546 
01547     rb_scan_args(argc, argv, "01", &e);
01548     e = f_abs(e);
01549     a = f_sub(self, e);
01550     b = f_add(self, e);
01551 
01552     if (f_eqeq_p(a, b))
01553         return self;
01554 
01555     nurat_rationalize_internal(a, b, &p, &q);
01556     return f_rational_new2(CLASS_OF(self), p, q);
01557 }
01558 
01559 /* :nodoc: */
01560 static VALUE
01561 nurat_hash(VALUE self)
01562 {
01563     st_index_t v, h[2];
01564     VALUE n;
01565 
01566     get_dat1(self);
01567     n = rb_hash(dat->num);
01568     h[0] = NUM2LONG(n);
01569     n = rb_hash(dat->den);
01570     h[1] = NUM2LONG(n);
01571     v = rb_memhash(h, sizeof(h));
01572     return LONG2FIX(v);
01573 }
01574 
01575 static VALUE
01576 f_format(VALUE self, VALUE (*func)(VALUE))
01577 {
01578     VALUE s;
01579     get_dat1(self);
01580 
01581     s = (*func)(dat->num);
01582     rb_str_cat2(s, "/");
01583     rb_str_concat(s, (*func)(dat->den));
01584 
01585     return s;
01586 }
01587 
01588 /*
01589  * call-seq:
01590  *    rat.to_s  ->  string
01591  *
01592  * Returns the value as a string.
01593  *
01594  *    Rational(2).to_s      #=> "2/1"
01595  *    Rational(-8, 6).to_s  #=> "-4/3"
01596  *    Rational('1/2').to_s  #=> "1/2"
01597  */
01598 static VALUE
01599 nurat_to_s(VALUE self)
01600 {
01601     return f_format(self, f_to_s);
01602 }
01603 
01604 /*
01605  * call-seq:
01606  *    rat.inspect  ->  string
01607  *
01608  * Returns the value as a string for inspection.
01609  *
01610  *    Rational(2).inspect      #=> "(2/1)"
01611  *    Rational(-8, 6).inspect  #=> "(-4/3)"
01612  *    Rational('1/2').inspect  #=> "(1/2)"
01613  */
01614 static VALUE
01615 nurat_inspect(VALUE self)
01616 {
01617     VALUE s;
01618 
01619     s = rb_usascii_str_new2("(");
01620     rb_str_concat(s, f_format(self, f_inspect));
01621     rb_str_cat2(s, ")");
01622 
01623     return s;
01624 }
01625 
01626 /* :nodoc: */
01627 static VALUE
01628 nurat_dumper(VALUE self)
01629 {
01630     return self;
01631 }
01632 
01633 /* :nodoc: */
01634 static VALUE
01635 nurat_loader(VALUE self, VALUE a)
01636 {
01637     get_dat1(self);
01638 
01639     dat->num = rb_ivar_get(a, id_i_num);
01640     dat->den = rb_ivar_get(a, id_i_den);
01641 
01642     return self;
01643 }
01644 
01645 /* :nodoc: */
01646 static VALUE
01647 nurat_marshal_dump(VALUE self)
01648 {
01649     VALUE a;
01650     get_dat1(self);
01651 
01652     a = rb_assoc_new(dat->num, dat->den);
01653     rb_copy_generic_ivar(a, self);
01654     return a;
01655 }
01656 
01657 /* :nodoc: */
01658 static VALUE
01659 nurat_marshal_load(VALUE self, VALUE a)
01660 {
01661     rb_check_frozen(self);
01662     rb_check_trusted(self);
01663 
01664     Check_Type(a, T_ARRAY);
01665     if (RARRAY_LEN(a) != 2)
01666         rb_raise(rb_eArgError, "marshaled rational must have an array whose length is 2 but %ld", RARRAY_LEN(a));
01667     if (f_zero_p(RARRAY_PTR(a)[1]))
01668         rb_raise_zerodiv();
01669 
01670     rb_ivar_set(self, id_i_num, RARRAY_PTR(a)[0]);
01671     rb_ivar_set(self, id_i_den, RARRAY_PTR(a)[1]);
01672 
01673     return self;
01674 }
01675 
01676 /* --- */
01677 
01678 VALUE
01679 rb_rational_reciprocal(VALUE x)
01680 {
01681     get_dat1(x);
01682     return f_rational_new_no_reduce2(CLASS_OF(x), dat->den, dat->num);
01683 }
01684 
01685 /*
01686  * call-seq:
01687  *    int.gcd(int2)  ->  integer
01688  *
01689  * Returns the greatest common divisor (always positive).  0.gcd(x)
01690  * and x.gcd(0) return abs(x).
01691  *
01692  *    2.gcd(2)                    #=> 2
01693  *    3.gcd(-7)                   #=> 1
01694  *    ((1<<31)-1).gcd((1<<61)-1)  #=> 1
01695  */
01696 VALUE
01697 rb_gcd(VALUE self, VALUE other)
01698 {
01699     other = nurat_int_value(other);
01700     return f_gcd(self, other);
01701 }
01702 
01703 /*
01704  * call-seq:
01705  *    int.lcm(int2)  ->  integer
01706  *
01707  * Returns the least common multiple (always positive).  0.lcm(x) and
01708  * x.lcm(0) return zero.
01709  *
01710  *    2.lcm(2)                    #=> 2
01711  *    3.lcm(-7)                   #=> 21
01712  *    ((1<<31)-1).lcm((1<<61)-1)  #=> 4951760154835678088235319297
01713  */
01714 VALUE
01715 rb_lcm(VALUE self, VALUE other)
01716 {
01717     other = nurat_int_value(other);
01718     return f_lcm(self, other);
01719 }
01720 
01721 /*
01722  * call-seq:
01723  *    int.gcdlcm(int2)  ->  array
01724  *
01725  * Returns an array; [int.gcd(int2), int.lcm(int2)].
01726  *
01727  *    2.gcdlcm(2)                    #=> [2, 2]
01728  *    3.gcdlcm(-7)                   #=> [1, 21]
01729  *    ((1<<31)-1).gcdlcm((1<<61)-1)  #=> [1, 4951760154835678088235319297]
01730  */
01731 VALUE
01732 rb_gcdlcm(VALUE self, VALUE other)
01733 {
01734     other = nurat_int_value(other);
01735     return rb_assoc_new(f_gcd(self, other), f_lcm(self, other));
01736 }
01737 
01738 VALUE
01739 rb_rational_raw(VALUE x, VALUE y)
01740 {
01741     return nurat_s_new_internal(rb_cRational, x, y);
01742 }
01743 
01744 VALUE
01745 rb_rational_new(VALUE x, VALUE y)
01746 {
01747     return nurat_s_canonicalize_internal(rb_cRational, x, y);
01748 }
01749 
01750 static VALUE nurat_s_convert(int argc, VALUE *argv, VALUE klass);
01751 
01752 VALUE
01753 rb_Rational(VALUE x, VALUE y)
01754 {
01755     VALUE a[2];
01756     a[0] = x;
01757     a[1] = y;
01758     return nurat_s_convert(2, a, rb_cRational);
01759 }
01760 
01761 #define id_numerator rb_intern("numerator")
01762 #define f_numerator(x) rb_funcall((x), id_numerator, 0)
01763 
01764 #define id_denominator rb_intern("denominator")
01765 #define f_denominator(x) rb_funcall((x), id_denominator, 0)
01766 
01767 #define id_to_r rb_intern("to_r")
01768 #define f_to_r(x) rb_funcall((x), id_to_r, 0)
01769 
01770 /*
01771  * call-seq:
01772  *    num.numerator  ->  integer
01773  *
01774  * Returns the numerator.
01775  */
01776 static VALUE
01777 numeric_numerator(VALUE self)
01778 {
01779     return f_numerator(f_to_r(self));
01780 }
01781 
01782 /*
01783  * call-seq:
01784  *    num.denominator  ->  integer
01785  *
01786  * Returns the denominator (always positive).
01787  */
01788 static VALUE
01789 numeric_denominator(VALUE self)
01790 {
01791     return f_denominator(f_to_r(self));
01792 }
01793 
01794 /*
01795  * call-seq:
01796  *    int.numerator  ->  self
01797  *
01798  * Returns self.
01799  */
01800 static VALUE
01801 integer_numerator(VALUE self)
01802 {
01803     return self;
01804 }
01805 
01806 /*
01807  * call-seq:
01808  *    int.denominator  ->  1
01809  *
01810  * Returns 1.
01811  */
01812 static VALUE
01813 integer_denominator(VALUE self)
01814 {
01815     return INT2FIX(1);
01816 }
01817 
01818 /*
01819  * call-seq:
01820  *    flo.numerator  ->  integer
01821  *
01822  * Returns the numerator.  The result is machine dependent.
01823  *
01824  *    n = 0.3.numerator    #=> 5404319552844595
01825  *    d = 0.3.denominator  #=> 18014398509481984
01826  *    n.fdiv(d)            #=> 0.3
01827  */
01828 static VALUE
01829 float_numerator(VALUE self)
01830 {
01831     double d = RFLOAT_VALUE(self);
01832     if (isinf(d) || isnan(d))
01833         return self;
01834     return rb_call_super(0, 0);
01835 }
01836 
01837 /*
01838  * call-seq:
01839  *    flo.denominator  ->  integer
01840  *
01841  * Returns the denominator (always positive).  The result is machine
01842  * dependent.
01843  *
01844  * See numerator.
01845  */
01846 static VALUE
01847 float_denominator(VALUE self)
01848 {
01849     double d = RFLOAT_VALUE(self);
01850     if (isinf(d) || isnan(d))
01851         return INT2FIX(1);
01852     return rb_call_super(0, 0);
01853 }
01854 
01855 /*
01856  * call-seq:
01857  *    nil.to_r  ->  (0/1)
01858  *
01859  * Returns zero as a rational.
01860  */
01861 static VALUE
01862 nilclass_to_r(VALUE self)
01863 {
01864     return rb_rational_new1(INT2FIX(0));
01865 }
01866 
01867 /*
01868  * call-seq:
01869  *    nil.rationalize([eps])  ->  (0/1)
01870  *
01871  * Returns zero as a rational.  The optional argument eps is always
01872  * ignored.
01873  */
01874 static VALUE
01875 nilclass_rationalize(int argc, VALUE *argv, VALUE self)
01876 {
01877     rb_scan_args(argc, argv, "01", NULL);
01878     return nilclass_to_r(self);
01879 }
01880 
01881 /*
01882  * call-seq:
01883  *    int.to_r  ->  rational
01884  *
01885  * Returns the value as a rational.
01886  *
01887  *    1.to_r        #=> (1/1)
01888  *    (1<<64).to_r  #=> (18446744073709551616/1)
01889  */
01890 static VALUE
01891 integer_to_r(VALUE self)
01892 {
01893     return rb_rational_new1(self);
01894 }
01895 
01896 /*
01897  * call-seq:
01898  *    int.rationalize([eps])  ->  rational
01899  *
01900  * Returns the value as a rational.  The optional argument eps is
01901  * always ignored.
01902  */
01903 static VALUE
01904 integer_rationalize(int argc, VALUE *argv, VALUE self)
01905 {
01906     rb_scan_args(argc, argv, "01", NULL);
01907     return integer_to_r(self);
01908 }
01909 
01910 static void
01911 float_decode_internal(VALUE self, VALUE *rf, VALUE *rn)
01912 {
01913     double f;
01914     int n;
01915 
01916     f = frexp(RFLOAT_VALUE(self), &n);
01917     f = ldexp(f, DBL_MANT_DIG);
01918     n -= DBL_MANT_DIG;
01919     *rf = rb_dbl2big(f);
01920     *rn = INT2FIX(n);
01921 }
01922 
01923 #if 0
01924 static VALUE
01925 float_decode(VALUE self)
01926 {
01927     VALUE f, n;
01928 
01929     float_decode_internal(self, &f, &n);
01930     return rb_assoc_new(f, n);
01931 }
01932 #endif
01933 
01934 #define id_lshift rb_intern("<<")
01935 #define f_lshift(x,n) rb_funcall((x), id_lshift, 1, (n))
01936 
01937 /*
01938  * call-seq:
01939  *    flt.to_r  ->  rational
01940  *
01941  * Returns the value as a rational.
01942  *
01943  * NOTE: 0.3.to_r isn't the same as '0.3'.to_r.  The latter is
01944  * equivalent to '3/10'.to_r, but the former isn't so.
01945  *
01946  *    2.0.to_r    #=> (2/1)
01947  *    2.5.to_r    #=> (5/2)
01948  *    -0.75.to_r  #=> (-3/4)
01949  *    0.0.to_r    #=> (0/1)
01950  *
01951  * See rationalize.
01952  */
01953 static VALUE
01954 float_to_r(VALUE self)
01955 {
01956     VALUE f, n;
01957 
01958     float_decode_internal(self, &f, &n);
01959 #if FLT_RADIX == 2
01960     {
01961         long ln = FIX2LONG(n);
01962 
01963         if (ln == 0)
01964             return f_to_r(f);
01965         if (ln > 0)
01966             return f_to_r(f_lshift(f, n));
01967         ln = -ln;
01968         return rb_rational_new2(f, f_lshift(ONE, INT2FIX(ln)));
01969     }
01970 #else
01971     return f_to_r(f_mul(f, f_expt(INT2FIX(FLT_RADIX), n)));
01972 #endif
01973 }
01974 
01975 /*
01976  * call-seq:
01977  *    flt.rationalize([eps])  ->  rational
01978  *
01979  * Returns a simpler approximation of the value (flt-|eps| <= result
01980  * <= flt+|eps|).  if the optional eps is not given, it will be chosen
01981  * automatically.
01982  *
01983  *    0.3.rationalize          #=> (3/10)
01984  *    1.333.rationalize        #=> (1333/1000)
01985  *    1.333.rationalize(0.01)  #=> (4/3)
01986  *
01987  * See to_r.
01988  */
01989 static VALUE
01990 float_rationalize(int argc, VALUE *argv, VALUE self)
01991 {
01992     VALUE e, a, b, p, q;
01993 
01994     if (f_negative_p(self))
01995         return f_negate(float_rationalize(argc, argv, f_abs(self)));
01996 
01997     rb_scan_args(argc, argv, "01", &e);
01998 
01999     if (argc != 0) {
02000         e = f_abs(e);
02001         a = f_sub(self, e);
02002         b = f_add(self, e);
02003     }
02004     else {
02005         VALUE f, n;
02006 
02007         float_decode_internal(self, &f, &n);
02008         if (f_zero_p(f) || f_positive_p(n))
02009             return rb_rational_new1(f_lshift(f, n));
02010 
02011 #if FLT_RADIX == 2
02012         {
02013             VALUE two_times_f, den;
02014 
02015             two_times_f = f_mul(TWO, f);
02016             den = f_lshift(ONE, f_sub(ONE, n));
02017 
02018             a = rb_rational_new2(f_sub(two_times_f, ONE), den);
02019             b = rb_rational_new2(f_add(two_times_f, ONE), den);
02020         }
02021 #else
02022         {
02023             VALUE radix_times_f, den;
02024 
02025             radix_times_f = f_mul(INT2FIX(FLT_RADIX), f);
02026             den = f_expt(INT2FIX(FLT_RADIX), f_sub(ONE, n));
02027 
02028             a = rb_rational_new2(f_sub(radix_times_f, INT2FIX(FLT_RADIX - 1)), den);
02029             b = rb_rational_new2(f_add(radix_times_f, INT2FIX(FLT_RADIX - 1)), den);
02030         }
02031 #endif
02032     }
02033 
02034     if (f_eqeq_p(a, b))
02035         return f_to_r(self);
02036 
02037     nurat_rationalize_internal(a, b, &p, &q);
02038     return rb_rational_new2(p, q);
02039 }
02040 
02041 #include <ctype.h>
02042 
02043 inline static int
02044 issign(int c)
02045 {
02046     return (c == '-' || c == '+');
02047 }
02048 
02049 static int
02050 read_sign(const char **s)
02051 {
02052     int sign = '?';
02053 
02054     if (issign(**s)) {
02055         sign = **s;
02056         (*s)++;
02057     }
02058     return sign;
02059 }
02060 
02061 inline static int
02062 isdecimal(int c)
02063 {
02064     return isdigit((unsigned char)c);
02065 }
02066 
02067 static int
02068 read_digits(const char **s, int strict,
02069             VALUE *num, int *count)
02070 {
02071     char *b, *bb;
02072     int us = 1, ret = 1;
02073 
02074     if (!isdecimal(**s)) {
02075         *num = ZERO;
02076         return 0;
02077     }
02078 
02079     bb = b = ALLOCA_N(char, strlen(*s) + 1);
02080 
02081     while (isdecimal(**s) || **s == '_') {
02082         if (**s == '_') {
02083             if (strict) {
02084                 if (us) {
02085                     ret = 0;
02086                     goto conv;
02087                 }
02088             }
02089             us = 1;
02090         }
02091         else {
02092             if (count)
02093                 (*count)++;
02094             *b++ = **s;
02095             us = 0;
02096         }
02097         (*s)++;
02098     }
02099     if (us)
02100         do {
02101             (*s)--;
02102         } while (**s == '_');
02103   conv:
02104     *b = '\0';
02105     *num = rb_cstr_to_inum(bb, 10, 0);
02106     return ret;
02107 }
02108 
02109 inline static int
02110 islettere(int c)
02111 {
02112     return (c == 'e' || c == 'E');
02113 }
02114 
02115 static int
02116 read_num(const char **s, int numsign, int strict,
02117          VALUE *num)
02118 {
02119     VALUE ip, fp, exp;
02120 
02121     *num = rb_rational_new2(ZERO, ONE);
02122     exp = Qnil;
02123 
02124     if (**s != '.') {
02125         if (!read_digits(s, strict, &ip, NULL))
02126             return 0;
02127         *num = rb_rational_new2(ip, ONE);
02128     }
02129 
02130     if (**s == '.') {
02131         int count = 0;
02132 
02133         (*s)++;
02134         if (!read_digits(s, strict, &fp, &count))
02135             return 0;
02136         {
02137             VALUE l = f_expt10(INT2NUM(count));
02138             *num = f_mul(*num, l);
02139             *num = f_add(*num, fp);
02140             *num = f_div(*num, l);
02141         }
02142     }
02143 
02144     if (islettere(**s)) {
02145         int expsign;
02146 
02147         (*s)++;
02148         expsign = read_sign(s);
02149         if (!read_digits(s, strict, &exp, NULL))
02150             return 0;
02151         if (expsign == '-')
02152             exp = f_negate(exp);
02153     }
02154 
02155     if (numsign == '-')
02156         *num = f_negate(*num);
02157     if (!NIL_P(exp)) {
02158         VALUE l = f_expt10(exp);
02159         *num = f_mul(*num, l);
02160     }
02161     return 1;
02162 }
02163 
02164 inline static int
02165 read_den(const char **s, int strict,
02166          VALUE *num)
02167 {
02168     if (!read_digits(s, strict, num, NULL))
02169         return 0;
02170     return 1;
02171 }
02172 
02173 static int
02174 read_rat_nos(const char **s, int sign, int strict,
02175              VALUE *num)
02176 {
02177     VALUE den;
02178 
02179     if (!read_num(s, sign, strict, num))
02180         return 0;
02181     if (**s == '/') {
02182         (*s)++;
02183         if (!read_den(s, strict, &den))
02184             return 0;
02185         if (!(FIXNUM_P(den) && FIX2LONG(den) == 1))
02186             *num = f_div(*num, den);
02187     }
02188     return 1;
02189 }
02190 
02191 static int
02192 read_rat(const char **s, int strict,
02193          VALUE *num)
02194 {
02195     int sign;
02196 
02197     sign = read_sign(s);
02198     if (!read_rat_nos(s, sign, strict, num))
02199         return 0;
02200     return 1;
02201 }
02202 
02203 inline static void
02204 skip_ws(const char **s)
02205 {
02206     while (isspace((unsigned char)**s))
02207         (*s)++;
02208 }
02209 
02210 static int
02211 parse_rat(const char *s, int strict,
02212           VALUE *num)
02213 {
02214     skip_ws(&s);
02215     if (!read_rat(&s, strict, num))
02216         return 0;
02217     skip_ws(&s);
02218 
02219     if (strict)
02220         if (*s != '\0')
02221             return 0;
02222     return 1;
02223 }
02224 
02225 static VALUE
02226 string_to_r_strict(VALUE self)
02227 {
02228     char *s;
02229     VALUE num;
02230 
02231     rb_must_asciicompat(self);
02232 
02233     s = RSTRING_PTR(self);
02234 
02235     if (!s || memchr(s, '\0', RSTRING_LEN(self)))
02236         rb_raise(rb_eArgError, "string contains null byte");
02237 
02238     if (s && s[RSTRING_LEN(self)]) {
02239         rb_str_modify(self);
02240         s = RSTRING_PTR(self);
02241         s[RSTRING_LEN(self)] = '\0';
02242     }
02243 
02244     if (!s)
02245         s = (char *)"";
02246 
02247     if (!parse_rat(s, 1, &num)) {
02248         VALUE ins = f_inspect(self);
02249         rb_raise(rb_eArgError, "invalid value for convert(): %s",
02250                  StringValuePtr(ins));
02251     }
02252 
02253     if (RB_TYPE_P(num, T_FLOAT))
02254         rb_raise(rb_eFloatDomainError, "Infinity");
02255     return num;
02256 }
02257 
02258 /*
02259  * call-seq:
02260  *    str.to_r  ->  rational
02261  *
02262  * Returns a rational which denotes the string form.  The parser
02263  * ignores leading whitespaces and trailing garbage.  Any digit
02264  * sequences can be separated by an underscore.  Returns zero for null
02265  * or garbage string.
02266  *
02267  * NOTE: '0.3'.to_r isn't the same as 0.3.to_r.  The former is
02268  * equivalent to '3/10'.to_r, but the latter isn't so.
02269  *
02270  *    '  2  '.to_r       #=> (2/1)
02271  *    '300/2'.to_r       #=> (150/1)
02272  *    '-9.2'.to_r        #=> (-46/5)
02273  *    '-9.2e2'.to_r      #=> (-920/1)
02274  *    '1_234_567'.to_r   #=> (1234567/1)
02275  *    '21 june 09'.to_r  #=> (21/1)
02276  *    '21/06/09'.to_r    #=> (7/2)
02277  *    'bwv 1079'.to_r    #=> (0/1)
02278  *
02279  * See Kernel.Rational.
02280  */
02281 static VALUE
02282 string_to_r(VALUE self)
02283 {
02284     char *s;
02285     VALUE num;
02286 
02287     rb_must_asciicompat(self);
02288 
02289     s = RSTRING_PTR(self);
02290 
02291     if (s && s[RSTRING_LEN(self)]) {
02292         rb_str_modify(self);
02293         s = RSTRING_PTR(self);
02294         s[RSTRING_LEN(self)] = '\0';
02295     }
02296 
02297     if (!s)
02298         s = (char *)"";
02299 
02300     (void)parse_rat(s, 0, &num);
02301 
02302     if (RB_TYPE_P(num, T_FLOAT))
02303         rb_raise(rb_eFloatDomainError, "Infinity");
02304     return num;
02305 }
02306 
02307 VALUE
02308 rb_cstr_to_rat(const char *s, int strict) /* for complex's internal */
02309 {
02310     VALUE num;
02311 
02312     (void)parse_rat(s, strict, &num);
02313 
02314     if (RB_TYPE_P(num, T_FLOAT))
02315         rb_raise(rb_eFloatDomainError, "Infinity");
02316     return num;
02317 }
02318 
02319 static VALUE
02320 nurat_s_convert(int argc, VALUE *argv, VALUE klass)
02321 {
02322     VALUE a1, a2, backref;
02323 
02324     rb_scan_args(argc, argv, "11", &a1, &a2);
02325 
02326     if (NIL_P(a1) || (argc == 2 && NIL_P(a2)))
02327         rb_raise(rb_eTypeError, "can't convert nil into Rational");
02328 
02329     switch (TYPE(a1)) {
02330       case T_COMPLEX:
02331         if (k_exact_zero_p(RCOMPLEX(a1)->imag))
02332             a1 = RCOMPLEX(a1)->real;
02333     }
02334 
02335     switch (TYPE(a2)) {
02336       case T_COMPLEX:
02337         if (k_exact_zero_p(RCOMPLEX(a2)->imag))
02338             a2 = RCOMPLEX(a2)->real;
02339     }
02340 
02341     backref = rb_backref_get();
02342     rb_match_busy(backref);
02343 
02344     switch (TYPE(a1)) {
02345       case T_FIXNUM:
02346       case T_BIGNUM:
02347         break;
02348       case T_FLOAT:
02349         a1 = f_to_r(a1);
02350         break;
02351       case T_STRING:
02352         a1 = string_to_r_strict(a1);
02353         break;
02354     }
02355 
02356     switch (TYPE(a2)) {
02357       case T_FIXNUM:
02358       case T_BIGNUM:
02359         break;
02360       case T_FLOAT:
02361         a2 = f_to_r(a2);
02362         break;
02363       case T_STRING:
02364         a2 = string_to_r_strict(a2);
02365         break;
02366     }
02367 
02368     rb_backref_set(backref);
02369 
02370     switch (TYPE(a1)) {
02371       case T_RATIONAL:
02372         if (argc == 1 || (k_exact_one_p(a2)))
02373             return a1;
02374     }
02375 
02376     if (argc == 1) {
02377         if (!(k_numeric_p(a1) && k_integer_p(a1)))
02378             return rb_convert_type(a1, T_RATIONAL, "Rational", "to_r");
02379     }
02380     else {
02381         if ((k_numeric_p(a1) && k_numeric_p(a2)) &&
02382             (!f_integer_p(a1) || !f_integer_p(a2)))
02383             return f_div(a1, a2);
02384     }
02385 
02386     {
02387         VALUE argv2[2];
02388         argv2[0] = a1;
02389         argv2[1] = a2;
02390         return nurat_s_new(argc, argv2, klass);
02391     }
02392 }
02393 
02394 /*
02395  * A rational number can be represented as a paired integer number;
02396  * a/b (b>0).  Where a is numerator and b is denominator.  Integer a
02397  * equals rational a/1 mathematically.
02398  *
02399  * In ruby, you can create rational object with Rational, to_r or
02400  * rationalize method.  The return values will be irreducible.
02401  *
02402  *    Rational(1)      #=> (1/1)
02403  *    Rational(2, 3)   #=> (2/3)
02404  *    Rational(4, -6)  #=> (-2/3)
02405  *    3.to_r           #=> (3/1)
02406  *
02407  * You can also create rational object from floating-point numbers or
02408  * strings.
02409  *
02410  *    Rational(0.3)    #=> (5404319552844595/18014398509481984)
02411  *    Rational('0.3')  #=> (3/10)
02412  *    Rational('2/3')  #=> (2/3)
02413  *
02414  *    0.3.to_r         #=> (5404319552844595/18014398509481984)
02415  *    '0.3'.to_r       #=> (3/10)
02416  *    '2/3'.to_r       #=> (2/3)
02417  *    0.3.rationalize  #=> (3/10)
02418  *
02419  * A rational object is an exact number, which helps you to write
02420  * program without any rounding errors.
02421  *
02422  *    10.times.inject(0){|t,| t + 0.1}              #=> 0.9999999999999999
02423  *    10.times.inject(0){|t,| t + Rational('0.1')}  #=> (1/1)
02424  *
02425  * However, when an expression has inexact factor (numerical value or
02426  * operation), will produce an inexact result.
02427  *
02428  *    Rational(10) / 3   #=> (10/3)
02429  *    Rational(10) / 3.0 #=> 3.3333333333333335
02430  *
02431  *    Rational(-8) ** Rational(1, 3)
02432  *                       #=> (1.0000000000000002+1.7320508075688772i)
02433  */
02434 void
02435 Init_Rational(void)
02436 {
02437     VALUE compat;
02438 #undef rb_intern
02439 #define rb_intern(str) rb_intern_const(str)
02440 
02441     assert(fprintf(stderr, "assert() is now active\n"));
02442 
02443     id_abs = rb_intern("abs");
02444     id_cmp = rb_intern("<=>");
02445     id_convert = rb_intern("convert");
02446     id_eqeq_p = rb_intern("==");
02447     id_expt = rb_intern("**");
02448     id_fdiv = rb_intern("fdiv");
02449     id_floor = rb_intern("floor");
02450     id_idiv = rb_intern("div");
02451     id_inspect = rb_intern("inspect");
02452     id_integer_p = rb_intern("integer?");
02453     id_negate = rb_intern("-@");
02454     id_to_f = rb_intern("to_f");
02455     id_to_i = rb_intern("to_i");
02456     id_to_s = rb_intern("to_s");
02457     id_truncate = rb_intern("truncate");
02458     id_i_num = rb_intern("@numerator");
02459     id_i_den = rb_intern("@denominator");
02460 
02461     rb_cRational = rb_define_class("Rational", rb_cNumeric);
02462 
02463     rb_define_alloc_func(rb_cRational, nurat_s_alloc);
02464     rb_undef_method(CLASS_OF(rb_cRational), "allocate");
02465 
02466 #if 0
02467     rb_define_private_method(CLASS_OF(rb_cRational), "new!", nurat_s_new_bang, -1);
02468     rb_define_private_method(CLASS_OF(rb_cRational), "new", nurat_s_new, -1);
02469 #else
02470     rb_undef_method(CLASS_OF(rb_cRational), "new");
02471 #endif
02472 
02473     rb_define_global_function("Rational", nurat_f_rational, -1);
02474 
02475     rb_define_method(rb_cRational, "numerator", nurat_numerator, 0);
02476     rb_define_method(rb_cRational, "denominator", nurat_denominator, 0);
02477 
02478     rb_define_method(rb_cRational, "+", nurat_add, 1);
02479     rb_define_method(rb_cRational, "-", nurat_sub, 1);
02480     rb_define_method(rb_cRational, "*", nurat_mul, 1);
02481     rb_define_method(rb_cRational, "/", nurat_div, 1);
02482     rb_define_method(rb_cRational, "quo", nurat_div, 1);
02483     rb_define_method(rb_cRational, "fdiv", nurat_fdiv, 1);
02484     rb_define_method(rb_cRational, "**", nurat_expt, 1);
02485 
02486     rb_define_method(rb_cRational, "<=>", nurat_cmp, 1);
02487     rb_define_method(rb_cRational, "==", nurat_eqeq_p, 1);
02488     rb_define_method(rb_cRational, "coerce", nurat_coerce, 1);
02489 
02490 #if 0 /* NUBY */
02491     rb_define_method(rb_cRational, "//", nurat_idiv, 1);
02492 #endif
02493 
02494 #if 0
02495     rb_define_method(rb_cRational, "quot", nurat_quot, 1);
02496     rb_define_method(rb_cRational, "quotrem", nurat_quotrem, 1);
02497 #endif
02498 
02499 #if 0
02500     rb_define_method(rb_cRational, "rational?", nurat_true, 0);
02501     rb_define_method(rb_cRational, "exact?", nurat_true, 0);
02502 #endif
02503 
02504     rb_define_method(rb_cRational, "floor", nurat_floor_n, -1);
02505     rb_define_method(rb_cRational, "ceil", nurat_ceil_n, -1);
02506     rb_define_method(rb_cRational, "truncate", nurat_truncate_n, -1);
02507     rb_define_method(rb_cRational, "round", nurat_round_n, -1);
02508 
02509     rb_define_method(rb_cRational, "to_i", nurat_truncate, 0);
02510     rb_define_method(rb_cRational, "to_f", nurat_to_f, 0);
02511     rb_define_method(rb_cRational, "to_r", nurat_to_r, 0);
02512     rb_define_method(rb_cRational, "rationalize", nurat_rationalize, -1);
02513 
02514     rb_define_method(rb_cRational, "hash", nurat_hash, 0);
02515 
02516     rb_define_method(rb_cRational, "to_s", nurat_to_s, 0);
02517     rb_define_method(rb_cRational, "inspect", nurat_inspect, 0);
02518 
02519     rb_define_private_method(rb_cRational, "marshal_dump", nurat_marshal_dump, 0);
02520     compat = rb_define_class_under(rb_cRational, "compatible", rb_cObject);
02521     rb_define_private_method(compat, "marshal_load", nurat_marshal_load, 1);
02522     rb_marshal_define_compat(rb_cRational, compat, nurat_dumper, nurat_loader);
02523 
02524     /* --- */
02525 
02526     rb_define_method(rb_cInteger, "gcd", rb_gcd, 1);
02527     rb_define_method(rb_cInteger, "lcm", rb_lcm, 1);
02528     rb_define_method(rb_cInteger, "gcdlcm", rb_gcdlcm, 1);
02529 
02530     rb_define_method(rb_cNumeric, "numerator", numeric_numerator, 0);
02531     rb_define_method(rb_cNumeric, "denominator", numeric_denominator, 0);
02532 
02533     rb_define_method(rb_cInteger, "numerator", integer_numerator, 0);
02534     rb_define_method(rb_cInteger, "denominator", integer_denominator, 0);
02535 
02536     rb_define_method(rb_cFloat, "numerator", float_numerator, 0);
02537     rb_define_method(rb_cFloat, "denominator", float_denominator, 0);
02538 
02539     rb_define_method(rb_cNilClass, "to_r", nilclass_to_r, 0);
02540     rb_define_method(rb_cNilClass, "rationalize", nilclass_rationalize, -1);
02541     rb_define_method(rb_cInteger, "to_r", integer_to_r, 0);
02542     rb_define_method(rb_cInteger, "rationalize", integer_rationalize, -1);
02543     rb_define_method(rb_cFloat, "to_r", float_to_r, 0);
02544     rb_define_method(rb_cFloat, "rationalize", float_rationalize, -1);
02545 
02546     rb_define_method(rb_cString, "to_r", string_to_r, 0);
02547 
02548     rb_define_private_method(CLASS_OF(rb_cRational), "convert", nurat_s_convert, -1);
02549 }
02550 
02551 /*
02552 Local variables:
02553 c-file-style: "ruby"
02554 End:
02555 */
02556