Ruby  2.0.0p247(2013-06-27revision41674)
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     s = (*func)(s);
01283 
01284     s = f_div(f_rational_new_bang1(CLASS_OF(self), s), b);
01285 
01286     if (f_lt_p(n, ONE))
01287         s = f_to_i(s);
01288 
01289     return s;
01290 }
01291 
01292 /*
01293  * call-seq:
01294  *    rat.floor               ->  integer
01295  *    rat.floor(precision=0)  ->  rational
01296  *
01297  * Returns the truncated value (toward negative infinity).
01298  *
01299  *    Rational(3).floor      #=> 3
01300  *    Rational(2, 3).floor   #=> 0
01301  *    Rational(-3, 2).floor  #=> -1
01302  *
01303  *           decimal      -  1  2  3 . 4  5  6
01304  *                          ^  ^  ^  ^   ^  ^
01305  *          precision      -3 -2 -1  0  +1 +2
01306  *
01307  *    '%f' % Rational('-123.456').floor(+1)  #=> "-123.500000"
01308  *    '%f' % Rational('-123.456').floor(-1)  #=> "-130.000000"
01309  */
01310 static VALUE
01311 nurat_floor_n(int argc, VALUE *argv, VALUE self)
01312 {
01313     return f_round_common(argc, argv, self, nurat_floor);
01314 }
01315 
01316 /*
01317  * call-seq:
01318  *    rat.ceil               ->  integer
01319  *    rat.ceil(precision=0)  ->  rational
01320  *
01321  * Returns the truncated value (toward positive infinity).
01322  *
01323  *    Rational(3).ceil      #=> 3
01324  *    Rational(2, 3).ceil   #=> 1
01325  *    Rational(-3, 2).ceil  #=> -1
01326  *
01327  *           decimal      -  1  2  3 . 4  5  6
01328  *                          ^  ^  ^  ^   ^  ^
01329  *          precision      -3 -2 -1  0  +1 +2
01330  *
01331  *    '%f' % Rational('-123.456').ceil(+1)  #=> "-123.400000"
01332  *    '%f' % Rational('-123.456').ceil(-1)  #=> "-120.000000"
01333  */
01334 static VALUE
01335 nurat_ceil_n(int argc, VALUE *argv, VALUE self)
01336 {
01337     return f_round_common(argc, argv, self, nurat_ceil);
01338 }
01339 
01340 /*
01341  * call-seq:
01342  *    rat.truncate               ->  integer
01343  *    rat.truncate(precision=0)  ->  rational
01344  *
01345  * Returns the truncated value (toward zero).
01346  *
01347  *    Rational(3).truncate      #=> 3
01348  *    Rational(2, 3).truncate   #=> 0
01349  *    Rational(-3, 2).truncate  #=> -1
01350  *
01351  *           decimal      -  1  2  3 . 4  5  6
01352  *                          ^  ^  ^  ^   ^  ^
01353  *          precision      -3 -2 -1  0  +1 +2
01354  *
01355  *    '%f' % Rational('-123.456').truncate(+1)  #=>  "-123.400000"
01356  *    '%f' % Rational('-123.456').truncate(-1)  #=>  "-120.000000"
01357  */
01358 static VALUE
01359 nurat_truncate_n(int argc, VALUE *argv, VALUE self)
01360 {
01361     return f_round_common(argc, argv, self, nurat_truncate);
01362 }
01363 
01364 /*
01365  * call-seq:
01366  *    rat.round               ->  integer
01367  *    rat.round(precision=0)  ->  rational
01368  *
01369  * Returns the truncated value (toward the nearest integer;
01370  * 0.5 => 1; -0.5 => -1).
01371  *
01372  *    Rational(3).round      #=> 3
01373  *    Rational(2, 3).round   #=> 1
01374  *    Rational(-3, 2).round  #=> -2
01375  *
01376  *           decimal      -  1  2  3 . 4  5  6
01377  *                          ^  ^  ^  ^   ^  ^
01378  *          precision      -3 -2 -1  0  +1 +2
01379  *
01380  *    '%f' % Rational('-123.456').round(+1)  #=> "-123.500000"
01381  *    '%f' % Rational('-123.456').round(-1)  #=> "-120.000000"
01382  */
01383 static VALUE
01384 nurat_round_n(int argc, VALUE *argv, VALUE self)
01385 {
01386     return f_round_common(argc, argv, self, nurat_round);
01387 }
01388 
01389 /*
01390  * call-seq:
01391  *    rat.to_f  ->  float
01392  *
01393  * Return the value as a float.
01394  *
01395  *    Rational(2).to_f      #=> 2.0
01396  *    Rational(9, 4).to_f   #=> 2.25
01397  *    Rational(-3, 4).to_f  #=> -0.75
01398  *    Rational(20, 3).to_f  #=> 6.666666666666667
01399  */
01400 static VALUE
01401 nurat_to_f(VALUE self)
01402 {
01403     get_dat1(self);
01404     return f_fdiv(dat->num, dat->den);
01405 }
01406 
01407 /*
01408  * call-seq:
01409  *    rat.to_r  ->  self
01410  *
01411  * Returns self.
01412  *
01413  *    Rational(2).to_r      #=> (2/1)
01414  *    Rational(-8, 6).to_r  #=> (-4/3)
01415  */
01416 static VALUE
01417 nurat_to_r(VALUE self)
01418 {
01419     return self;
01420 }
01421 
01422 #define id_ceil rb_intern("ceil")
01423 #define f_ceil(x) rb_funcall((x), id_ceil, 0)
01424 
01425 #define id_quo rb_intern("quo")
01426 #define f_quo(x,y) rb_funcall((x), id_quo, 1, (y))
01427 
01428 #define f_reciprocal(x) f_quo(ONE, (x))
01429 
01430 /*
01431   The algorithm here is the method described in CLISP.  Bruno Haible has
01432   graciously given permission to use this algorithm.  He says, "You can use
01433   it, if you present the following explanation of the algorithm."
01434 
01435   Algorithm (recursively presented):
01436     If x is a rational number, return x.
01437     If x = 0.0, return 0.
01438     If x < 0.0, return (- (rationalize (- x))).
01439     If x > 0.0:
01440       Call (integer-decode-float x). It returns a m,e,s=1 (mantissa,
01441       exponent, sign).
01442       If m = 0 or e >= 0: return x = m*2^e.
01443       Search a rational number between a = (m-1/2)*2^e and b = (m+1/2)*2^e
01444       with smallest possible numerator and denominator.
01445       Note 1: If m is a power of 2, we ought to take a = (m-1/4)*2^e.
01446         But in this case the result will be x itself anyway, regardless of
01447         the choice of a. Therefore we can simply ignore this case.
01448       Note 2: At first, we need to consider the closed interval [a,b].
01449         but since a and b have the denominator 2^(|e|+1) whereas x itself
01450         has a denominator <= 2^|e|, we can restrict the search to the open
01451         interval (a,b).
01452       So, for given a and b (0 < a < b) we are searching a rational number
01453       y with a <= y <= b.
01454       Recursive algorithm fraction_between(a,b):
01455         c := (ceiling a)
01456         if c < b
01457           then return c       ; because a <= c < b, c integer
01458           else
01459             ; a is not integer (otherwise we would have had c = a < b)
01460             k := c-1          ; k = floor(a), k < a < b <= k+1
01461             return y = k + 1/fraction_between(1/(b-k), 1/(a-k))
01462                               ; note 1 <= 1/(b-k) < 1/(a-k)
01463 
01464   You can see that we are actually computing a continued fraction expansion.
01465 
01466   Algorithm (iterative):
01467     If x is rational, return x.
01468     Call (integer-decode-float x). It returns a m,e,s (mantissa,
01469       exponent, sign).
01470     If m = 0 or e >= 0, return m*2^e*s. (This includes the case x = 0.0.)
01471     Create rational numbers a := (2*m-1)*2^(e-1) and b := (2*m+1)*2^(e-1)
01472     (positive and already in lowest terms because the denominator is a
01473     power of two and the numerator is odd).
01474     Start a continued fraction expansion
01475       p[-1] := 0, p[0] := 1, q[-1] := 1, q[0] := 0, i := 0.
01476     Loop
01477       c := (ceiling a)
01478       if c >= b
01479         then k := c-1, partial_quotient(k), (a,b) := (1/(b-k),1/(a-k)),
01480              goto Loop
01481     finally partial_quotient(c).
01482     Here partial_quotient(c) denotes the iteration
01483       i := i+1, p[i] := c*p[i-1]+p[i-2], q[i] := c*q[i-1]+q[i-2].
01484     At the end, return s * (p[i]/q[i]).
01485     This rational number is already in lowest terms because
01486     p[i]*q[i-1]-p[i-1]*q[i] = (-1)^i.
01487 */
01488 
01489 static void
01490 nurat_rationalize_internal(VALUE a, VALUE b, VALUE *p, VALUE *q)
01491 {
01492     VALUE c, k, t, p0, p1, p2, q0, q1, q2;
01493 
01494     p0 = ZERO;
01495     p1 = ONE;
01496     q0 = ONE;
01497     q1 = ZERO;
01498 
01499     while (1) {
01500         c = f_ceil(a);
01501         if (f_lt_p(c, b))
01502             break;
01503         k = f_sub(c, ONE);
01504         p2 = f_add(f_mul(k, p1), p0);
01505         q2 = f_add(f_mul(k, q1), q0);
01506         t = f_reciprocal(f_sub(b, k));
01507         b = f_reciprocal(f_sub(a, k));
01508         a = t;
01509         p0 = p1;
01510         q0 = q1;
01511         p1 = p2;
01512         q1 = q2;
01513     }
01514     *p = f_add(f_mul(c, p1), p0);
01515     *q = f_add(f_mul(c, q1), q0);
01516 }
01517 
01518 /*
01519  * call-seq:
01520  *    rat.rationalize       ->  self
01521  *    rat.rationalize(eps)  ->  rational
01522  *
01523  * Returns a simpler approximation of the value if the optional
01524  * argument eps is given (rat-|eps| <= result <= rat+|eps|), self
01525  * otherwise.
01526  *
01527  *    r = Rational(5033165, 16777216)
01528  *    r.rationalize                    #=> (5033165/16777216)
01529  *    r.rationalize(Rational('0.01'))  #=> (3/10)
01530  *    r.rationalize(Rational('0.1'))   #=> (1/3)
01531  */
01532 static VALUE
01533 nurat_rationalize(int argc, VALUE *argv, VALUE self)
01534 {
01535     VALUE e, a, b, p, q;
01536 
01537     if (argc == 0)
01538         return self;
01539 
01540     if (f_negative_p(self))
01541         return f_negate(nurat_rationalize(argc, argv, f_abs(self)));
01542 
01543     rb_scan_args(argc, argv, "01", &e);
01544     e = f_abs(e);
01545     a = f_sub(self, e);
01546     b = f_add(self, e);
01547 
01548     if (f_eqeq_p(a, b))
01549         return self;
01550 
01551     nurat_rationalize_internal(a, b, &p, &q);
01552     return f_rational_new2(CLASS_OF(self), p, q);
01553 }
01554 
01555 /* :nodoc: */
01556 static VALUE
01557 nurat_hash(VALUE self)
01558 {
01559     st_index_t v, h[2];
01560     VALUE n;
01561 
01562     get_dat1(self);
01563     n = rb_hash(dat->num);
01564     h[0] = NUM2LONG(n);
01565     n = rb_hash(dat->den);
01566     h[1] = NUM2LONG(n);
01567     v = rb_memhash(h, sizeof(h));
01568     return LONG2FIX(v);
01569 }
01570 
01571 static VALUE
01572 f_format(VALUE self, VALUE (*func)(VALUE))
01573 {
01574     VALUE s;
01575     get_dat1(self);
01576 
01577     s = (*func)(dat->num);
01578     rb_str_cat2(s, "/");
01579     rb_str_concat(s, (*func)(dat->den));
01580 
01581     return s;
01582 }
01583 
01584 /*
01585  * call-seq:
01586  *    rat.to_s  ->  string
01587  *
01588  * Returns the value as a string.
01589  *
01590  *    Rational(2).to_s      #=> "2/1"
01591  *    Rational(-8, 6).to_s  #=> "-4/3"
01592  *    Rational('1/2').to_s  #=> "1/2"
01593  */
01594 static VALUE
01595 nurat_to_s(VALUE self)
01596 {
01597     return f_format(self, f_to_s);
01598 }
01599 
01600 /*
01601  * call-seq:
01602  *    rat.inspect  ->  string
01603  *
01604  * Returns the value as a string for inspection.
01605  *
01606  *    Rational(2).inspect      #=> "(2/1)"
01607  *    Rational(-8, 6).inspect  #=> "(-4/3)"
01608  *    Rational('1/2').inspect  #=> "(1/2)"
01609  */
01610 static VALUE
01611 nurat_inspect(VALUE self)
01612 {
01613     VALUE s;
01614 
01615     s = rb_usascii_str_new2("(");
01616     rb_str_concat(s, f_format(self, f_inspect));
01617     rb_str_cat2(s, ")");
01618 
01619     return s;
01620 }
01621 
01622 /* :nodoc: */
01623 static VALUE
01624 nurat_dumper(VALUE self)
01625 {
01626     return self;
01627 }
01628 
01629 /* :nodoc: */
01630 static VALUE
01631 nurat_loader(VALUE self, VALUE a)
01632 {
01633     get_dat1(self);
01634 
01635     dat->num = rb_ivar_get(a, id_i_num);
01636     dat->den = rb_ivar_get(a, id_i_den);
01637 
01638     return self;
01639 }
01640 
01641 /* :nodoc: */
01642 static VALUE
01643 nurat_marshal_dump(VALUE self)
01644 {
01645     VALUE a;
01646     get_dat1(self);
01647 
01648     a = rb_assoc_new(dat->num, dat->den);
01649     rb_copy_generic_ivar(a, self);
01650     return a;
01651 }
01652 
01653 /* :nodoc: */
01654 static VALUE
01655 nurat_marshal_load(VALUE self, VALUE a)
01656 {
01657     rb_check_frozen(self);
01658     rb_check_trusted(self);
01659 
01660     Check_Type(a, T_ARRAY);
01661     if (RARRAY_LEN(a) != 2)
01662         rb_raise(rb_eArgError, "marshaled rational must have an array whose length is 2 but %ld", RARRAY_LEN(a));
01663     if (f_zero_p(RARRAY_PTR(a)[1]))
01664         rb_raise_zerodiv();
01665 
01666     rb_ivar_set(self, id_i_num, RARRAY_PTR(a)[0]);
01667     rb_ivar_set(self, id_i_den, RARRAY_PTR(a)[1]);
01668 
01669     return self;
01670 }
01671 
01672 /* --- */
01673 
01674 VALUE
01675 rb_rational_reciprocal(VALUE x)
01676 {
01677     get_dat1(x);
01678     return f_rational_new_no_reduce2(CLASS_OF(x), dat->den, dat->num);
01679 }
01680 
01681 /*
01682  * call-seq:
01683  *    int.gcd(int2)  ->  integer
01684  *
01685  * Returns the greatest common divisor (always positive).  0.gcd(x)
01686  * and x.gcd(0) return abs(x).
01687  *
01688  *    2.gcd(2)                    #=> 2
01689  *    3.gcd(-7)                   #=> 1
01690  *    ((1<<31)-1).gcd((1<<61)-1)  #=> 1
01691  */
01692 VALUE
01693 rb_gcd(VALUE self, VALUE other)
01694 {
01695     other = nurat_int_value(other);
01696     return f_gcd(self, other);
01697 }
01698 
01699 /*
01700  * call-seq:
01701  *    int.lcm(int2)  ->  integer
01702  *
01703  * Returns the least common multiple (always positive).  0.lcm(x) and
01704  * x.lcm(0) return zero.
01705  *
01706  *    2.lcm(2)                    #=> 2
01707  *    3.lcm(-7)                   #=> 21
01708  *    ((1<<31)-1).lcm((1<<61)-1)  #=> 4951760154835678088235319297
01709  */
01710 VALUE
01711 rb_lcm(VALUE self, VALUE other)
01712 {
01713     other = nurat_int_value(other);
01714     return f_lcm(self, other);
01715 }
01716 
01717 /*
01718  * call-seq:
01719  *    int.gcdlcm(int2)  ->  array
01720  *
01721  * Returns an array; [int.gcd(int2), int.lcm(int2)].
01722  *
01723  *    2.gcdlcm(2)                    #=> [2, 2]
01724  *    3.gcdlcm(-7)                   #=> [1, 21]
01725  *    ((1<<31)-1).gcdlcm((1<<61)-1)  #=> [1, 4951760154835678088235319297]
01726  */
01727 VALUE
01728 rb_gcdlcm(VALUE self, VALUE other)
01729 {
01730     other = nurat_int_value(other);
01731     return rb_assoc_new(f_gcd(self, other), f_lcm(self, other));
01732 }
01733 
01734 VALUE
01735 rb_rational_raw(VALUE x, VALUE y)
01736 {
01737     return nurat_s_new_internal(rb_cRational, x, y);
01738 }
01739 
01740 VALUE
01741 rb_rational_new(VALUE x, VALUE y)
01742 {
01743     return nurat_s_canonicalize_internal(rb_cRational, x, y);
01744 }
01745 
01746 static VALUE nurat_s_convert(int argc, VALUE *argv, VALUE klass);
01747 
01748 VALUE
01749 rb_Rational(VALUE x, VALUE y)
01750 {
01751     VALUE a[2];
01752     a[0] = x;
01753     a[1] = y;
01754     return nurat_s_convert(2, a, rb_cRational);
01755 }
01756 
01757 #define id_numerator rb_intern("numerator")
01758 #define f_numerator(x) rb_funcall((x), id_numerator, 0)
01759 
01760 #define id_denominator rb_intern("denominator")
01761 #define f_denominator(x) rb_funcall((x), id_denominator, 0)
01762 
01763 #define id_to_r rb_intern("to_r")
01764 #define f_to_r(x) rb_funcall((x), id_to_r, 0)
01765 
01766 /*
01767  * call-seq:
01768  *    num.numerator  ->  integer
01769  *
01770  * Returns the numerator.
01771  */
01772 static VALUE
01773 numeric_numerator(VALUE self)
01774 {
01775     return f_numerator(f_to_r(self));
01776 }
01777 
01778 /*
01779  * call-seq:
01780  *    num.denominator  ->  integer
01781  *
01782  * Returns the denominator (always positive).
01783  */
01784 static VALUE
01785 numeric_denominator(VALUE self)
01786 {
01787     return f_denominator(f_to_r(self));
01788 }
01789 
01790 /*
01791  * call-seq:
01792  *    int.numerator  ->  self
01793  *
01794  * Returns self.
01795  */
01796 static VALUE
01797 integer_numerator(VALUE self)
01798 {
01799     return self;
01800 }
01801 
01802 /*
01803  * call-seq:
01804  *    int.denominator  ->  1
01805  *
01806  * Returns 1.
01807  */
01808 static VALUE
01809 integer_denominator(VALUE self)
01810 {
01811     return INT2FIX(1);
01812 }
01813 
01814 /*
01815  * call-seq:
01816  *    flo.numerator  ->  integer
01817  *
01818  * Returns the numerator.  The result is machine dependent.
01819  *
01820  *    n = 0.3.numerator    #=> 5404319552844595
01821  *    d = 0.3.denominator  #=> 18014398509481984
01822  *    n.fdiv(d)            #=> 0.3
01823  */
01824 static VALUE
01825 float_numerator(VALUE self)
01826 {
01827     double d = RFLOAT_VALUE(self);
01828     if (isinf(d) || isnan(d))
01829         return self;
01830     return rb_call_super(0, 0);
01831 }
01832 
01833 /*
01834  * call-seq:
01835  *    flo.denominator  ->  integer
01836  *
01837  * Returns the denominator (always positive).  The result is machine
01838  * dependent.
01839  *
01840  * See numerator.
01841  */
01842 static VALUE
01843 float_denominator(VALUE self)
01844 {
01845     double d = RFLOAT_VALUE(self);
01846     if (isinf(d) || isnan(d))
01847         return INT2FIX(1);
01848     return rb_call_super(0, 0);
01849 }
01850 
01851 /*
01852  * call-seq:
01853  *    nil.to_r  ->  (0/1)
01854  *
01855  * Returns zero as a rational.
01856  */
01857 static VALUE
01858 nilclass_to_r(VALUE self)
01859 {
01860     return rb_rational_new1(INT2FIX(0));
01861 }
01862 
01863 /*
01864  * call-seq:
01865  *    nil.rationalize([eps])  ->  (0/1)
01866  *
01867  * Returns zero as a rational.  The optional argument eps is always
01868  * ignored.
01869  */
01870 static VALUE
01871 nilclass_rationalize(int argc, VALUE *argv, VALUE self)
01872 {
01873     rb_scan_args(argc, argv, "01", NULL);
01874     return nilclass_to_r(self);
01875 }
01876 
01877 /*
01878  * call-seq:
01879  *    int.to_r  ->  rational
01880  *
01881  * Returns the value as a rational.
01882  *
01883  *    1.to_r        #=> (1/1)
01884  *    (1<<64).to_r  #=> (18446744073709551616/1)
01885  */
01886 static VALUE
01887 integer_to_r(VALUE self)
01888 {
01889     return rb_rational_new1(self);
01890 }
01891 
01892 /*
01893  * call-seq:
01894  *    int.rationalize([eps])  ->  rational
01895  *
01896  * Returns the value as a rational.  The optional argument eps is
01897  * always ignored.
01898  */
01899 static VALUE
01900 integer_rationalize(int argc, VALUE *argv, VALUE self)
01901 {
01902     rb_scan_args(argc, argv, "01", NULL);
01903     return integer_to_r(self);
01904 }
01905 
01906 static void
01907 float_decode_internal(VALUE self, VALUE *rf, VALUE *rn)
01908 {
01909     double f;
01910     int n;
01911 
01912     f = frexp(RFLOAT_VALUE(self), &n);
01913     f = ldexp(f, DBL_MANT_DIG);
01914     n -= DBL_MANT_DIG;
01915     *rf = rb_dbl2big(f);
01916     *rn = INT2FIX(n);
01917 }
01918 
01919 #if 0
01920 static VALUE
01921 float_decode(VALUE self)
01922 {
01923     VALUE f, n;
01924 
01925     float_decode_internal(self, &f, &n);
01926     return rb_assoc_new(f, n);
01927 }
01928 #endif
01929 
01930 #define id_lshift rb_intern("<<")
01931 #define f_lshift(x,n) rb_funcall((x), id_lshift, 1, (n))
01932 
01933 /*
01934  * call-seq:
01935  *    flt.to_r  ->  rational
01936  *
01937  * Returns the value as a rational.
01938  *
01939  * NOTE: 0.3.to_r isn't the same as '0.3'.to_r.  The latter is
01940  * equivalent to '3/10'.to_r, but the former isn't so.
01941  *
01942  *    2.0.to_r    #=> (2/1)
01943  *    2.5.to_r    #=> (5/2)
01944  *    -0.75.to_r  #=> (-3/4)
01945  *    0.0.to_r    #=> (0/1)
01946  *
01947  * See rationalize.
01948  */
01949 static VALUE
01950 float_to_r(VALUE self)
01951 {
01952     VALUE f, n;
01953 
01954     float_decode_internal(self, &f, &n);
01955 #if FLT_RADIX == 2
01956     {
01957         long ln = FIX2LONG(n);
01958 
01959         if (ln == 0)
01960             return f_to_r(f);
01961         if (ln > 0)
01962             return f_to_r(f_lshift(f, n));
01963         ln = -ln;
01964         return rb_rational_new2(f, f_lshift(ONE, INT2FIX(ln)));
01965     }
01966 #else
01967     return f_to_r(f_mul(f, f_expt(INT2FIX(FLT_RADIX), n)));
01968 #endif
01969 }
01970 
01971 /*
01972  * call-seq:
01973  *    flt.rationalize([eps])  ->  rational
01974  *
01975  * Returns a simpler approximation of the value (flt-|eps| <= result
01976  * <= flt+|eps|).  if the optional eps is not given, it will be chosen
01977  * automatically.
01978  *
01979  *    0.3.rationalize          #=> (3/10)
01980  *    1.333.rationalize        #=> (1333/1000)
01981  *    1.333.rationalize(0.01)  #=> (4/3)
01982  *
01983  * See to_r.
01984  */
01985 static VALUE
01986 float_rationalize(int argc, VALUE *argv, VALUE self)
01987 {
01988     VALUE e, a, b, p, q;
01989 
01990     if (f_negative_p(self))
01991         return f_negate(float_rationalize(argc, argv, f_abs(self)));
01992 
01993     rb_scan_args(argc, argv, "01", &e);
01994 
01995     if (argc != 0) {
01996         e = f_abs(e);
01997         a = f_sub(self, e);
01998         b = f_add(self, e);
01999     }
02000     else {
02001         VALUE f, n;
02002 
02003         float_decode_internal(self, &f, &n);
02004         if (f_zero_p(f) || f_positive_p(n))
02005             return rb_rational_new1(f_lshift(f, n));
02006 
02007 #if FLT_RADIX == 2
02008         {
02009             VALUE two_times_f, den;
02010 
02011             two_times_f = f_mul(TWO, f);
02012             den = f_lshift(ONE, f_sub(ONE, n));
02013 
02014             a = rb_rational_new2(f_sub(two_times_f, ONE), den);
02015             b = rb_rational_new2(f_add(two_times_f, ONE), den);
02016         }
02017 #else
02018         {
02019             VALUE radix_times_f, den;
02020 
02021             radix_times_f = f_mul(INT2FIX(FLT_RADIX), f);
02022             den = f_expt(INT2FIX(FLT_RADIX), f_sub(ONE, n));
02023 
02024             a = rb_rational_new2(f_sub(radix_times_f, INT2FIX(FLT_RADIX - 1)), den);
02025             b = rb_rational_new2(f_add(radix_times_f, INT2FIX(FLT_RADIX - 1)), den);
02026         }
02027 #endif
02028     }
02029 
02030     if (f_eqeq_p(a, b))
02031         return f_to_r(self);
02032 
02033     nurat_rationalize_internal(a, b, &p, &q);
02034     return rb_rational_new2(p, q);
02035 }
02036 
02037 #include <ctype.h>
02038 
02039 inline static int
02040 issign(int c)
02041 {
02042     return (c == '-' || c == '+');
02043 }
02044 
02045 static int
02046 read_sign(const char **s)
02047 {
02048     int sign = '?';
02049 
02050     if (issign(**s)) {
02051         sign = **s;
02052         (*s)++;
02053     }
02054     return sign;
02055 }
02056 
02057 inline static int
02058 isdecimal(int c)
02059 {
02060     return isdigit((unsigned char)c);
02061 }
02062 
02063 static int
02064 read_digits(const char **s, int strict,
02065             VALUE *num, int *count)
02066 {
02067     char *b, *bb;
02068     int us = 1, ret = 1;
02069 
02070     if (!isdecimal(**s)) {
02071         *num = ZERO;
02072         return 0;
02073     }
02074 
02075     bb = b = ALLOCA_N(char, strlen(*s) + 1);
02076 
02077     while (isdecimal(**s) || **s == '_') {
02078         if (**s == '_') {
02079             if (strict) {
02080                 if (us) {
02081                     ret = 0;
02082                     goto conv;
02083                 }
02084             }
02085             us = 1;
02086         }
02087         else {
02088             if (count)
02089                 (*count)++;
02090             *b++ = **s;
02091             us = 0;
02092         }
02093         (*s)++;
02094     }
02095     if (us)
02096         do {
02097             (*s)--;
02098         } while (**s == '_');
02099   conv:
02100     *b = '\0';
02101     *num = rb_cstr_to_inum(bb, 10, 0);
02102     return ret;
02103 }
02104 
02105 inline static int
02106 islettere(int c)
02107 {
02108     return (c == 'e' || c == 'E');
02109 }
02110 
02111 static int
02112 read_num(const char **s, int numsign, int strict,
02113          VALUE *num)
02114 {
02115     VALUE ip, fp, exp;
02116 
02117     *num = rb_rational_new2(ZERO, ONE);
02118     exp = Qnil;
02119 
02120     if (**s != '.') {
02121         if (!read_digits(s, strict, &ip, NULL))
02122             return 0;
02123         *num = rb_rational_new2(ip, ONE);
02124     }
02125 
02126     if (**s == '.') {
02127         int count = 0;
02128 
02129         (*s)++;
02130         if (!read_digits(s, strict, &fp, &count))
02131             return 0;
02132         {
02133             VALUE l = f_expt10(INT2NUM(count));
02134             *num = f_mul(*num, l);
02135             *num = f_add(*num, fp);
02136             *num = f_div(*num, l);
02137         }
02138     }
02139 
02140     if (islettere(**s)) {
02141         int expsign;
02142 
02143         (*s)++;
02144         expsign = read_sign(s);
02145         if (!read_digits(s, strict, &exp, NULL))
02146             return 0;
02147         if (expsign == '-')
02148             exp = f_negate(exp);
02149     }
02150 
02151     if (numsign == '-')
02152         *num = f_negate(*num);
02153     if (!NIL_P(exp)) {
02154         VALUE l = f_expt10(exp);
02155         *num = f_mul(*num, l);
02156     }
02157     return 1;
02158 }
02159 
02160 inline static int
02161 read_den(const char **s, int strict,
02162          VALUE *num)
02163 {
02164     if (!read_digits(s, strict, num, NULL))
02165         return 0;
02166     return 1;
02167 }
02168 
02169 static int
02170 read_rat_nos(const char **s, int sign, int strict,
02171              VALUE *num)
02172 {
02173     VALUE den;
02174 
02175     if (!read_num(s, sign, strict, num))
02176         return 0;
02177     if (**s == '/') {
02178         (*s)++;
02179         if (!read_den(s, strict, &den))
02180             return 0;
02181         if (!(FIXNUM_P(den) && FIX2LONG(den) == 1))
02182             *num = f_div(*num, den);
02183     }
02184     return 1;
02185 }
02186 
02187 static int
02188 read_rat(const char **s, int strict,
02189          VALUE *num)
02190 {
02191     int sign;
02192 
02193     sign = read_sign(s);
02194     if (!read_rat_nos(s, sign, strict, num))
02195         return 0;
02196     return 1;
02197 }
02198 
02199 inline static void
02200 skip_ws(const char **s)
02201 {
02202     while (isspace((unsigned char)**s))
02203         (*s)++;
02204 }
02205 
02206 static int
02207 parse_rat(const char *s, int strict,
02208           VALUE *num)
02209 {
02210     skip_ws(&s);
02211     if (!read_rat(&s, strict, num))
02212         return 0;
02213     skip_ws(&s);
02214 
02215     if (strict)
02216         if (*s != '\0')
02217             return 0;
02218     return 1;
02219 }
02220 
02221 static VALUE
02222 string_to_r_strict(VALUE self)
02223 {
02224     char *s;
02225     VALUE num;
02226 
02227     rb_must_asciicompat(self);
02228 
02229     s = RSTRING_PTR(self);
02230 
02231     if (!s || memchr(s, '\0', RSTRING_LEN(self)))
02232         rb_raise(rb_eArgError, "string contains null byte");
02233 
02234     if (s && s[RSTRING_LEN(self)]) {
02235         rb_str_modify(self);
02236         s = RSTRING_PTR(self);
02237         s[RSTRING_LEN(self)] = '\0';
02238     }
02239 
02240     if (!s)
02241         s = (char *)"";
02242 
02243     if (!parse_rat(s, 1, &num)) {
02244         VALUE ins = f_inspect(self);
02245         rb_raise(rb_eArgError, "invalid value for convert(): %s",
02246                  StringValuePtr(ins));
02247     }
02248 
02249     if (RB_TYPE_P(num, T_FLOAT))
02250         rb_raise(rb_eFloatDomainError, "Infinity");
02251     return num;
02252 }
02253 
02254 /*
02255  * call-seq:
02256  *    str.to_r  ->  rational
02257  *
02258  * Returns a rational which denotes the string form.  The parser
02259  * ignores leading whitespaces and trailing garbage.  Any digit
02260  * sequences can be separated by an underscore.  Returns zero for null
02261  * or garbage string.
02262  *
02263  * NOTE: '0.3'.to_r isn't the same as 0.3.to_r.  The former is
02264  * equivalent to '3/10'.to_r, but the latter isn't so.
02265  *
02266  *    '  2  '.to_r       #=> (2/1)
02267  *    '300/2'.to_r       #=> (150/1)
02268  *    '-9.2'.to_r        #=> (-46/5)
02269  *    '-9.2e2'.to_r      #=> (-920/1)
02270  *    '1_234_567'.to_r   #=> (1234567/1)
02271  *    '21 june 09'.to_r  #=> (21/1)
02272  *    '21/06/09'.to_r    #=> (7/2)
02273  *    'bwv 1079'.to_r    #=> (0/1)
02274  *
02275  * See Kernel.Rational.
02276  */
02277 static VALUE
02278 string_to_r(VALUE self)
02279 {
02280     char *s;
02281     VALUE num;
02282 
02283     rb_must_asciicompat(self);
02284 
02285     s = RSTRING_PTR(self);
02286 
02287     if (s && s[RSTRING_LEN(self)]) {
02288         rb_str_modify(self);
02289         s = RSTRING_PTR(self);
02290         s[RSTRING_LEN(self)] = '\0';
02291     }
02292 
02293     if (!s)
02294         s = (char *)"";
02295 
02296     (void)parse_rat(s, 0, &num);
02297 
02298     if (RB_TYPE_P(num, T_FLOAT))
02299         rb_raise(rb_eFloatDomainError, "Infinity");
02300     return num;
02301 }
02302 
02303 VALUE
02304 rb_cstr_to_rat(const char *s, int strict) /* for complex's internal */
02305 {
02306     VALUE num;
02307 
02308     (void)parse_rat(s, strict, &num);
02309 
02310     if (RB_TYPE_P(num, T_FLOAT))
02311         rb_raise(rb_eFloatDomainError, "Infinity");
02312     return num;
02313 }
02314 
02315 static VALUE
02316 nurat_s_convert(int argc, VALUE *argv, VALUE klass)
02317 {
02318     VALUE a1, a2, backref;
02319 
02320     rb_scan_args(argc, argv, "11", &a1, &a2);
02321 
02322     if (NIL_P(a1) || (argc == 2 && NIL_P(a2)))
02323         rb_raise(rb_eTypeError, "can't convert nil into Rational");
02324 
02325     switch (TYPE(a1)) {
02326       case T_COMPLEX:
02327         if (k_exact_zero_p(RCOMPLEX(a1)->imag))
02328             a1 = RCOMPLEX(a1)->real;
02329     }
02330 
02331     switch (TYPE(a2)) {
02332       case T_COMPLEX:
02333         if (k_exact_zero_p(RCOMPLEX(a2)->imag))
02334             a2 = RCOMPLEX(a2)->real;
02335     }
02336 
02337     backref = rb_backref_get();
02338     rb_match_busy(backref);
02339 
02340     switch (TYPE(a1)) {
02341       case T_FIXNUM:
02342       case T_BIGNUM:
02343         break;
02344       case T_FLOAT:
02345         a1 = f_to_r(a1);
02346         break;
02347       case T_STRING:
02348         a1 = string_to_r_strict(a1);
02349         break;
02350     }
02351 
02352     switch (TYPE(a2)) {
02353       case T_FIXNUM:
02354       case T_BIGNUM:
02355         break;
02356       case T_FLOAT:
02357         a2 = f_to_r(a2);
02358         break;
02359       case T_STRING:
02360         a2 = string_to_r_strict(a2);
02361         break;
02362     }
02363 
02364     rb_backref_set(backref);
02365 
02366     switch (TYPE(a1)) {
02367       case T_RATIONAL:
02368         if (argc == 1 || (k_exact_one_p(a2)))
02369             return a1;
02370     }
02371 
02372     if (argc == 1) {
02373         if (!(k_numeric_p(a1) && k_integer_p(a1)))
02374             return rb_convert_type(a1, T_RATIONAL, "Rational", "to_r");
02375     }
02376     else {
02377         if ((k_numeric_p(a1) && k_numeric_p(a2)) &&
02378             (!f_integer_p(a1) || !f_integer_p(a2)))
02379             return f_div(a1, a2);
02380     }
02381 
02382     {
02383         VALUE argv2[2];
02384         argv2[0] = a1;
02385         argv2[1] = a2;
02386         return nurat_s_new(argc, argv2, klass);
02387     }
02388 }
02389 
02390 /*
02391  * A rational number can be represented as a paired integer number;
02392  * a/b (b>0).  Where a is numerator and b is denominator.  Integer a
02393  * equals rational a/1 mathematically.
02394  *
02395  * In ruby, you can create rational object with Rational, to_r or
02396  * rationalize method.  The return values will be irreducible.
02397  *
02398  *    Rational(1)      #=> (1/1)
02399  *    Rational(2, 3)   #=> (2/3)
02400  *    Rational(4, -6)  #=> (-2/3)
02401  *    3.to_r           #=> (3/1)
02402  *
02403  * You can also create rational object from floating-point numbers or
02404  * strings.
02405  *
02406  *    Rational(0.3)    #=> (5404319552844595/18014398509481984)
02407  *    Rational('0.3')  #=> (3/10)
02408  *    Rational('2/3')  #=> (2/3)
02409  *
02410  *    0.3.to_r         #=> (5404319552844595/18014398509481984)
02411  *    '0.3'.to_r       #=> (3/10)
02412  *    '2/3'.to_r       #=> (2/3)
02413  *    0.3.rationalize  #=> (3/10)
02414  *
02415  * A rational object is an exact number, which helps you to write
02416  * program without any rounding errors.
02417  *
02418  *    10.times.inject(0){|t,| t + 0.1}              #=> 0.9999999999999999
02419  *    10.times.inject(0){|t,| t + Rational('0.1')}  #=> (1/1)
02420  *
02421  * However, when an expression has inexact factor (numerical value or
02422  * operation), will produce an inexact result.
02423  *
02424  *    Rational(10) / 3   #=> (10/3)
02425  *    Rational(10) / 3.0 #=> 3.3333333333333335
02426  *
02427  *    Rational(-8) ** Rational(1, 3)
02428  *                       #=> (1.0000000000000002+1.7320508075688772i)
02429  */
02430 void
02431 Init_Rational(void)
02432 {
02433     VALUE compat;
02434 #undef rb_intern
02435 #define rb_intern(str) rb_intern_const(str)
02436 
02437     assert(fprintf(stderr, "assert() is now active\n"));
02438 
02439     id_abs = rb_intern("abs");
02440     id_cmp = rb_intern("<=>");
02441     id_convert = rb_intern("convert");
02442     id_eqeq_p = rb_intern("==");
02443     id_expt = rb_intern("**");
02444     id_fdiv = rb_intern("fdiv");
02445     id_floor = rb_intern("floor");
02446     id_idiv = rb_intern("div");
02447     id_inspect = rb_intern("inspect");
02448     id_integer_p = rb_intern("integer?");
02449     id_negate = rb_intern("-@");
02450     id_to_f = rb_intern("to_f");
02451     id_to_i = rb_intern("to_i");
02452     id_to_s = rb_intern("to_s");
02453     id_truncate = rb_intern("truncate");
02454     id_i_num = rb_intern("@numerator");
02455     id_i_den = rb_intern("@denominator");
02456 
02457     rb_cRational = rb_define_class("Rational", rb_cNumeric);
02458 
02459     rb_define_alloc_func(rb_cRational, nurat_s_alloc);
02460     rb_undef_method(CLASS_OF(rb_cRational), "allocate");
02461 
02462 #if 0
02463     rb_define_private_method(CLASS_OF(rb_cRational), "new!", nurat_s_new_bang, -1);
02464     rb_define_private_method(CLASS_OF(rb_cRational), "new", nurat_s_new, -1);
02465 #else
02466     rb_undef_method(CLASS_OF(rb_cRational), "new");
02467 #endif
02468 
02469     rb_define_global_function("Rational", nurat_f_rational, -1);
02470 
02471     rb_define_method(rb_cRational, "numerator", nurat_numerator, 0);
02472     rb_define_method(rb_cRational, "denominator", nurat_denominator, 0);
02473 
02474     rb_define_method(rb_cRational, "+", nurat_add, 1);
02475     rb_define_method(rb_cRational, "-", nurat_sub, 1);
02476     rb_define_method(rb_cRational, "*", nurat_mul, 1);
02477     rb_define_method(rb_cRational, "/", nurat_div, 1);
02478     rb_define_method(rb_cRational, "quo", nurat_div, 1);
02479     rb_define_method(rb_cRational, "fdiv", nurat_fdiv, 1);
02480     rb_define_method(rb_cRational, "**", nurat_expt, 1);
02481 
02482     rb_define_method(rb_cRational, "<=>", nurat_cmp, 1);
02483     rb_define_method(rb_cRational, "==", nurat_eqeq_p, 1);
02484     rb_define_method(rb_cRational, "coerce", nurat_coerce, 1);
02485 
02486 #if 0 /* NUBY */
02487     rb_define_method(rb_cRational, "//", nurat_idiv, 1);
02488 #endif
02489 
02490 #if 0
02491     rb_define_method(rb_cRational, "quot", nurat_quot, 1);
02492     rb_define_method(rb_cRational, "quotrem", nurat_quotrem, 1);
02493 #endif
02494 
02495 #if 0
02496     rb_define_method(rb_cRational, "rational?", nurat_true, 0);
02497     rb_define_method(rb_cRational, "exact?", nurat_true, 0);
02498 #endif
02499 
02500     rb_define_method(rb_cRational, "floor", nurat_floor_n, -1);
02501     rb_define_method(rb_cRational, "ceil", nurat_ceil_n, -1);
02502     rb_define_method(rb_cRational, "truncate", nurat_truncate_n, -1);
02503     rb_define_method(rb_cRational, "round", nurat_round_n, -1);
02504 
02505     rb_define_method(rb_cRational, "to_i", nurat_truncate, 0);
02506     rb_define_method(rb_cRational, "to_f", nurat_to_f, 0);
02507     rb_define_method(rb_cRational, "to_r", nurat_to_r, 0);
02508     rb_define_method(rb_cRational, "rationalize", nurat_rationalize, -1);
02509 
02510     rb_define_method(rb_cRational, "hash", nurat_hash, 0);
02511 
02512     rb_define_method(rb_cRational, "to_s", nurat_to_s, 0);
02513     rb_define_method(rb_cRational, "inspect", nurat_inspect, 0);
02514 
02515     rb_define_private_method(rb_cRational, "marshal_dump", nurat_marshal_dump, 0);
02516     compat = rb_define_class_under(rb_cRational, "compatible", rb_cObject);
02517     rb_define_private_method(compat, "marshal_load", nurat_marshal_load, 1);
02518     rb_marshal_define_compat(rb_cRational, compat, nurat_dumper, nurat_loader);
02519 
02520     /* --- */
02521 
02522     rb_define_method(rb_cInteger, "gcd", rb_gcd, 1);
02523     rb_define_method(rb_cInteger, "lcm", rb_lcm, 1);
02524     rb_define_method(rb_cInteger, "gcdlcm", rb_gcdlcm, 1);
02525 
02526     rb_define_method(rb_cNumeric, "numerator", numeric_numerator, 0);
02527     rb_define_method(rb_cNumeric, "denominator", numeric_denominator, 0);
02528 
02529     rb_define_method(rb_cInteger, "numerator", integer_numerator, 0);
02530     rb_define_method(rb_cInteger, "denominator", integer_denominator, 0);
02531 
02532     rb_define_method(rb_cFloat, "numerator", float_numerator, 0);
02533     rb_define_method(rb_cFloat, "denominator", float_denominator, 0);
02534 
02535     rb_define_method(rb_cNilClass, "to_r", nilclass_to_r, 0);
02536     rb_define_method(rb_cNilClass, "rationalize", nilclass_rationalize, -1);
02537     rb_define_method(rb_cInteger, "to_r", integer_to_r, 0);
02538     rb_define_method(rb_cInteger, "rationalize", integer_rationalize, -1);
02539     rb_define_method(rb_cFloat, "to_r", float_to_r, 0);
02540     rb_define_method(rb_cFloat, "rationalize", float_rationalize, -1);
02541 
02542     rb_define_method(rb_cString, "to_r", string_to_r, 0);
02543 
02544     rb_define_private_method(CLASS_OF(rb_cRational), "convert", nurat_s_convert, -1);
02545 }
02546 
02547 /*
02548 Local variables:
02549 c-file-style: "ruby"
02550 End:
02551 */
02552