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