Ruby  2.0.0p594(2014-10-27revision48167)
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     VALUE tmp;
02074 
02075     if (!isdecimal(**s)) {
02076         *num = ZERO;
02077         return 0;
02078     }
02079 
02080     bb = b = ALLOCV_N(char, tmp, strlen(*s) + 1);
02081 
02082     while (isdecimal(**s) || **s == '_') {
02083         if (**s == '_') {
02084             if (strict) {
02085                 if (us) {
02086                     ret = 0;
02087                     goto conv;
02088                 }
02089             }
02090             us = 1;
02091         }
02092         else {
02093             if (count)
02094                 (*count)++;
02095             *b++ = **s;
02096             us = 0;
02097         }
02098         (*s)++;
02099     }
02100     if (us)
02101         do {
02102             (*s)--;
02103         } while (**s == '_');
02104   conv:
02105     *b = '\0';
02106     *num = rb_cstr_to_inum(bb, 10, 0);
02107     ALLOCV_END(tmp);
02108     return ret;
02109 }
02110 
02111 inline static int
02112 islettere(int c)
02113 {
02114     return (c == 'e' || c == 'E');
02115 }
02116 
02117 static int
02118 read_num(const char **s, int numsign, int strict,
02119          VALUE *num)
02120 {
02121     VALUE ip, fp, exp;
02122 
02123     *num = rb_rational_new2(ZERO, ONE);
02124     exp = Qnil;
02125 
02126     if (**s != '.') {
02127         if (!read_digits(s, strict, &ip, NULL))
02128             return 0;
02129         *num = rb_rational_new2(ip, ONE);
02130     }
02131 
02132     if (**s == '.') {
02133         int count = 0;
02134 
02135         (*s)++;
02136         if (!read_digits(s, strict, &fp, &count))
02137             return 0;
02138         {
02139             VALUE l = f_expt10(INT2NUM(count));
02140             *num = f_mul(*num, l);
02141             *num = f_add(*num, fp);
02142             *num = f_div(*num, l);
02143         }
02144     }
02145 
02146     if (islettere(**s)) {
02147         int expsign;
02148 
02149         (*s)++;
02150         expsign = read_sign(s);
02151         if (!read_digits(s, strict, &exp, NULL))
02152             return 0;
02153         if (expsign == '-')
02154             exp = f_negate(exp);
02155     }
02156 
02157     if (numsign == '-')
02158         *num = f_negate(*num);
02159     if (!NIL_P(exp)) {
02160         VALUE l = f_expt10(exp);
02161         *num = f_mul(*num, l);
02162     }
02163     return 1;
02164 }
02165 
02166 inline static int
02167 read_den(const char **s, int strict,
02168          VALUE *num)
02169 {
02170     if (!read_digits(s, strict, num, NULL))
02171         return 0;
02172     return 1;
02173 }
02174 
02175 static int
02176 read_rat_nos(const char **s, int sign, int strict,
02177              VALUE *num)
02178 {
02179     VALUE den;
02180 
02181     if (!read_num(s, sign, strict, num))
02182         return 0;
02183     if (**s == '/') {
02184         (*s)++;
02185         if (!read_den(s, strict, &den))
02186             return 0;
02187         if (!(FIXNUM_P(den) && FIX2LONG(den) == 1))
02188             *num = f_div(*num, den);
02189     }
02190     return 1;
02191 }
02192 
02193 static int
02194 read_rat(const char **s, int strict,
02195          VALUE *num)
02196 {
02197     int sign;
02198 
02199     sign = read_sign(s);
02200     if (!read_rat_nos(s, sign, strict, num))
02201         return 0;
02202     return 1;
02203 }
02204 
02205 inline static void
02206 skip_ws(const char **s)
02207 {
02208     while (isspace((unsigned char)**s))
02209         (*s)++;
02210 }
02211 
02212 static int
02213 parse_rat(const char *s, int strict,
02214           VALUE *num)
02215 {
02216     skip_ws(&s);
02217     if (!read_rat(&s, strict, num))
02218         return 0;
02219     skip_ws(&s);
02220 
02221     if (strict)
02222         if (*s != '\0')
02223             return 0;
02224     return 1;
02225 }
02226 
02227 static VALUE
02228 string_to_r_strict(VALUE self)
02229 {
02230     char *s;
02231     VALUE num;
02232 
02233     rb_must_asciicompat(self);
02234 
02235     s = RSTRING_PTR(self);
02236 
02237     if (!s || memchr(s, '\0', RSTRING_LEN(self)))
02238         rb_raise(rb_eArgError, "string contains null byte");
02239 
02240     if (s && s[RSTRING_LEN(self)]) {
02241         rb_str_modify(self);
02242         s = RSTRING_PTR(self);
02243         s[RSTRING_LEN(self)] = '\0';
02244     }
02245 
02246     if (!s)
02247         s = (char *)"";
02248 
02249     if (!parse_rat(s, 1, &num)) {
02250         VALUE ins = f_inspect(self);
02251         rb_raise(rb_eArgError, "invalid value for convert(): %s",
02252                  StringValuePtr(ins));
02253     }
02254 
02255     if (RB_TYPE_P(num, T_FLOAT))
02256         rb_raise(rb_eFloatDomainError, "Infinity");
02257     return num;
02258 }
02259 
02260 /*
02261  * call-seq:
02262  *    str.to_r  ->  rational
02263  *
02264  * Returns a rational which denotes the string form.  The parser
02265  * ignores leading whitespaces and trailing garbage.  Any digit
02266  * sequences can be separated by an underscore.  Returns zero for null
02267  * or garbage string.
02268  *
02269  * NOTE: '0.3'.to_r isn't the same as 0.3.to_r.  The former is
02270  * equivalent to '3/10'.to_r, but the latter isn't so.
02271  *
02272  *    '  2  '.to_r       #=> (2/1)
02273  *    '300/2'.to_r       #=> (150/1)
02274  *    '-9.2'.to_r        #=> (-46/5)
02275  *    '-9.2e2'.to_r      #=> (-920/1)
02276  *    '1_234_567'.to_r   #=> (1234567/1)
02277  *    '21 june 09'.to_r  #=> (21/1)
02278  *    '21/06/09'.to_r    #=> (7/2)
02279  *    'bwv 1079'.to_r    #=> (0/1)
02280  *
02281  * See Kernel.Rational.
02282  */
02283 static VALUE
02284 string_to_r(VALUE self)
02285 {
02286     char *s;
02287     VALUE num;
02288 
02289     rb_must_asciicompat(self);
02290 
02291     s = RSTRING_PTR(self);
02292 
02293     if (s && s[RSTRING_LEN(self)]) {
02294         rb_str_modify(self);
02295         s = RSTRING_PTR(self);
02296         s[RSTRING_LEN(self)] = '\0';
02297     }
02298 
02299     if (!s)
02300         s = (char *)"";
02301 
02302     (void)parse_rat(s, 0, &num);
02303 
02304     if (RB_TYPE_P(num, T_FLOAT))
02305         rb_raise(rb_eFloatDomainError, "Infinity");
02306     return num;
02307 }
02308 
02309 VALUE
02310 rb_cstr_to_rat(const char *s, int strict) /* for complex's internal */
02311 {
02312     VALUE num;
02313 
02314     (void)parse_rat(s, strict, &num);
02315 
02316     if (RB_TYPE_P(num, T_FLOAT))
02317         rb_raise(rb_eFloatDomainError, "Infinity");
02318     return num;
02319 }
02320 
02321 static VALUE
02322 nurat_s_convert(int argc, VALUE *argv, VALUE klass)
02323 {
02324     VALUE a1, a2, backref;
02325 
02326     rb_scan_args(argc, argv, "11", &a1, &a2);
02327 
02328     if (NIL_P(a1) || (argc == 2 && NIL_P(a2)))
02329         rb_raise(rb_eTypeError, "can't convert nil into Rational");
02330 
02331     switch (TYPE(a1)) {
02332       case T_COMPLEX:
02333         if (k_exact_zero_p(RCOMPLEX(a1)->imag))
02334             a1 = RCOMPLEX(a1)->real;
02335     }
02336 
02337     switch (TYPE(a2)) {
02338       case T_COMPLEX:
02339         if (k_exact_zero_p(RCOMPLEX(a2)->imag))
02340             a2 = RCOMPLEX(a2)->real;
02341     }
02342 
02343     backref = rb_backref_get();
02344     rb_match_busy(backref);
02345 
02346     switch (TYPE(a1)) {
02347       case T_FIXNUM:
02348       case T_BIGNUM:
02349         break;
02350       case T_FLOAT:
02351         a1 = f_to_r(a1);
02352         break;
02353       case T_STRING:
02354         a1 = string_to_r_strict(a1);
02355         break;
02356     }
02357 
02358     switch (TYPE(a2)) {
02359       case T_FIXNUM:
02360       case T_BIGNUM:
02361         break;
02362       case T_FLOAT:
02363         a2 = f_to_r(a2);
02364         break;
02365       case T_STRING:
02366         a2 = string_to_r_strict(a2);
02367         break;
02368     }
02369 
02370     rb_backref_set(backref);
02371 
02372     switch (TYPE(a1)) {
02373       case T_RATIONAL:
02374         if (argc == 1 || (k_exact_one_p(a2)))
02375             return a1;
02376     }
02377 
02378     if (argc == 1) {
02379         if (!(k_numeric_p(a1) && k_integer_p(a1)))
02380             return rb_convert_type(a1, T_RATIONAL, "Rational", "to_r");
02381     }
02382     else {
02383         if ((k_numeric_p(a1) && k_numeric_p(a2)) &&
02384             (!f_integer_p(a1) || !f_integer_p(a2)))
02385             return f_div(a1, a2);
02386     }
02387 
02388     {
02389         VALUE argv2[2];
02390         argv2[0] = a1;
02391         argv2[1] = a2;
02392         return nurat_s_new(argc, argv2, klass);
02393     }
02394 }
02395 
02396 /*
02397  * A rational number can be represented as a paired integer number;
02398  * a/b (b>0).  Where a is numerator and b is denominator.  Integer a
02399  * equals rational a/1 mathematically.
02400  *
02401  * In ruby, you can create rational object with Rational, to_r or
02402  * rationalize method.  The return values will be irreducible.
02403  *
02404  *    Rational(1)      #=> (1/1)
02405  *    Rational(2, 3)   #=> (2/3)
02406  *    Rational(4, -6)  #=> (-2/3)
02407  *    3.to_r           #=> (3/1)
02408  *
02409  * You can also create rational object from floating-point numbers or
02410  * strings.
02411  *
02412  *    Rational(0.3)    #=> (5404319552844595/18014398509481984)
02413  *    Rational('0.3')  #=> (3/10)
02414  *    Rational('2/3')  #=> (2/3)
02415  *
02416  *    0.3.to_r         #=> (5404319552844595/18014398509481984)
02417  *    '0.3'.to_r       #=> (3/10)
02418  *    '2/3'.to_r       #=> (2/3)
02419  *    0.3.rationalize  #=> (3/10)
02420  *
02421  * A rational object is an exact number, which helps you to write
02422  * program without any rounding errors.
02423  *
02424  *    10.times.inject(0){|t,| t + 0.1}              #=> 0.9999999999999999
02425  *    10.times.inject(0){|t,| t + Rational('0.1')}  #=> (1/1)
02426  *
02427  * However, when an expression has inexact factor (numerical value or
02428  * operation), will produce an inexact result.
02429  *
02430  *    Rational(10) / 3   #=> (10/3)
02431  *    Rational(10) / 3.0 #=> 3.3333333333333335
02432  *
02433  *    Rational(-8) ** Rational(1, 3)
02434  *                       #=> (1.0000000000000002+1.7320508075688772i)
02435  */
02436 void
02437 Init_Rational(void)
02438 {
02439     VALUE compat;
02440 #undef rb_intern
02441 #define rb_intern(str) rb_intern_const(str)
02442 
02443     assert(fprintf(stderr, "assert() is now active\n"));
02444 
02445     id_abs = rb_intern("abs");
02446     id_cmp = rb_intern("<=>");
02447     id_convert = rb_intern("convert");
02448     id_eqeq_p = rb_intern("==");
02449     id_expt = rb_intern("**");
02450     id_fdiv = rb_intern("fdiv");
02451     id_floor = rb_intern("floor");
02452     id_idiv = rb_intern("div");
02453     id_inspect = rb_intern("inspect");
02454     id_integer_p = rb_intern("integer?");
02455     id_negate = rb_intern("-@");
02456     id_to_f = rb_intern("to_f");
02457     id_to_i = rb_intern("to_i");
02458     id_to_s = rb_intern("to_s");
02459     id_truncate = rb_intern("truncate");
02460     id_i_num = rb_intern("@numerator");
02461     id_i_den = rb_intern("@denominator");
02462 
02463     rb_cRational = rb_define_class("Rational", rb_cNumeric);
02464 
02465     rb_define_alloc_func(rb_cRational, nurat_s_alloc);
02466     rb_undef_method(CLASS_OF(rb_cRational), "allocate");
02467 
02468 #if 0
02469     rb_define_private_method(CLASS_OF(rb_cRational), "new!", nurat_s_new_bang, -1);
02470     rb_define_private_method(CLASS_OF(rb_cRational), "new", nurat_s_new, -1);
02471 #else
02472     rb_undef_method(CLASS_OF(rb_cRational), "new");
02473 #endif
02474 
02475     rb_define_global_function("Rational", nurat_f_rational, -1);
02476 
02477     rb_define_method(rb_cRational, "numerator", nurat_numerator, 0);
02478     rb_define_method(rb_cRational, "denominator", nurat_denominator, 0);
02479 
02480     rb_define_method(rb_cRational, "+", nurat_add, 1);
02481     rb_define_method(rb_cRational, "-", nurat_sub, 1);
02482     rb_define_method(rb_cRational, "*", nurat_mul, 1);
02483     rb_define_method(rb_cRational, "/", nurat_div, 1);
02484     rb_define_method(rb_cRational, "quo", nurat_div, 1);
02485     rb_define_method(rb_cRational, "fdiv", nurat_fdiv, 1);
02486     rb_define_method(rb_cRational, "**", nurat_expt, 1);
02487 
02488     rb_define_method(rb_cRational, "<=>", nurat_cmp, 1);
02489     rb_define_method(rb_cRational, "==", nurat_eqeq_p, 1);
02490     rb_define_method(rb_cRational, "coerce", nurat_coerce, 1);
02491 
02492 #if 0 /* NUBY */
02493     rb_define_method(rb_cRational, "//", nurat_idiv, 1);
02494 #endif
02495 
02496 #if 0
02497     rb_define_method(rb_cRational, "quot", nurat_quot, 1);
02498     rb_define_method(rb_cRational, "quotrem", nurat_quotrem, 1);
02499 #endif
02500 
02501 #if 0
02502     rb_define_method(rb_cRational, "rational?", nurat_true, 0);
02503     rb_define_method(rb_cRational, "exact?", nurat_true, 0);
02504 #endif
02505 
02506     rb_define_method(rb_cRational, "floor", nurat_floor_n, -1);
02507     rb_define_method(rb_cRational, "ceil", nurat_ceil_n, -1);
02508     rb_define_method(rb_cRational, "truncate", nurat_truncate_n, -1);
02509     rb_define_method(rb_cRational, "round", nurat_round_n, -1);
02510 
02511     rb_define_method(rb_cRational, "to_i", nurat_truncate, 0);
02512     rb_define_method(rb_cRational, "to_f", nurat_to_f, 0);
02513     rb_define_method(rb_cRational, "to_r", nurat_to_r, 0);
02514     rb_define_method(rb_cRational, "rationalize", nurat_rationalize, -1);
02515 
02516     rb_define_method(rb_cRational, "hash", nurat_hash, 0);
02517 
02518     rb_define_method(rb_cRational, "to_s", nurat_to_s, 0);
02519     rb_define_method(rb_cRational, "inspect", nurat_inspect, 0);
02520 
02521     rb_define_private_method(rb_cRational, "marshal_dump", nurat_marshal_dump, 0);
02522     compat = rb_define_class_under(rb_cRational, "compatible", rb_cObject);
02523     rb_define_private_method(compat, "marshal_load", nurat_marshal_load, 1);
02524     rb_marshal_define_compat(rb_cRational, compat, nurat_dumper, nurat_loader);
02525 
02526     /* --- */
02527 
02528     rb_define_method(rb_cInteger, "gcd", rb_gcd, 1);
02529     rb_define_method(rb_cInteger, "lcm", rb_lcm, 1);
02530     rb_define_method(rb_cInteger, "gcdlcm", rb_gcdlcm, 1);
02531 
02532     rb_define_method(rb_cNumeric, "numerator", numeric_numerator, 0);
02533     rb_define_method(rb_cNumeric, "denominator", numeric_denominator, 0);
02534 
02535     rb_define_method(rb_cInteger, "numerator", integer_numerator, 0);
02536     rb_define_method(rb_cInteger, "denominator", integer_denominator, 0);
02537 
02538     rb_define_method(rb_cFloat, "numerator", float_numerator, 0);
02539     rb_define_method(rb_cFloat, "denominator", float_denominator, 0);
02540 
02541     rb_define_method(rb_cNilClass, "to_r", nilclass_to_r, 0);
02542     rb_define_method(rb_cNilClass, "rationalize", nilclass_rationalize, -1);
02543     rb_define_method(rb_cInteger, "to_r", integer_to_r, 0);
02544     rb_define_method(rb_cInteger, "rationalize", integer_rationalize, -1);
02545     rb_define_method(rb_cFloat, "to_r", float_to_r, 0);
02546     rb_define_method(rb_cFloat, "rationalize", float_rationalize, -1);
02547 
02548     rb_define_method(rb_cString, "to_r", string_to_r, 0);
02549 
02550     rb_define_private_method(CLASS_OF(rb_cRational), "convert", nurat_s_convert, -1);
02551 }
02552 
02553 /*
02554 Local variables:
02555 c-file-style: "ruby"
02556 End:
02557 */
02558