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