1 /*
2   rational.c: Coded by Tadayoshi Funaba 2008-2012
3 
4   This implementation is based on Keiju Ishitsuka's Rational library
5   which is written in ruby.
6 */
7 
8 #include "internal.h"
9 #include "id.h"
10 #include <math.h>
11 #include <float.h>
12 
13 #ifdef HAVE_IEEEFP_H
14 #include <ieeefp.h>
15 #endif
16 
17 #define NDEBUG
18 #include "ruby_assert.h"
19 
20 #if defined(HAVE_LIBGMP) && defined(HAVE_GMP_H)
21 #define USE_GMP
22 #include <gmp.h>
23 #endif
24 
25 #define ZERO INT2FIX(0)
26 #define ONE INT2FIX(1)
27 #define TWO INT2FIX(2)
28 
29 #define GMP_GCD_DIGITS 1
30 
31 #define INT_POSITIVE_P(x) (FIXNUM_P(x) ? FIXNUM_POSITIVE_P(x) : BIGNUM_POSITIVE_P(x))
32 #define INT_ZERO_P(x) (FIXNUM_P(x) ? FIXNUM_ZERO_P(x) : rb_bigzero_p(x))
33 
34 VALUE rb_cRational;
35 
36 static ID id_abs, id_idiv, id_integer_p,
37     id_i_num, id_i_den;
38 #define id_to_i idTo_i
39 
40 #define f_boolcast(x) ((x) ? Qtrue : Qfalse)
41 #define f_inspect rb_inspect
42 #define f_to_s rb_obj_as_string
43 
44 static VALUE nurat_to_f(VALUE self);
45 
46 #define binop(n,op) \
47 inline static VALUE \
48 f_##n(VALUE x, VALUE y)\
49 {\
50     return rb_funcall(x, (op), 1, y); \
51 }
52 
53 #define fun1(n) \
54 inline static VALUE \
55 f_##n(VALUE x)\
56 {\
57     return rb_funcall(x, id_##n, 0);\
58 }
59 
60 inline static VALUE
f_add(VALUE x,VALUE y)61 f_add(VALUE x, VALUE y)
62 {
63     if (FIXNUM_ZERO_P(y))
64 	return x;
65     if (FIXNUM_ZERO_P(x))
66 	return y;
67     return rb_funcall(x, '+', 1, y);
68 }
69 
70 inline static VALUE
f_div(VALUE x,VALUE y)71 f_div(VALUE x, VALUE y)
72 {
73     if (y == ONE)
74 	return x;
75     if (RB_INTEGER_TYPE_P(x))
76 	return rb_int_div(x, y);
77     return rb_funcall(x, '/', 1, y);
78 }
79 
80 inline static int
f_lt_p(VALUE x,VALUE y)81 f_lt_p(VALUE x, VALUE y)
82 {
83     if (FIXNUM_P(x) && FIXNUM_P(y))
84 	return (SIGNED_VALUE)x < (SIGNED_VALUE)y;
85     return RTEST(rb_funcall(x, '<', 1, y));
86 }
87 
88 #ifndef NDEBUG
89 /* f_mod is used only in f_gcd defined when NDEBUG is not defined */
90 binop(mod, '%')
91 #endif
92 
93 inline static VALUE
f_mul(VALUE x,VALUE y)94 f_mul(VALUE x, VALUE y)
95 {
96     if (FIXNUM_ZERO_P(y) && RB_INTEGER_TYPE_P(x))
97 	return ZERO;
98     if (y == ONE) return x;
99     if (FIXNUM_ZERO_P(x) && RB_INTEGER_TYPE_P(y))
100 	return ZERO;
101     if (x == ONE) return y;
102     else if (RB_INTEGER_TYPE_P(x))
103 	return rb_int_mul(x, y);
104     return rb_funcall(x, '*', 1, y);
105 }
106 
107 inline static VALUE
f_sub(VALUE x,VALUE y)108 f_sub(VALUE x, VALUE y)
109 {
110     if (FIXNUM_P(y) && FIXNUM_ZERO_P(y))
111 	return x;
112     return rb_funcall(x, '-', 1, y);
113 }
114 
115 inline static VALUE
f_abs(VALUE x)116 f_abs(VALUE x)
117 {
118     if (RB_INTEGER_TYPE_P(x))
119 	return rb_int_abs(x);
120     return rb_funcall(x, id_abs, 0);
121 }
122 
fun1(integer_p)123 fun1(integer_p)
124 
125 inline static VALUE
126 f_to_i(VALUE x)
127 {
128     if (RB_TYPE_P(x, T_STRING))
129 	return rb_str_to_inum(x, 10, 0);
130     return rb_funcall(x, id_to_i, 0);
131 }
132 
133 inline static VALUE
f_eqeq_p(VALUE x,VALUE y)134 f_eqeq_p(VALUE x, VALUE y)
135 {
136     if (FIXNUM_P(x) && FIXNUM_P(y))
137 	return x == y;
138     return (int)rb_equal(x, y);
139 }
140 
141 inline static VALUE
f_idiv(VALUE x,VALUE y)142 f_idiv(VALUE x, VALUE y)
143 {
144     if (RB_INTEGER_TYPE_P(x))
145 	return rb_int_idiv(x, y);
146     return rb_funcall(x, id_idiv, 1, y);
147 }
148 
149 #define f_expt10(x) rb_int_pow(INT2FIX(10), x)
150 
151 inline static int
f_zero_p(VALUE x)152 f_zero_p(VALUE x)
153 {
154     if (RB_INTEGER_TYPE_P(x)) {
155 	return FIXNUM_ZERO_P(x);
156     }
157     else if (RB_TYPE_P(x, T_RATIONAL)) {
158 	VALUE num = RRATIONAL(x)->num;
159 
160 	return FIXNUM_ZERO_P(num);
161     }
162     return (int)rb_equal(x, ZERO);
163 }
164 
165 #define f_nonzero_p(x) (!f_zero_p(x))
166 
167 inline static int
f_one_p(VALUE x)168 f_one_p(VALUE x)
169 {
170     if (RB_INTEGER_TYPE_P(x)) {
171 	return x == LONG2FIX(1);
172     }
173     else if (RB_TYPE_P(x, T_RATIONAL)) {
174 	VALUE num = RRATIONAL(x)->num;
175 	VALUE den = RRATIONAL(x)->den;
176 
177 	return num == LONG2FIX(1) && den == LONG2FIX(1);
178     }
179     return (int)rb_equal(x, ONE);
180 }
181 
182 inline static int
f_minus_one_p(VALUE x)183 f_minus_one_p(VALUE x)
184 {
185     if (RB_INTEGER_TYPE_P(x)) {
186 	return x == LONG2FIX(-1);
187     }
188     else if (RB_TYPE_P(x, T_BIGNUM)) {
189 	return Qfalse;
190     }
191     else if (RB_TYPE_P(x, T_RATIONAL)) {
192 	VALUE num = RRATIONAL(x)->num;
193 	VALUE den = RRATIONAL(x)->den;
194 
195 	return num == LONG2FIX(-1) && den == LONG2FIX(1);
196     }
197     return (int)rb_equal(x, INT2FIX(-1));
198 }
199 
200 inline static int
f_kind_of_p(VALUE x,VALUE c)201 f_kind_of_p(VALUE x, VALUE c)
202 {
203     return (int)rb_obj_is_kind_of(x, c);
204 }
205 
206 inline static int
k_numeric_p(VALUE x)207 k_numeric_p(VALUE x)
208 {
209     return f_kind_of_p(x, rb_cNumeric);
210 }
211 
212 inline static int
k_integer_p(VALUE x)213 k_integer_p(VALUE x)
214 {
215     return RB_INTEGER_TYPE_P(x);
216 }
217 
218 inline static int
k_float_p(VALUE x)219 k_float_p(VALUE x)
220 {
221     return RB_FLOAT_TYPE_P(x);
222 }
223 
224 inline static int
k_rational_p(VALUE x)225 k_rational_p(VALUE x)
226 {
227     return RB_TYPE_P(x, T_RATIONAL);
228 }
229 
230 #define k_exact_p(x) (!k_float_p(x))
231 #define k_inexact_p(x) k_float_p(x)
232 
233 #define k_exact_zero_p(x) (k_exact_p(x) && f_zero_p(x))
234 #define k_exact_one_p(x) (k_exact_p(x) && f_one_p(x))
235 
236 #ifdef USE_GMP
237 VALUE
rb_gcd_gmp(VALUE x,VALUE y)238 rb_gcd_gmp(VALUE x, VALUE y)
239 {
240     const size_t nails = (sizeof(BDIGIT)-SIZEOF_BDIGIT)*CHAR_BIT;
241     mpz_t mx, my, mz;
242     size_t count;
243     VALUE z;
244     long zn;
245 
246     mpz_init(mx);
247     mpz_init(my);
248     mpz_init(mz);
249     mpz_import(mx, BIGNUM_LEN(x), -1, sizeof(BDIGIT), 0, nails, BIGNUM_DIGITS(x));
250     mpz_import(my, BIGNUM_LEN(y), -1, sizeof(BDIGIT), 0, nails, BIGNUM_DIGITS(y));
251 
252     mpz_gcd(mz, mx, my);
253 
254     mpz_clear(mx);
255     mpz_clear(my);
256 
257     zn = (mpz_sizeinbase(mz, 16) + SIZEOF_BDIGIT*2 - 1) / (SIZEOF_BDIGIT*2);
258     z = rb_big_new(zn, 1);
259     mpz_export(BIGNUM_DIGITS(z), &count, -1, sizeof(BDIGIT), 0, nails, mz);
260 
261     mpz_clear(mz);
262 
263     return rb_big_norm(z);
264 }
265 #endif
266 
267 #ifndef NDEBUG
268 #define f_gcd f_gcd_orig
269 #endif
270 
271 inline static long
i_gcd(long x,long y)272 i_gcd(long x, long y)
273 {
274     unsigned long u, v, t;
275     int shift;
276 
277     if (x < 0)
278 	x = -x;
279     if (y < 0)
280 	y = -y;
281 
282     if (x == 0)
283 	return y;
284     if (y == 0)
285 	return x;
286 
287     u = (unsigned long)x;
288     v = (unsigned long)y;
289     for (shift = 0; ((u | v) & 1) == 0; ++shift) {
290 	u >>= 1;
291 	v >>= 1;
292     }
293 
294     while ((u & 1) == 0)
295 	u >>= 1;
296 
297     do {
298 	while ((v & 1) == 0)
299 	    v >>= 1;
300 
301 	if (u > v) {
302 	    t = v;
303 	    v = u;
304 	    u = t;
305 	}
306 	v = v - u;
307     } while (v != 0);
308 
309     return (long)(u << shift);
310 }
311 
312 inline static VALUE
f_gcd_normal(VALUE x,VALUE y)313 f_gcd_normal(VALUE x, VALUE y)
314 {
315     VALUE z;
316 
317     if (FIXNUM_P(x) && FIXNUM_P(y))
318 	return LONG2NUM(i_gcd(FIX2LONG(x), FIX2LONG(y)));
319 
320     if (INT_NEGATIVE_P(x))
321 	x = rb_int_uminus(x);
322     if (INT_NEGATIVE_P(y))
323 	y = rb_int_uminus(y);
324 
325     if (INT_ZERO_P(x))
326 	return y;
327     if (INT_ZERO_P(y))
328 	return x;
329 
330     for (;;) {
331 	if (FIXNUM_P(x)) {
332 	    if (FIXNUM_ZERO_P(x))
333 		return y;
334 	    if (FIXNUM_P(y))
335 		return LONG2NUM(i_gcd(FIX2LONG(x), FIX2LONG(y)));
336 	}
337 	z = x;
338 	x = rb_int_modulo(y, x);
339 	y = z;
340     }
341     /* NOTREACHED */
342 }
343 
344 VALUE
rb_gcd_normal(VALUE x,VALUE y)345 rb_gcd_normal(VALUE x, VALUE y)
346 {
347     return f_gcd_normal(x, y);
348 }
349 
350 inline static VALUE
f_gcd(VALUE x,VALUE y)351 f_gcd(VALUE x, VALUE y)
352 {
353 #ifdef USE_GMP
354     if (RB_TYPE_P(x, T_BIGNUM) && RB_TYPE_P(y, T_BIGNUM)) {
355         size_t xn = BIGNUM_LEN(x);
356         size_t yn = BIGNUM_LEN(y);
357         if (GMP_GCD_DIGITS <= xn || GMP_GCD_DIGITS <= yn)
358             return rb_gcd_gmp(x, y);
359     }
360 #endif
361     return f_gcd_normal(x, y);
362 }
363 
364 #ifndef NDEBUG
365 #undef f_gcd
366 
367 inline static VALUE
f_gcd(VALUE x,VALUE y)368 f_gcd(VALUE x, VALUE y)
369 {
370     VALUE r = f_gcd_orig(x, y);
371     if (f_nonzero_p(r)) {
372 	assert(f_zero_p(f_mod(x, r)));
373 	assert(f_zero_p(f_mod(y, r)));
374     }
375     return r;
376 }
377 #endif
378 
379 inline static VALUE
f_lcm(VALUE x,VALUE y)380 f_lcm(VALUE x, VALUE y)
381 {
382     if (INT_ZERO_P(x) || INT_ZERO_P(y))
383 	return ZERO;
384     return f_abs(f_mul(f_div(x, f_gcd(x, y)), y));
385 }
386 
387 #define get_dat1(x) \
388     struct RRational *dat = RRATIONAL(x)
389 
390 #define get_dat2(x,y) \
391     struct RRational *adat = RRATIONAL(x), *bdat = RRATIONAL(y)
392 
393 inline static VALUE
nurat_s_new_internal(VALUE klass,VALUE num,VALUE den)394 nurat_s_new_internal(VALUE klass, VALUE num, VALUE den)
395 {
396     NEWOBJ_OF(obj, struct RRational, klass, T_RATIONAL | (RGENGC_WB_PROTECTED_RATIONAL ? FL_WB_PROTECTED : 0));
397 
398     RRATIONAL_SET_NUM(obj, num);
399     RRATIONAL_SET_DEN(obj, den);
400     OBJ_FREEZE_RAW(obj);
401 
402     return (VALUE)obj;
403 }
404 
405 static VALUE
nurat_s_alloc(VALUE klass)406 nurat_s_alloc(VALUE klass)
407 {
408     return nurat_s_new_internal(klass, ZERO, ONE);
409 }
410 
411 inline static VALUE
f_rational_new_bang1(VALUE klass,VALUE x)412 f_rational_new_bang1(VALUE klass, VALUE x)
413 {
414     return nurat_s_new_internal(klass, x, ONE);
415 }
416 
417 #ifdef CANONICALIZATION_FOR_MATHN
418 static int canonicalization = 0;
419 
420 RUBY_FUNC_EXPORTED void
nurat_canonicalization(int f)421 nurat_canonicalization(int f)
422 {
423     canonicalization = f;
424 }
425 #else
426 # define canonicalization 0
427 #endif
428 
429 inline static void
nurat_int_check(VALUE num)430 nurat_int_check(VALUE num)
431 {
432     if (!RB_INTEGER_TYPE_P(num)) {
433 	if (!k_numeric_p(num) || !f_integer_p(num))
434 	    rb_raise(rb_eTypeError, "not an integer");
435     }
436 }
437 
438 inline static VALUE
nurat_int_value(VALUE num)439 nurat_int_value(VALUE num)
440 {
441     nurat_int_check(num);
442     if (!k_integer_p(num))
443 	num = f_to_i(num);
444     return num;
445 }
446 
447 static void
nurat_canonicalize(VALUE * num,VALUE * den)448 nurat_canonicalize(VALUE *num, VALUE *den)
449 {
450     assert(num); assert(RB_INTEGER_TYPE_P(*num));
451     assert(den); assert(RB_INTEGER_TYPE_P(*den));
452     if (INT_NEGATIVE_P(*den)) {
453         *num = rb_int_uminus(*num);
454         *den = rb_int_uminus(*den);
455     }
456     else if (INT_ZERO_P(*den)) {
457         rb_num_zerodiv();
458     }
459 }
460 
461 static void
nurat_reduce(VALUE * x,VALUE * y)462 nurat_reduce(VALUE *x, VALUE *y)
463 {
464     VALUE gcd;
465     if (*x == ONE || *y == ONE) return;
466     gcd = f_gcd(*x, *y);
467     *x = f_idiv(*x, gcd);
468     *y = f_idiv(*y, gcd);
469 }
470 
471 inline static VALUE
nurat_s_canonicalize_internal(VALUE klass,VALUE num,VALUE den)472 nurat_s_canonicalize_internal(VALUE klass, VALUE num, VALUE den)
473 {
474     nurat_canonicalize(&num, &den);
475     nurat_reduce(&num, &den);
476 
477     if (canonicalization && f_one_p(den))
478 	return num;
479     return nurat_s_new_internal(klass, num, den);
480 }
481 
482 inline static VALUE
nurat_s_canonicalize_internal_no_reduce(VALUE klass,VALUE num,VALUE den)483 nurat_s_canonicalize_internal_no_reduce(VALUE klass, VALUE num, VALUE den)
484 {
485     nurat_canonicalize(&num, &den);
486 
487     if (canonicalization && f_one_p(den))
488 	return num;
489     return nurat_s_new_internal(klass, num, den);
490 }
491 
492 static VALUE
nurat_s_new(int argc,VALUE * argv,VALUE klass)493 nurat_s_new(int argc, VALUE *argv, VALUE klass)
494 {
495     VALUE num, den;
496 
497     switch (rb_scan_args(argc, argv, "11", &num, &den)) {
498       case 1:
499 	num = nurat_int_value(num);
500 	den = ONE;
501 	break;
502       default:
503 	num = nurat_int_value(num);
504 	den = nurat_int_value(den);
505 	break;
506     }
507 
508     return nurat_s_canonicalize_internal(klass, num, den);
509 }
510 
511 inline static VALUE
f_rational_new2(VALUE klass,VALUE x,VALUE y)512 f_rational_new2(VALUE klass, VALUE x, VALUE y)
513 {
514     assert(!k_rational_p(x));
515     assert(!k_rational_p(y));
516     return nurat_s_canonicalize_internal(klass, x, y);
517 }
518 
519 inline static VALUE
f_rational_new_no_reduce2(VALUE klass,VALUE x,VALUE y)520 f_rational_new_no_reduce2(VALUE klass, VALUE x, VALUE y)
521 {
522     assert(!k_rational_p(x));
523     assert(!k_rational_p(y));
524     return nurat_s_canonicalize_internal_no_reduce(klass, x, y);
525 }
526 
527 static VALUE nurat_convert(VALUE klass, VALUE numv, VALUE denv, int raise);
528 static VALUE nurat_s_convert(int argc, VALUE *argv, VALUE klass);
529 
530 /*
531  * call-seq:
532  *    Rational(x, y, exception: true)  ->  rational
533  *    Rational(arg, exception: true)   ->  rational
534  *
535  * Returns +x/y+ or +arg+ as a Rational.
536  *
537  *    Rational(2, 3)   #=> (2/3)
538  *    Rational(5)      #=> (5/1)
539  *    Rational(0.5)    #=> (1/2)
540  *    Rational(0.3)    #=> (5404319552844595/18014398509481984)
541  *
542  *    Rational("2/3")  #=> (2/3)
543  *    Rational("0.3")  #=> (3/10)
544  *
545  *    Rational("10 cents")  #=> ArgumentError
546  *    Rational(nil)         #=> TypeError
547  *    Rational(1, nil)      #=> TypeError
548  *
549  *    Rational("10 cents", exception: false)  #=> nil
550  *
551  * Syntax of the string form:
552  *
553  *   string form = extra spaces , rational , extra spaces ;
554  *   rational = [ sign ] , unsigned rational ;
555  *   unsigned rational = numerator | numerator , "/" , denominator ;
556  *   numerator = integer part | fractional part | integer part , fractional part ;
557  *   denominator = digits ;
558  *   integer part = digits ;
559  *   fractional part = "." , digits , [ ( "e" | "E" ) , [ sign ] , digits ] ;
560  *   sign = "-" | "+" ;
561  *   digits = digit , { digit | "_" , digit } ;
562  *   digit = "0" | "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9" ;
563  *   extra spaces = ? \s* ? ;
564  *
565  * See also String#to_r.
566  */
567 static VALUE
nurat_f_rational(int argc,VALUE * argv,VALUE klass)568 nurat_f_rational(int argc, VALUE *argv, VALUE klass)
569 {
570     VALUE a1, a2, opts = Qnil;
571     int raise = TRUE;
572 
573     if (rb_scan_args(argc, argv, "11:", &a1, &a2, &opts) == 1) {
574         a2 = Qundef;
575     }
576     if (!NIL_P(opts)) {
577         static ID kwds[1];
578         VALUE exception;
579         if (!kwds[0]) {
580             kwds[0] = idException;
581         }
582         rb_get_kwargs(opts, kwds, 0, 1, &exception);
583         raise = (exception != Qfalse);
584     }
585     return nurat_convert(rb_cRational, a1, a2, raise);
586 }
587 
588 /*
589  * call-seq:
590  *    rat.numerator  ->  integer
591  *
592  * Returns the numerator.
593  *
594  *    Rational(7).numerator        #=> 7
595  *    Rational(7, 1).numerator     #=> 7
596  *    Rational(9, -4).numerator    #=> -9
597  *    Rational(-2, -10).numerator  #=> 1
598  */
599 static VALUE
nurat_numerator(VALUE self)600 nurat_numerator(VALUE self)
601 {
602     get_dat1(self);
603     return dat->num;
604 }
605 
606 /*
607  * call-seq:
608  *    rat.denominator  ->  integer
609  *
610  * Returns the denominator (always positive).
611  *
612  *    Rational(7).denominator             #=> 1
613  *    Rational(7, 1).denominator          #=> 1
614  *    Rational(9, -4).denominator         #=> 4
615  *    Rational(-2, -10).denominator       #=> 5
616  */
617 static VALUE
nurat_denominator(VALUE self)618 nurat_denominator(VALUE self)
619 {
620     get_dat1(self);
621     return dat->den;
622 }
623 
624 /*
625  * call-seq:
626  *    -rat  ->  rational
627  *
628  * Negates +rat+.
629  */
630 VALUE
rb_rational_uminus(VALUE self)631 rb_rational_uminus(VALUE self)
632 {
633     const int unused = (assert(RB_TYPE_P(self, T_RATIONAL)), 0);
634     get_dat1(self);
635     (void)unused;
636     return f_rational_new2(CLASS_OF(self), rb_int_uminus(dat->num), dat->den);
637 }
638 
639 #ifndef NDEBUG
640 #define f_imul f_imul_orig
641 #endif
642 
643 inline static VALUE
f_imul(long a,long b)644 f_imul(long a, long b)
645 {
646     VALUE r;
647 
648     if (a == 0 || b == 0)
649 	return ZERO;
650     else if (a == 1)
651 	return LONG2NUM(b);
652     else if (b == 1)
653 	return LONG2NUM(a);
654 
655     if (MUL_OVERFLOW_LONG_P(a, b))
656 	r = rb_big_mul(rb_int2big(a), rb_int2big(b));
657     else
658         r = LONG2NUM(a * b);
659     return r;
660 }
661 
662 #ifndef NDEBUG
663 #undef f_imul
664 
665 inline static VALUE
f_imul(long x,long y)666 f_imul(long x, long y)
667 {
668     VALUE r = f_imul_orig(x, y);
669     assert(f_eqeq_p(r, f_mul(LONG2NUM(x), LONG2NUM(y))));
670     return r;
671 }
672 #endif
673 
674 inline static VALUE
f_addsub(VALUE self,VALUE anum,VALUE aden,VALUE bnum,VALUE bden,int k)675 f_addsub(VALUE self, VALUE anum, VALUE aden, VALUE bnum, VALUE bden, int k)
676 {
677     VALUE num, den;
678 
679     if (FIXNUM_P(anum) && FIXNUM_P(aden) &&
680 	FIXNUM_P(bnum) && FIXNUM_P(bden)) {
681 	long an = FIX2LONG(anum);
682 	long ad = FIX2LONG(aden);
683 	long bn = FIX2LONG(bnum);
684 	long bd = FIX2LONG(bden);
685 	long ig = i_gcd(ad, bd);
686 
687 	VALUE g = LONG2NUM(ig);
688 	VALUE a = f_imul(an, bd / ig);
689 	VALUE b = f_imul(bn, ad / ig);
690 	VALUE c;
691 
692 	if (k == '+')
693 	    c = rb_int_plus(a, b);
694 	else
695 	    c = rb_int_minus(a, b);
696 
697 	b = rb_int_idiv(aden, g);
698 	g = f_gcd(c, g);
699 	num = rb_int_idiv(c, g);
700 	a = rb_int_idiv(bden, g);
701 	den = rb_int_mul(a, b);
702     }
703     else if (RB_INTEGER_TYPE_P(anum) && RB_INTEGER_TYPE_P(aden) &&
704              RB_INTEGER_TYPE_P(bnum) && RB_INTEGER_TYPE_P(bden)) {
705 	VALUE g = f_gcd(aden, bden);
706 	VALUE a = rb_int_mul(anum, rb_int_idiv(bden, g));
707 	VALUE b = rb_int_mul(bnum, rb_int_idiv(aden, g));
708 	VALUE c;
709 
710 	if (k == '+')
711 	    c = rb_int_plus(a, b);
712 	else
713 	    c = rb_int_minus(a, b);
714 
715 	b = rb_int_idiv(aden, g);
716 	g = f_gcd(c, g);
717 	num = rb_int_idiv(c, g);
718 	a = rb_int_idiv(bden, g);
719 	den = rb_int_mul(a, b);
720     }
721     else {
722         double a = NUM2DBL(anum) / NUM2DBL(aden);
723         double b = NUM2DBL(bnum) / NUM2DBL(bden);
724         double c = k == '+' ? a + b : a - b;
725         return DBL2NUM(c);
726     }
727     return f_rational_new_no_reduce2(CLASS_OF(self), num, den);
728 }
729 
730 static double nurat_to_double(VALUE self);
731 /*
732  * call-seq:
733  *    rat + numeric  ->  numeric
734  *
735  * Performs addition.
736  *
737  *    Rational(2, 3)  + Rational(2, 3)   #=> (4/3)
738  *    Rational(900)   + Rational(1)      #=> (901/1)
739  *    Rational(-2, 9) + Rational(-9, 2)  #=> (-85/18)
740  *    Rational(9, 8)  + 4                #=> (41/8)
741  *    Rational(20, 9) + 9.8              #=> 12.022222222222222
742  */
743 VALUE
rb_rational_plus(VALUE self,VALUE other)744 rb_rational_plus(VALUE self, VALUE other)
745 {
746     if (RB_INTEGER_TYPE_P(other)) {
747 	{
748 	    get_dat1(self);
749 
750 	    return f_rational_new_no_reduce2(CLASS_OF(self),
751 					     rb_int_plus(dat->num, rb_int_mul(other, dat->den)),
752 					     dat->den);
753 	}
754     }
755     else if (RB_FLOAT_TYPE_P(other)) {
756 	return DBL2NUM(nurat_to_double(self) + RFLOAT_VALUE(other));
757     }
758     else if (RB_TYPE_P(other, T_RATIONAL)) {
759 	{
760 	    get_dat2(self, other);
761 
762 	    return f_addsub(self,
763 			    adat->num, adat->den,
764 			    bdat->num, bdat->den, '+');
765 	}
766     }
767     else {
768 	return rb_num_coerce_bin(self, other, '+');
769     }
770 }
771 
772 /*
773  * call-seq:
774  *    rat - numeric  ->  numeric
775  *
776  * Performs subtraction.
777  *
778  *    Rational(2, 3)  - Rational(2, 3)   #=> (0/1)
779  *    Rational(900)   - Rational(1)      #=> (899/1)
780  *    Rational(-2, 9) - Rational(-9, 2)  #=> (77/18)
781  *    Rational(9, 8)  - 4                #=> (-23/8)
782  *    Rational(20, 9) - 9.8              #=> -7.577777777777778
783  */
784 VALUE
rb_rational_minus(VALUE self,VALUE other)785 rb_rational_minus(VALUE self, VALUE other)
786 {
787     if (RB_INTEGER_TYPE_P(other)) {
788 	{
789 	    get_dat1(self);
790 
791 	    return f_rational_new_no_reduce2(CLASS_OF(self),
792 					     rb_int_minus(dat->num, rb_int_mul(other, dat->den)),
793 					     dat->den);
794 	}
795     }
796     else if (RB_FLOAT_TYPE_P(other)) {
797 	return DBL2NUM(nurat_to_double(self) - RFLOAT_VALUE(other));
798     }
799     else if (RB_TYPE_P(other, T_RATIONAL)) {
800 	{
801 	    get_dat2(self, other);
802 
803 	    return f_addsub(self,
804 			    adat->num, adat->den,
805 			    bdat->num, bdat->den, '-');
806 	}
807     }
808     else {
809 	return rb_num_coerce_bin(self, other, '-');
810     }
811 }
812 
813 inline static VALUE
f_muldiv(VALUE self,VALUE anum,VALUE aden,VALUE bnum,VALUE bden,int k)814 f_muldiv(VALUE self, VALUE anum, VALUE aden, VALUE bnum, VALUE bden, int k)
815 {
816     VALUE num, den;
817 
818     assert(RB_TYPE_P(self, T_RATIONAL));
819 
820     /* Integer#** can return Rational with Float right now */
821     if (RB_FLOAT_TYPE_P(anum) || RB_FLOAT_TYPE_P(aden) ||
822         RB_FLOAT_TYPE_P(bnum) || RB_FLOAT_TYPE_P(bden)) {
823         double an = NUM2DBL(anum), ad = NUM2DBL(aden);
824         double bn = NUM2DBL(bnum), bd = NUM2DBL(bden);
825         double x = (an * bn) / (ad * bd);
826         return DBL2NUM(x);
827     }
828 
829     assert(RB_INTEGER_TYPE_P(anum));
830     assert(RB_INTEGER_TYPE_P(aden));
831     assert(RB_INTEGER_TYPE_P(bnum));
832     assert(RB_INTEGER_TYPE_P(bden));
833 
834     if (k == '/') {
835 	VALUE t;
836 
837 	if (INT_NEGATIVE_P(bnum)) {
838 	    anum = rb_int_uminus(anum);
839 	    bnum = rb_int_uminus(bnum);
840 	}
841 	t = bnum;
842 	bnum = bden;
843 	bden = t;
844     }
845 
846     if (FIXNUM_P(anum) && FIXNUM_P(aden) &&
847 	FIXNUM_P(bnum) && FIXNUM_P(bden)) {
848 	long an = FIX2LONG(anum);
849 	long ad = FIX2LONG(aden);
850 	long bn = FIX2LONG(bnum);
851 	long bd = FIX2LONG(bden);
852 	long g1 = i_gcd(an, bd);
853 	long g2 = i_gcd(ad, bn);
854 
855 	num = f_imul(an / g1, bn / g2);
856 	den = f_imul(ad / g2, bd / g1);
857     }
858     else {
859 	VALUE g1 = f_gcd(anum, bden);
860 	VALUE g2 = f_gcd(aden, bnum);
861 
862 	num = rb_int_mul(rb_int_idiv(anum, g1), rb_int_idiv(bnum, g2));
863 	den = rb_int_mul(rb_int_idiv(aden, g2), rb_int_idiv(bden, g1));
864     }
865     return f_rational_new_no_reduce2(CLASS_OF(self), num, den);
866 }
867 
868 /*
869  * call-seq:
870  *    rat * numeric  ->  numeric
871  *
872  * Performs multiplication.
873  *
874  *    Rational(2, 3)  * Rational(2, 3)   #=> (4/9)
875  *    Rational(900)   * Rational(1)      #=> (900/1)
876  *    Rational(-2, 9) * Rational(-9, 2)  #=> (1/1)
877  *    Rational(9, 8)  * 4                #=> (9/2)
878  *    Rational(20, 9) * 9.8              #=> 21.77777777777778
879  */
880 VALUE
rb_rational_mul(VALUE self,VALUE other)881 rb_rational_mul(VALUE self, VALUE other)
882 {
883     if (RB_INTEGER_TYPE_P(other)) {
884 	{
885 	    get_dat1(self);
886 
887 	    return f_muldiv(self,
888 			    dat->num, dat->den,
889 			    other, ONE, '*');
890 	}
891     }
892     else if (RB_FLOAT_TYPE_P(other)) {
893 	return DBL2NUM(nurat_to_double(self) * RFLOAT_VALUE(other));
894     }
895     else if (RB_TYPE_P(other, T_RATIONAL)) {
896 	{
897 	    get_dat2(self, other);
898 
899 	    return f_muldiv(self,
900 			    adat->num, adat->den,
901 			    bdat->num, bdat->den, '*');
902 	}
903     }
904     else {
905 	return rb_num_coerce_bin(self, other, '*');
906     }
907 }
908 
909 /*
910  * call-seq:
911  *    rat / numeric     ->  numeric
912  *    rat.quo(numeric)  ->  numeric
913  *
914  * Performs division.
915  *
916  *    Rational(2, 3)  / Rational(2, 3)   #=> (1/1)
917  *    Rational(900)   / Rational(1)      #=> (900/1)
918  *    Rational(-2, 9) / Rational(-9, 2)  #=> (4/81)
919  *    Rational(9, 8)  / 4                #=> (9/32)
920  *    Rational(20, 9) / 9.8              #=> 0.22675736961451246
921  */
922 VALUE
rb_rational_div(VALUE self,VALUE other)923 rb_rational_div(VALUE self, VALUE other)
924 {
925     if (RB_INTEGER_TYPE_P(other)) {
926 	if (f_zero_p(other))
927             rb_num_zerodiv();
928 	{
929 	    get_dat1(self);
930 
931 	    return f_muldiv(self,
932 			    dat->num, dat->den,
933 			    other, ONE, '/');
934 	}
935     }
936     else if (RB_FLOAT_TYPE_P(other)) {
937         VALUE v = nurat_to_f(self);
938         return rb_flo_div_flo(v, other);
939     }
940     else if (RB_TYPE_P(other, T_RATIONAL)) {
941 	if (f_zero_p(other))
942             rb_num_zerodiv();
943 	{
944 	    get_dat2(self, other);
945 
946 	    if (f_one_p(self))
947 		return f_rational_new_no_reduce2(CLASS_OF(self),
948 						 bdat->den, bdat->num);
949 
950 	    return f_muldiv(self,
951 			    adat->num, adat->den,
952 			    bdat->num, bdat->den, '/');
953 	}
954     }
955     else {
956 	return rb_num_coerce_bin(self, other, '/');
957     }
958 }
959 
960 /*
961  * call-seq:
962  *    rat.fdiv(numeric)  ->  float
963  *
964  * Performs division and returns the value as a Float.
965  *
966  *    Rational(2, 3).fdiv(1)       #=> 0.6666666666666666
967  *    Rational(2, 3).fdiv(0.5)     #=> 1.3333333333333333
968  *    Rational(2).fdiv(3)          #=> 0.6666666666666666
969  */
970 static VALUE
nurat_fdiv(VALUE self,VALUE other)971 nurat_fdiv(VALUE self, VALUE other)
972 {
973     VALUE div;
974     if (f_zero_p(other))
975         return rb_rational_div(self, rb_float_new(0.0));
976     if (FIXNUM_P(other) && other == LONG2FIX(1))
977 	return nurat_to_f(self);
978     div = rb_rational_div(self, other);
979     if (RB_TYPE_P(div, T_RATIONAL))
980 	return nurat_to_f(div);
981     if (RB_FLOAT_TYPE_P(div))
982 	return div;
983     return rb_funcall(div, idTo_f, 0);
984 }
985 
986 inline static VALUE
f_odd_p(VALUE integer)987 f_odd_p(VALUE integer)
988 {
989     if (rb_funcall(integer, '%', 1, INT2FIX(2)) != INT2FIX(0)) {
990 	return Qtrue;
991     }
992     return Qfalse;
993 }
994 
995 /*
996  * call-seq:
997  *    rat ** numeric  ->  numeric
998  *
999  * Performs exponentiation.
1000  *
1001  *    Rational(2)    ** Rational(3)     #=> (8/1)
1002  *    Rational(10)   ** -2              #=> (1/100)
1003  *    Rational(10)   ** -2.0            #=> 0.01
1004  *    Rational(-4)   ** Rational(1, 2)  #=> (0.0+2.0i)
1005  *    Rational(1, 2) ** 0               #=> (1/1)
1006  *    Rational(1, 2) ** 0.0             #=> 1.0
1007  */
1008 VALUE
rb_rational_pow(VALUE self,VALUE other)1009 rb_rational_pow(VALUE self, VALUE other)
1010 {
1011     if (k_numeric_p(other) && k_exact_zero_p(other))
1012 	return f_rational_new_bang1(CLASS_OF(self), ONE);
1013 
1014     if (k_rational_p(other)) {
1015 	get_dat1(other);
1016 
1017 	if (f_one_p(dat->den))
1018 	    other = dat->num; /* c14n */
1019     }
1020 
1021     /* Deal with special cases of 0**n and 1**n */
1022     if (k_numeric_p(other) && k_exact_p(other)) {
1023 	get_dat1(self);
1024 	if (f_one_p(dat->den)) {
1025 	    if (f_one_p(dat->num)) {
1026 		return f_rational_new_bang1(CLASS_OF(self), ONE);
1027 	    }
1028 	    else if (f_minus_one_p(dat->num) && RB_INTEGER_TYPE_P(other)) {
1029 		return f_rational_new_bang1(CLASS_OF(self), INT2FIX(f_odd_p(other) ? -1 : 1));
1030 	    }
1031 	    else if (INT_ZERO_P(dat->num)) {
1032 		if (rb_num_negative_p(other)) {
1033                     rb_num_zerodiv();
1034 		}
1035 		else {
1036 		    return f_rational_new_bang1(CLASS_OF(self), ZERO);
1037 		}
1038 	    }
1039 	}
1040     }
1041 
1042     /* General case */
1043     if (FIXNUM_P(other)) {
1044 	{
1045 	    VALUE num, den;
1046 
1047 	    get_dat1(self);
1048 
1049             if (INT_POSITIVE_P(other)) {
1050 		num = rb_int_pow(dat->num, other);
1051 		den = rb_int_pow(dat->den, other);
1052             }
1053             else if (INT_NEGATIVE_P(other)) {
1054 		num = rb_int_pow(dat->den, rb_int_uminus(other));
1055 		den = rb_int_pow(dat->num, rb_int_uminus(other));
1056             }
1057             else {
1058 		num = ONE;
1059 		den = ONE;
1060 	    }
1061 	    if (RB_FLOAT_TYPE_P(num)) { /* infinity due to overflow */
1062 		if (RB_FLOAT_TYPE_P(den))
1063 		    return DBL2NUM(nan(""));
1064 		return num;
1065 	    }
1066 	    if (RB_FLOAT_TYPE_P(den)) { /* infinity due to overflow */
1067 		num = ZERO;
1068 		den = ONE;
1069 	    }
1070 	    return f_rational_new2(CLASS_OF(self), num, den);
1071 	}
1072     }
1073     else if (RB_TYPE_P(other, T_BIGNUM)) {
1074 	rb_warn("in a**b, b may be too big");
1075 	return rb_float_pow(nurat_to_f(self), other);
1076     }
1077     else if (RB_FLOAT_TYPE_P(other) || RB_TYPE_P(other, T_RATIONAL)) {
1078 	return rb_float_pow(nurat_to_f(self), other);
1079     }
1080     else {
1081 	return rb_num_coerce_bin(self, other, rb_intern("**"));
1082     }
1083 }
1084 #define nurat_expt rb_rational_pow
1085 
1086 /*
1087  * call-seq:
1088  *    rational <=> numeric  ->  -1, 0, +1, or nil
1089  *
1090  * Returns -1, 0, or +1 depending on whether +rational+ is
1091  * less than, equal to, or greater than +numeric+.
1092  *
1093  * +nil+ is returned if the two values are incomparable.
1094  *
1095  *    Rational(2, 3) <=> Rational(2, 3)  #=> 0
1096  *    Rational(5)    <=> 5               #=> 0
1097  *    Rational(2, 3) <=> Rational(1, 3)  #=> 1
1098  *    Rational(1, 3) <=> 1               #=> -1
1099  *    Rational(1, 3) <=> 0.3             #=> 1
1100  *
1101  *    Rational(1, 3) <=> "0.3"           #=> nil
1102  */
1103 VALUE
rb_rational_cmp(VALUE self,VALUE other)1104 rb_rational_cmp(VALUE self, VALUE other)
1105 {
1106     if (RB_INTEGER_TYPE_P(other)) {
1107 	{
1108 	    get_dat1(self);
1109 
1110 	    if (dat->den == LONG2FIX(1))
1111 		return rb_int_cmp(dat->num, other); /* c14n */
1112 	    other = f_rational_new_bang1(CLASS_OF(self), other);
1113 	    goto other_is_rational;
1114 	}
1115     }
1116     else if (RB_FLOAT_TYPE_P(other)) {
1117 	return rb_dbl_cmp(nurat_to_double(self), RFLOAT_VALUE(other));
1118     }
1119     else if (RB_TYPE_P(other, T_RATIONAL)) {
1120 	other_is_rational:
1121 	{
1122 	    VALUE num1, num2;
1123 
1124 	    get_dat2(self, other);
1125 
1126 	    if (FIXNUM_P(adat->num) && FIXNUM_P(adat->den) &&
1127 		FIXNUM_P(bdat->num) && FIXNUM_P(bdat->den)) {
1128 		num1 = f_imul(FIX2LONG(adat->num), FIX2LONG(bdat->den));
1129 		num2 = f_imul(FIX2LONG(bdat->num), FIX2LONG(adat->den));
1130 	    }
1131 	    else {
1132 		num1 = rb_int_mul(adat->num, bdat->den);
1133 		num2 = rb_int_mul(bdat->num, adat->den);
1134 	    }
1135 	    return rb_int_cmp(rb_int_minus(num1, num2), ZERO);
1136 	}
1137     }
1138     else {
1139 	return rb_num_coerce_cmp(self, other, rb_intern("<=>"));
1140     }
1141 }
1142 
1143 /*
1144  * call-seq:
1145  *    rat == object  ->  true or false
1146  *
1147  * Returns +true+ if +rat+ equals +object+ numerically.
1148  *
1149  *    Rational(2, 3)  == Rational(2, 3)   #=> true
1150  *    Rational(5)     == 5                #=> true
1151  *    Rational(0)     == 0.0              #=> true
1152  *    Rational('1/3') == 0.33             #=> false
1153  *    Rational('1/2') == '1/2'            #=> false
1154  */
1155 static VALUE
nurat_eqeq_p(VALUE self,VALUE other)1156 nurat_eqeq_p(VALUE self, VALUE other)
1157 {
1158     if (RB_INTEGER_TYPE_P(other)) {
1159         get_dat1(self);
1160 
1161         if (RB_INTEGER_TYPE_P(dat->num) && RB_INTEGER_TYPE_P(dat->den)) {
1162 	    if (INT_ZERO_P(dat->num) && INT_ZERO_P(other))
1163 		return Qtrue;
1164 
1165 	    if (!FIXNUM_P(dat->den))
1166 		return Qfalse;
1167 	    if (FIX2LONG(dat->den) != 1)
1168 		return Qfalse;
1169 	    return rb_int_equal(dat->num, other);
1170 	}
1171         else {
1172             const double d = nurat_to_double(self);
1173             return f_boolcast(FIXNUM_ZERO_P(rb_dbl_cmp(d, NUM2DBL(other))));
1174         }
1175     }
1176     else if (RB_FLOAT_TYPE_P(other)) {
1177 	const double d = nurat_to_double(self);
1178 	return f_boolcast(FIXNUM_ZERO_P(rb_dbl_cmp(d, RFLOAT_VALUE(other))));
1179     }
1180     else if (RB_TYPE_P(other, T_RATIONAL)) {
1181 	{
1182 	    get_dat2(self, other);
1183 
1184 	    if (INT_ZERO_P(adat->num) && INT_ZERO_P(bdat->num))
1185 		return Qtrue;
1186 
1187 	    return f_boolcast(rb_int_equal(adat->num, bdat->num) &&
1188 			      rb_int_equal(adat->den, bdat->den));
1189 	}
1190     }
1191     else {
1192 	return rb_equal(other, self);
1193     }
1194 }
1195 
1196 /* :nodoc: */
1197 static VALUE
nurat_coerce(VALUE self,VALUE other)1198 nurat_coerce(VALUE self, VALUE other)
1199 {
1200     if (RB_INTEGER_TYPE_P(other)) {
1201 	return rb_assoc_new(f_rational_new_bang1(CLASS_OF(self), other), self);
1202     }
1203     else if (RB_FLOAT_TYPE_P(other)) {
1204         return rb_assoc_new(other, nurat_to_f(self));
1205     }
1206     else if (RB_TYPE_P(other, T_RATIONAL)) {
1207 	return rb_assoc_new(other, self);
1208     }
1209     else if (RB_TYPE_P(other, T_COMPLEX)) {
1210 	if (k_exact_zero_p(RCOMPLEX(other)->imag))
1211 	    return rb_assoc_new(f_rational_new_bang1
1212 				(CLASS_OF(self), RCOMPLEX(other)->real), self);
1213 	else
1214 	    return rb_assoc_new(other, rb_Complex(self, INT2FIX(0)));
1215     }
1216 
1217     rb_raise(rb_eTypeError, "%s can't be coerced into %s",
1218 	     rb_obj_classname(other), rb_obj_classname(self));
1219     return Qnil;
1220 }
1221 
1222 /*
1223  *  call-seq:
1224  *     rat.positive?  ->  true or false
1225  *
1226  *  Returns +true+ if +rat+ is greater than 0.
1227  */
1228 static VALUE
nurat_positive_p(VALUE self)1229 nurat_positive_p(VALUE self)
1230 {
1231     get_dat1(self);
1232     return f_boolcast(INT_POSITIVE_P(dat->num));
1233 }
1234 
1235 /*
1236  *  call-seq:
1237  *     rat.negative?  ->  true or false
1238  *
1239  *  Returns +true+ if +rat+ is less than 0.
1240  */
1241 static VALUE
nurat_negative_p(VALUE self)1242 nurat_negative_p(VALUE self)
1243 {
1244     get_dat1(self);
1245     return f_boolcast(INT_NEGATIVE_P(dat->num));
1246 }
1247 
1248 /*
1249  *  call-seq:
1250  *     rat.abs        ->  rational
1251  *     rat.magnitude  ->  rational
1252  *
1253  *  Returns the absolute value of +rat+.
1254  *
1255  *     (1/2r).abs    #=> (1/2)
1256  *     (-1/2r).abs   #=> (1/2)
1257  *
1258  *  Rational#magnitude is an alias for Rational#abs.
1259  */
1260 
1261 VALUE
rb_rational_abs(VALUE self)1262 rb_rational_abs(VALUE self)
1263 {
1264     get_dat1(self);
1265     if (INT_NEGATIVE_P(dat->num)) {
1266         VALUE num = rb_int_abs(dat->num);
1267         return nurat_s_canonicalize_internal_no_reduce(CLASS_OF(self), num, dat->den);
1268     }
1269     return self;
1270 }
1271 
1272 static VALUE
nurat_floor(VALUE self)1273 nurat_floor(VALUE self)
1274 {
1275     get_dat1(self);
1276     return rb_int_idiv(dat->num, dat->den);
1277 }
1278 
1279 static VALUE
nurat_ceil(VALUE self)1280 nurat_ceil(VALUE self)
1281 {
1282     get_dat1(self);
1283     return rb_int_uminus(rb_int_idiv(rb_int_uminus(dat->num), dat->den));
1284 }
1285 
1286 /*
1287  * call-seq:
1288  *    rat.to_i  ->  integer
1289  *
1290  * Returns the truncated value as an integer.
1291  *
1292  * Equivalent to Rational#truncate.
1293  *
1294  *    Rational(2, 3).to_i    #=> 0
1295  *    Rational(3).to_i       #=> 3
1296  *    Rational(300.6).to_i   #=> 300
1297  *    Rational(98, 71).to_i  #=> 1
1298  *    Rational(-31, 2).to_i  #=> -15
1299  */
1300 static VALUE
nurat_truncate(VALUE self)1301 nurat_truncate(VALUE self)
1302 {
1303     get_dat1(self);
1304     if (INT_NEGATIVE_P(dat->num))
1305 	return rb_int_uminus(rb_int_idiv(rb_int_uminus(dat->num), dat->den));
1306     return rb_int_idiv(dat->num, dat->den);
1307 }
1308 
1309 static VALUE
nurat_round_half_up(VALUE self)1310 nurat_round_half_up(VALUE self)
1311 {
1312     VALUE num, den, neg;
1313 
1314     get_dat1(self);
1315 
1316     num = dat->num;
1317     den = dat->den;
1318     neg = INT_NEGATIVE_P(num);
1319 
1320     if (neg)
1321 	num = rb_int_uminus(num);
1322 
1323     num = rb_int_plus(rb_int_mul(num, TWO), den);
1324     den = rb_int_mul(den, TWO);
1325     num = rb_int_idiv(num, den);
1326 
1327     if (neg)
1328 	num = rb_int_uminus(num);
1329 
1330     return num;
1331 }
1332 
1333 static VALUE
nurat_round_half_down(VALUE self)1334 nurat_round_half_down(VALUE self)
1335 {
1336     VALUE num, den, neg;
1337 
1338     get_dat1(self);
1339 
1340     num = dat->num;
1341     den = dat->den;
1342     neg = INT_NEGATIVE_P(num);
1343 
1344     if (neg)
1345 	num = rb_int_uminus(num);
1346 
1347     num = rb_int_plus(rb_int_mul(num, TWO), den);
1348     num = rb_int_minus(num, ONE);
1349     den = rb_int_mul(den, TWO);
1350     num = rb_int_idiv(num, den);
1351 
1352     if (neg)
1353 	num = rb_int_uminus(num);
1354 
1355     return num;
1356 }
1357 
1358 static VALUE
nurat_round_half_even(VALUE self)1359 nurat_round_half_even(VALUE self)
1360 {
1361     VALUE num, den, neg, qr;
1362 
1363     get_dat1(self);
1364 
1365     num = dat->num;
1366     den = dat->den;
1367     neg = INT_NEGATIVE_P(num);
1368 
1369     if (neg)
1370 	num = rb_int_uminus(num);
1371 
1372     num = rb_int_plus(rb_int_mul(num, TWO), den);
1373     den = rb_int_mul(den, TWO);
1374     qr = rb_int_divmod(num, den);
1375     num = RARRAY_AREF(qr, 0);
1376     if (INT_ZERO_P(RARRAY_AREF(qr, 1)))
1377 	num = rb_int_and(num, LONG2FIX(((int)~1)));
1378 
1379     if (neg)
1380 	num = rb_int_uminus(num);
1381 
1382     return num;
1383 }
1384 
1385 static VALUE
f_round_common(int argc,VALUE * argv,VALUE self,VALUE (* func)(VALUE))1386 f_round_common(int argc, VALUE *argv, VALUE self, VALUE (*func)(VALUE))
1387 {
1388     VALUE n, b, s;
1389 
1390     if (rb_check_arity(argc, 0, 1) == 0)
1391 	return (*func)(self);
1392 
1393     n = argv[0];
1394 
1395     if (!k_integer_p(n))
1396 	rb_raise(rb_eTypeError, "not an integer");
1397 
1398     b = f_expt10(n);
1399     s = rb_rational_mul(self, b);
1400 
1401     if (k_float_p(s)) {
1402 	if (INT_NEGATIVE_P(n))
1403 	    return ZERO;
1404 	return self;
1405     }
1406 
1407     if (!k_rational_p(s)) {
1408 	s = f_rational_new_bang1(CLASS_OF(self), s);
1409     }
1410 
1411     s = (*func)(s);
1412 
1413     s = rb_rational_div(f_rational_new_bang1(CLASS_OF(self), s), b);
1414 
1415     if (RB_TYPE_P(s, T_RATIONAL) && FIX2INT(rb_int_cmp(n, ONE)) < 0)
1416 	s = nurat_truncate(s);
1417 
1418     return s;
1419 }
1420 
1421 VALUE
rb_rational_floor(VALUE self,int ndigits)1422 rb_rational_floor(VALUE self, int ndigits)
1423 {
1424     if (ndigits == 0) {
1425         return nurat_floor(self);
1426     }
1427     else {
1428         VALUE n = INT2NUM(ndigits);
1429         return f_round_common(1, &n, self, nurat_floor);
1430     }
1431 }
1432 
1433 /*
1434  * call-seq:
1435  *    rat.floor([ndigits])  ->  integer or rational
1436  *
1437  * Returns the largest number less than or equal to +rat+ with
1438  * a precision of +ndigits+ decimal digits (default: 0).
1439  *
1440  * When the precision is negative, the returned value is an integer
1441  * with at least <code>ndigits.abs</code> trailing zeros.
1442  *
1443  * Returns a rational when +ndigits+ is positive,
1444  * otherwise returns an integer.
1445  *
1446  *    Rational(3).floor      #=> 3
1447  *    Rational(2, 3).floor   #=> 0
1448  *    Rational(-3, 2).floor  #=> -2
1449  *
1450  *      #    decimal      -  1  2  3 . 4  5  6
1451  *      #                   ^  ^  ^  ^   ^  ^
1452  *      #   precision      -3 -2 -1  0  +1 +2
1453  *
1454  *    Rational('-123.456').floor(+1).to_f  #=> -123.5
1455  *    Rational('-123.456').floor(-1)       #=> -130
1456  */
1457 static VALUE
nurat_floor_n(int argc,VALUE * argv,VALUE self)1458 nurat_floor_n(int argc, VALUE *argv, VALUE self)
1459 {
1460     return f_round_common(argc, argv, self, nurat_floor);
1461 }
1462 
1463 /*
1464  * call-seq:
1465  *    rat.ceil([ndigits])  ->  integer or rational
1466  *
1467  * Returns the smallest number greater than or equal to +rat+ with
1468  * a precision of +ndigits+ decimal digits (default: 0).
1469  *
1470  * When the precision is negative, the returned value is an integer
1471  * with at least <code>ndigits.abs</code> trailing zeros.
1472  *
1473  * Returns a rational when +ndigits+ is positive,
1474  * otherwise returns an integer.
1475  *
1476  *    Rational(3).ceil      #=> 3
1477  *    Rational(2, 3).ceil   #=> 1
1478  *    Rational(-3, 2).ceil  #=> -1
1479  *
1480  *      #    decimal      -  1  2  3 . 4  5  6
1481  *      #                   ^  ^  ^  ^   ^  ^
1482  *      #   precision      -3 -2 -1  0  +1 +2
1483  *
1484  *    Rational('-123.456').ceil(+1).to_f  #=> -123.4
1485  *    Rational('-123.456').ceil(-1)       #=> -120
1486  */
1487 static VALUE
nurat_ceil_n(int argc,VALUE * argv,VALUE self)1488 nurat_ceil_n(int argc, VALUE *argv, VALUE self)
1489 {
1490     return f_round_common(argc, argv, self, nurat_ceil);
1491 }
1492 
1493 /*
1494  * call-seq:
1495  *    rat.truncate([ndigits])  ->  integer or rational
1496  *
1497  * Returns +rat+ truncated (toward zero) to
1498  * a precision of +ndigits+ decimal digits (default: 0).
1499  *
1500  * When the precision is negative, the returned value is an integer
1501  * with at least <code>ndigits.abs</code> trailing zeros.
1502  *
1503  * Returns a rational when +ndigits+ is positive,
1504  * otherwise returns an integer.
1505  *
1506  *    Rational(3).truncate      #=> 3
1507  *    Rational(2, 3).truncate   #=> 0
1508  *    Rational(-3, 2).truncate  #=> -1
1509  *
1510  *      #    decimal      -  1  2  3 . 4  5  6
1511  *      #                   ^  ^  ^  ^   ^  ^
1512  *      #   precision      -3 -2 -1  0  +1 +2
1513  *
1514  *    Rational('-123.456').truncate(+1).to_f  #=> -123.4
1515  *    Rational('-123.456').truncate(-1)       #=> -120
1516  */
1517 static VALUE
nurat_truncate_n(int argc,VALUE * argv,VALUE self)1518 nurat_truncate_n(int argc, VALUE *argv, VALUE self)
1519 {
1520     return f_round_common(argc, argv, self, nurat_truncate);
1521 }
1522 
1523 /*
1524  * call-seq:
1525  *    rat.round([ndigits] [, half: mode])  ->  integer or rational
1526  *
1527  * Returns +rat+ rounded to the nearest value with
1528  * a precision of +ndigits+ decimal digits (default: 0).
1529  *
1530  * When the precision is negative, the returned value is an integer
1531  * with at least <code>ndigits.abs</code> trailing zeros.
1532  *
1533  * Returns a rational when +ndigits+ is positive,
1534  * otherwise returns an integer.
1535  *
1536  *    Rational(3).round      #=> 3
1537  *    Rational(2, 3).round   #=> 1
1538  *    Rational(-3, 2).round  #=> -2
1539  *
1540  *      #    decimal      -  1  2  3 . 4  5  6
1541  *      #                   ^  ^  ^  ^   ^  ^
1542  *      #   precision      -3 -2 -1  0  +1 +2
1543  *
1544  *    Rational('-123.456').round(+1).to_f  #=> -123.5
1545  *    Rational('-123.456').round(-1)       #=> -120
1546  *
1547  * The optional +half+ keyword argument is available
1548  * similar to Float#round.
1549  *
1550  *    Rational(25, 100).round(1, half: :up)    #=> (3/10)
1551  *    Rational(25, 100).round(1, half: :down)  #=> (1/5)
1552  *    Rational(25, 100).round(1, half: :even)  #=> (1/5)
1553  *    Rational(35, 100).round(1, half: :up)    #=> (2/5)
1554  *    Rational(35, 100).round(1, half: :down)  #=> (3/10)
1555  *    Rational(35, 100).round(1, half: :even)  #=> (2/5)
1556  *    Rational(-25, 100).round(1, half: :up)   #=> (-3/10)
1557  *    Rational(-25, 100).round(1, half: :down) #=> (-1/5)
1558  *    Rational(-25, 100).round(1, half: :even) #=> (-1/5)
1559  */
1560 static VALUE
nurat_round_n(int argc,VALUE * argv,VALUE self)1561 nurat_round_n(int argc, VALUE *argv, VALUE self)
1562 {
1563     VALUE opt;
1564     enum ruby_num_rounding_mode mode = (
1565 	argc = rb_scan_args(argc, argv, "*:", NULL, &opt),
1566 	rb_num_get_rounding_option(opt));
1567     VALUE (*round_func)(VALUE) = ROUND_FUNC(mode, nurat_round);
1568     return f_round_common(argc, argv, self, round_func);
1569 }
1570 
1571 static double
nurat_to_double(VALUE self)1572 nurat_to_double(VALUE self)
1573 {
1574     get_dat1(self);
1575     if (!RB_INTEGER_TYPE_P(dat->num) || !RB_INTEGER_TYPE_P(dat->den)) {
1576         return NUM2DBL(dat->num) / NUM2DBL(dat->den);
1577     }
1578     return rb_int_fdiv_double(dat->num, dat->den);
1579 }
1580 
1581 /*
1582  * call-seq:
1583  *    rat.to_f  ->  float
1584  *
1585  * Returns the value as a Float.
1586  *
1587  *    Rational(2).to_f      #=> 2.0
1588  *    Rational(9, 4).to_f   #=> 2.25
1589  *    Rational(-3, 4).to_f  #=> -0.75
1590  *    Rational(20, 3).to_f  #=> 6.666666666666667
1591  */
1592 static VALUE
nurat_to_f(VALUE self)1593 nurat_to_f(VALUE self)
1594 {
1595     return DBL2NUM(nurat_to_double(self));
1596 }
1597 
1598 /*
1599  * call-seq:
1600  *    rat.to_r  ->  self
1601  *
1602  * Returns self.
1603  *
1604  *    Rational(2).to_r      #=> (2/1)
1605  *    Rational(-8, 6).to_r  #=> (-4/3)
1606  */
1607 static VALUE
nurat_to_r(VALUE self)1608 nurat_to_r(VALUE self)
1609 {
1610     return self;
1611 }
1612 
1613 #define id_ceil rb_intern("ceil")
1614 #define f_ceil(x) rb_funcall((x), id_ceil, 0)
1615 
1616 #define id_quo rb_intern("quo")
1617 #define f_quo(x,y) rb_funcall((x), id_quo, 1, (y))
1618 
1619 #define f_reciprocal(x) f_quo(ONE, (x))
1620 
1621 /*
1622   The algorithm here is the method described in CLISP.  Bruno Haible has
1623   graciously given permission to use this algorithm.  He says, "You can use
1624   it, if you present the following explanation of the algorithm."
1625 
1626   Algorithm (recursively presented):
1627     If x is a rational number, return x.
1628     If x = 0.0, return 0.
1629     If x < 0.0, return (- (rationalize (- x))).
1630     If x > 0.0:
1631       Call (integer-decode-float x). It returns a m,e,s=1 (mantissa,
1632       exponent, sign).
1633       If m = 0 or e >= 0: return x = m*2^e.
1634       Search a rational number between a = (m-1/2)*2^e and b = (m+1/2)*2^e
1635       with smallest possible numerator and denominator.
1636       Note 1: If m is a power of 2, we ought to take a = (m-1/4)*2^e.
1637         But in this case the result will be x itself anyway, regardless of
1638         the choice of a. Therefore we can simply ignore this case.
1639       Note 2: At first, we need to consider the closed interval [a,b].
1640         but since a and b have the denominator 2^(|e|+1) whereas x itself
1641         has a denominator <= 2^|e|, we can restrict the search to the open
1642         interval (a,b).
1643       So, for given a and b (0 < a < b) we are searching a rational number
1644       y with a <= y <= b.
1645       Recursive algorithm fraction_between(a,b):
1646         c := (ceiling a)
1647         if c < b
1648           then return c       ; because a <= c < b, c integer
1649           else
1650             ; a is not integer (otherwise we would have had c = a < b)
1651             k := c-1          ; k = floor(a), k < a < b <= k+1
1652             return y = k + 1/fraction_between(1/(b-k), 1/(a-k))
1653                               ; note 1 <= 1/(b-k) < 1/(a-k)
1654 
1655   You can see that we are actually computing a continued fraction expansion.
1656 
1657   Algorithm (iterative):
1658     If x is rational, return x.
1659     Call (integer-decode-float x). It returns a m,e,s (mantissa,
1660       exponent, sign).
1661     If m = 0 or e >= 0, return m*2^e*s. (This includes the case x = 0.0.)
1662     Create rational numbers a := (2*m-1)*2^(e-1) and b := (2*m+1)*2^(e-1)
1663     (positive and already in lowest terms because the denominator is a
1664     power of two and the numerator is odd).
1665     Start a continued fraction expansion
1666       p[-1] := 0, p[0] := 1, q[-1] := 1, q[0] := 0, i := 0.
1667     Loop
1668       c := (ceiling a)
1669       if c >= b
1670         then k := c-1, partial_quotient(k), (a,b) := (1/(b-k),1/(a-k)),
1671              goto Loop
1672     finally partial_quotient(c).
1673     Here partial_quotient(c) denotes the iteration
1674       i := i+1, p[i] := c*p[i-1]+p[i-2], q[i] := c*q[i-1]+q[i-2].
1675     At the end, return s * (p[i]/q[i]).
1676     This rational number is already in lowest terms because
1677     p[i]*q[i-1]-p[i-1]*q[i] = (-1)^i.
1678 */
1679 
1680 static void
nurat_rationalize_internal(VALUE a,VALUE b,VALUE * p,VALUE * q)1681 nurat_rationalize_internal(VALUE a, VALUE b, VALUE *p, VALUE *q)
1682 {
1683     VALUE c, k, t, p0, p1, p2, q0, q1, q2;
1684 
1685     p0 = ZERO;
1686     p1 = ONE;
1687     q0 = ONE;
1688     q1 = ZERO;
1689 
1690     while (1) {
1691 	c = f_ceil(a);
1692 	if (f_lt_p(c, b))
1693 	    break;
1694 	k = f_sub(c, ONE);
1695 	p2 = f_add(f_mul(k, p1), p0);
1696 	q2 = f_add(f_mul(k, q1), q0);
1697 	t = f_reciprocal(f_sub(b, k));
1698 	b = f_reciprocal(f_sub(a, k));
1699 	a = t;
1700 	p0 = p1;
1701 	q0 = q1;
1702 	p1 = p2;
1703 	q1 = q2;
1704     }
1705     *p = f_add(f_mul(c, p1), p0);
1706     *q = f_add(f_mul(c, q1), q0);
1707 }
1708 
1709 /*
1710  * call-seq:
1711  *    rat.rationalize       ->  self
1712  *    rat.rationalize(eps)  ->  rational
1713  *
1714  * Returns a simpler approximation of the value if the optional
1715  * argument +eps+ is given (rat-|eps| <= result <= rat+|eps|),
1716  * self otherwise.
1717  *
1718  *    r = Rational(5033165, 16777216)
1719  *    r.rationalize                    #=> (5033165/16777216)
1720  *    r.rationalize(Rational('0.01'))  #=> (3/10)
1721  *    r.rationalize(Rational('0.1'))   #=> (1/3)
1722  */
1723 static VALUE
nurat_rationalize(int argc,VALUE * argv,VALUE self)1724 nurat_rationalize(int argc, VALUE *argv, VALUE self)
1725 {
1726     VALUE e, a, b, p, q;
1727 
1728     if (rb_check_arity(argc, 0, 1) == 0)
1729 	return self;
1730 
1731     if (nurat_negative_p(self))
1732 	return rb_rational_uminus(nurat_rationalize(argc, argv, rb_rational_uminus(self)));
1733 
1734     e = f_abs(argv[0]);
1735     a = f_sub(self, e);
1736     b = f_add(self, e);
1737 
1738     if (f_eqeq_p(a, b))
1739 	return self;
1740 
1741     nurat_rationalize_internal(a, b, &p, &q);
1742     return f_rational_new2(CLASS_OF(self), p, q);
1743 }
1744 
1745 /* :nodoc: */
1746 static VALUE
nurat_hash(VALUE self)1747 nurat_hash(VALUE self)
1748 {
1749     st_index_t v, h[2];
1750     VALUE n;
1751 
1752     get_dat1(self);
1753     n = rb_hash(dat->num);
1754     h[0] = NUM2LONG(n);
1755     n = rb_hash(dat->den);
1756     h[1] = NUM2LONG(n);
1757     v = rb_memhash(h, sizeof(h));
1758     return ST2FIX(v);
1759 }
1760 
1761 static VALUE
f_format(VALUE self,VALUE (* func)(VALUE))1762 f_format(VALUE self, VALUE (*func)(VALUE))
1763 {
1764     VALUE s;
1765     get_dat1(self);
1766 
1767     s = (*func)(dat->num);
1768     rb_str_cat2(s, "/");
1769     rb_str_concat(s, (*func)(dat->den));
1770 
1771     return s;
1772 }
1773 
1774 /*
1775  * call-seq:
1776  *    rat.to_s  ->  string
1777  *
1778  * Returns the value as a string.
1779  *
1780  *    Rational(2).to_s      #=> "2/1"
1781  *    Rational(-8, 6).to_s  #=> "-4/3"
1782  *    Rational('1/2').to_s  #=> "1/2"
1783  */
1784 static VALUE
nurat_to_s(VALUE self)1785 nurat_to_s(VALUE self)
1786 {
1787     return f_format(self, f_to_s);
1788 }
1789 
1790 /*
1791  * call-seq:
1792  *    rat.inspect  ->  string
1793  *
1794  * Returns the value as a string for inspection.
1795  *
1796  *    Rational(2).inspect      #=> "(2/1)"
1797  *    Rational(-8, 6).inspect  #=> "(-4/3)"
1798  *    Rational('1/2').inspect  #=> "(1/2)"
1799  */
1800 static VALUE
nurat_inspect(VALUE self)1801 nurat_inspect(VALUE self)
1802 {
1803     VALUE s;
1804 
1805     s = rb_usascii_str_new2("(");
1806     rb_str_concat(s, f_format(self, f_inspect));
1807     rb_str_cat2(s, ")");
1808 
1809     return s;
1810 }
1811 
1812 /* :nodoc: */
1813 static VALUE
nurat_dumper(VALUE self)1814 nurat_dumper(VALUE self)
1815 {
1816     return self;
1817 }
1818 
1819 /* :nodoc: */
1820 static VALUE
nurat_loader(VALUE self,VALUE a)1821 nurat_loader(VALUE self, VALUE a)
1822 {
1823     VALUE num, den;
1824 
1825     get_dat1(self);
1826     num = rb_ivar_get(a, id_i_num);
1827     den = rb_ivar_get(a, id_i_den);
1828     nurat_int_check(num);
1829     nurat_int_check(den);
1830     nurat_canonicalize(&num, &den);
1831     RRATIONAL_SET_NUM(dat, num);
1832     RRATIONAL_SET_DEN(dat, den);
1833     OBJ_FREEZE_RAW(self);
1834 
1835     return self;
1836 }
1837 
1838 /* :nodoc: */
1839 static VALUE
nurat_marshal_dump(VALUE self)1840 nurat_marshal_dump(VALUE self)
1841 {
1842     VALUE a;
1843     get_dat1(self);
1844 
1845     a = rb_assoc_new(dat->num, dat->den);
1846     rb_copy_generic_ivar(a, self);
1847     return a;
1848 }
1849 
1850 /* :nodoc: */
1851 static VALUE
nurat_marshal_load(VALUE self,VALUE a)1852 nurat_marshal_load(VALUE self, VALUE a)
1853 {
1854     VALUE num, den;
1855 
1856     rb_check_frozen(self);
1857     rb_check_trusted(self);
1858 
1859     Check_Type(a, T_ARRAY);
1860     if (RARRAY_LEN(a) != 2)
1861 	rb_raise(rb_eArgError, "marshaled rational must have an array whose length is 2 but %ld", RARRAY_LEN(a));
1862 
1863     num = RARRAY_AREF(a, 0);
1864     den = RARRAY_AREF(a, 1);
1865     nurat_int_check(num);
1866     nurat_int_check(den);
1867     nurat_canonicalize(&num, &den);
1868     rb_ivar_set(self, id_i_num, num);
1869     rb_ivar_set(self, id_i_den, den);
1870 
1871     return self;
1872 }
1873 
1874 /* --- */
1875 
1876 VALUE
rb_rational_reciprocal(VALUE x)1877 rb_rational_reciprocal(VALUE x)
1878 {
1879     get_dat1(x);
1880     return nurat_convert(CLASS_OF(x), dat->den, dat->num, FALSE);
1881 }
1882 
1883 /*
1884  * call-seq:
1885  *    int.gcd(other_int)  ->  integer
1886  *
1887  * Returns the greatest common divisor of the two integers.
1888  * The result is always positive. 0.gcd(x) and x.gcd(0) return x.abs.
1889  *
1890  *    36.gcd(60)                  #=> 12
1891  *    2.gcd(2)                    #=> 2
1892  *    3.gcd(-7)                   #=> 1
1893  *    ((1<<31)-1).gcd((1<<61)-1)  #=> 1
1894  */
1895 VALUE
rb_gcd(VALUE self,VALUE other)1896 rb_gcd(VALUE self, VALUE other)
1897 {
1898     other = nurat_int_value(other);
1899     return f_gcd(self, other);
1900 }
1901 
1902 /*
1903  * call-seq:
1904  *    int.lcm(other_int)  ->  integer
1905  *
1906  * Returns the least common multiple of the two integers.
1907  * The result is always positive. 0.lcm(x) and x.lcm(0) return zero.
1908  *
1909  *    36.lcm(60)                  #=> 180
1910  *    2.lcm(2)                    #=> 2
1911  *    3.lcm(-7)                   #=> 21
1912  *    ((1<<31)-1).lcm((1<<61)-1)  #=> 4951760154835678088235319297
1913  */
1914 VALUE
rb_lcm(VALUE self,VALUE other)1915 rb_lcm(VALUE self, VALUE other)
1916 {
1917     other = nurat_int_value(other);
1918     return f_lcm(self, other);
1919 }
1920 
1921 /*
1922  * call-seq:
1923  *    int.gcdlcm(other_int)  ->  array
1924  *
1925  * Returns an array with the greatest common divisor and
1926  * the least common multiple of the two integers, [gcd, lcm].
1927  *
1928  *    36.gcdlcm(60)                  #=> [12, 180]
1929  *    2.gcdlcm(2)                    #=> [2, 2]
1930  *    3.gcdlcm(-7)                   #=> [1, 21]
1931  *    ((1<<31)-1).gcdlcm((1<<61)-1)  #=> [1, 4951760154835678088235319297]
1932  */
1933 VALUE
rb_gcdlcm(VALUE self,VALUE other)1934 rb_gcdlcm(VALUE self, VALUE other)
1935 {
1936     other = nurat_int_value(other);
1937     return rb_assoc_new(f_gcd(self, other), f_lcm(self, other));
1938 }
1939 
1940 VALUE
rb_rational_raw(VALUE x,VALUE y)1941 rb_rational_raw(VALUE x, VALUE y)
1942 {
1943     return nurat_s_new_internal(rb_cRational, x, y);
1944 }
1945 
1946 VALUE
rb_rational_new(VALUE x,VALUE y)1947 rb_rational_new(VALUE x, VALUE y)
1948 {
1949     return nurat_s_canonicalize_internal(rb_cRational, x, y);
1950 }
1951 
1952 VALUE
rb_Rational(VALUE x,VALUE y)1953 rb_Rational(VALUE x, VALUE y)
1954 {
1955     VALUE a[2];
1956     a[0] = x;
1957     a[1] = y;
1958     return nurat_s_convert(2, a, rb_cRational);
1959 }
1960 
1961 VALUE
rb_rational_num(VALUE rat)1962 rb_rational_num(VALUE rat)
1963 {
1964     return nurat_numerator(rat);
1965 }
1966 
1967 VALUE
rb_rational_den(VALUE rat)1968 rb_rational_den(VALUE rat)
1969 {
1970     return nurat_denominator(rat);
1971 }
1972 
1973 #define id_numerator rb_intern("numerator")
1974 #define f_numerator(x) rb_funcall((x), id_numerator, 0)
1975 
1976 #define id_denominator rb_intern("denominator")
1977 #define f_denominator(x) rb_funcall((x), id_denominator, 0)
1978 
1979 #define id_to_r idTo_r
1980 #define f_to_r(x) rb_funcall((x), id_to_r, 0)
1981 
1982 /*
1983  * call-seq:
1984  *    num.numerator  ->  integer
1985  *
1986  * Returns the numerator.
1987  */
1988 static VALUE
numeric_numerator(VALUE self)1989 numeric_numerator(VALUE self)
1990 {
1991     return f_numerator(f_to_r(self));
1992 }
1993 
1994 /*
1995  * call-seq:
1996  *    num.denominator  ->  integer
1997  *
1998  * Returns the denominator (always positive).
1999  */
2000 static VALUE
numeric_denominator(VALUE self)2001 numeric_denominator(VALUE self)
2002 {
2003     return f_denominator(f_to_r(self));
2004 }
2005 
2006 
2007 /*
2008  *  call-seq:
2009  *     num.quo(int_or_rat)   ->  rat
2010  *     num.quo(flo)          ->  flo
2011  *
2012  *  Returns the most exact division (rational for integers, float for floats).
2013  */
2014 
2015 VALUE
rb_numeric_quo(VALUE x,VALUE y)2016 rb_numeric_quo(VALUE x, VALUE y)
2017 {
2018     if (RB_FLOAT_TYPE_P(y)) {
2019         return rb_funcall(x, rb_intern("fdiv"), 1, y);
2020     }
2021 
2022     if (canonicalization) {
2023         x = rb_rational_raw1(x);
2024     }
2025     else {
2026         x = rb_convert_type(x, T_RATIONAL, "Rational", "to_r");
2027     }
2028     return rb_rational_div(x, y);
2029 }
2030 
2031 VALUE
rb_rational_canonicalize(VALUE x)2032 rb_rational_canonicalize(VALUE x)
2033 {
2034     if (RB_TYPE_P(x, T_RATIONAL)) {
2035         get_dat1(x);
2036         if (f_one_p(dat->den)) return dat->num;
2037     }
2038     return x;
2039 }
2040 
2041 /*
2042  * call-seq:
2043  *    int.numerator  ->  self
2044  *
2045  * Returns self.
2046  */
2047 static VALUE
integer_numerator(VALUE self)2048 integer_numerator(VALUE self)
2049 {
2050     return self;
2051 }
2052 
2053 /*
2054  * call-seq:
2055  *    int.denominator  ->  1
2056  *
2057  * Returns 1.
2058  */
2059 static VALUE
integer_denominator(VALUE self)2060 integer_denominator(VALUE self)
2061 {
2062     return INT2FIX(1);
2063 }
2064 
2065 static VALUE float_to_r(VALUE self);
2066 /*
2067  * call-seq:
2068  *    flo.numerator  ->  integer
2069  *
2070  * Returns the numerator.  The result is machine dependent.
2071  *
2072  *    n = 0.3.numerator    #=> 5404319552844595
2073  *    d = 0.3.denominator  #=> 18014398509481984
2074  *    n.fdiv(d)            #=> 0.3
2075  *
2076  * See also Float#denominator.
2077  */
2078 static VALUE
float_numerator(VALUE self)2079 float_numerator(VALUE self)
2080 {
2081     double d = RFLOAT_VALUE(self);
2082     VALUE r;
2083     if (isinf(d) || isnan(d))
2084 	return self;
2085     r = float_to_r(self);
2086     if (canonicalization && k_integer_p(r)) {
2087 	return r;
2088     }
2089     return nurat_numerator(r);
2090 }
2091 
2092 /*
2093  * call-seq:
2094  *    flo.denominator  ->  integer
2095  *
2096  * Returns the denominator (always positive).  The result is machine
2097  * dependent.
2098  *
2099  * See also Float#numerator.
2100  */
2101 static VALUE
float_denominator(VALUE self)2102 float_denominator(VALUE self)
2103 {
2104     double d = RFLOAT_VALUE(self);
2105     VALUE r;
2106     if (isinf(d) || isnan(d))
2107 	return INT2FIX(1);
2108     r = float_to_r(self);
2109     if (canonicalization && k_integer_p(r)) {
2110 	return ONE;
2111     }
2112     return nurat_denominator(r);
2113 }
2114 
2115 /*
2116  * call-seq:
2117  *    nil.to_r  ->  (0/1)
2118  *
2119  * Returns zero as a rational.
2120  */
2121 static VALUE
nilclass_to_r(VALUE self)2122 nilclass_to_r(VALUE self)
2123 {
2124     return rb_rational_new1(INT2FIX(0));
2125 }
2126 
2127 /*
2128  * call-seq:
2129  *    nil.rationalize([eps])  ->  (0/1)
2130  *
2131  * Returns zero as a rational.  The optional argument +eps+ is always
2132  * ignored.
2133  */
2134 static VALUE
nilclass_rationalize(int argc,VALUE * argv,VALUE self)2135 nilclass_rationalize(int argc, VALUE *argv, VALUE self)
2136 {
2137     rb_check_arity(argc, 0, 1);
2138     return nilclass_to_r(self);
2139 }
2140 
2141 /*
2142  * call-seq:
2143  *    int.to_r  ->  rational
2144  *
2145  * Returns the value as a rational.
2146  *
2147  *    1.to_r        #=> (1/1)
2148  *    (1<<64).to_r  #=> (18446744073709551616/1)
2149  */
2150 static VALUE
integer_to_r(VALUE self)2151 integer_to_r(VALUE self)
2152 {
2153     return rb_rational_new1(self);
2154 }
2155 
2156 /*
2157  * call-seq:
2158  *    int.rationalize([eps])  ->  rational
2159  *
2160  * Returns the value as a rational.  The optional argument +eps+ is
2161  * always ignored.
2162  */
2163 static VALUE
integer_rationalize(int argc,VALUE * argv,VALUE self)2164 integer_rationalize(int argc, VALUE *argv, VALUE self)
2165 {
2166     rb_check_arity(argc, 0, 1);
2167     return integer_to_r(self);
2168 }
2169 
2170 static void
float_decode_internal(VALUE self,VALUE * rf,VALUE * rn)2171 float_decode_internal(VALUE self, VALUE *rf, VALUE *rn)
2172 {
2173     double f;
2174     int n;
2175 
2176     f = frexp(RFLOAT_VALUE(self), &n);
2177     f = ldexp(f, DBL_MANT_DIG);
2178     n -= DBL_MANT_DIG;
2179     *rf = rb_dbl2big(f);
2180     *rn = INT2FIX(n);
2181 }
2182 
2183 /*
2184  * call-seq:
2185  *    flt.to_r  ->  rational
2186  *
2187  * Returns the value as a rational.
2188  *
2189  *    2.0.to_r    #=> (2/1)
2190  *    2.5.to_r    #=> (5/2)
2191  *    -0.75.to_r  #=> (-3/4)
2192  *    0.0.to_r    #=> (0/1)
2193  *    0.3.to_r    #=> (5404319552844595/18014398509481984)
2194  *
2195  * NOTE: 0.3.to_r isn't the same as "0.3".to_r.  The latter is
2196  * equivalent to "3/10".to_r, but the former isn't so.
2197  *
2198  *    0.3.to_r   == 3/10r  #=> false
2199  *    "0.3".to_r == 3/10r  #=> true
2200  *
2201  * See also Float#rationalize.
2202  */
2203 static VALUE
float_to_r(VALUE self)2204 float_to_r(VALUE self)
2205 {
2206     VALUE f, n;
2207 
2208     float_decode_internal(self, &f, &n);
2209 #if FLT_RADIX == 2
2210     {
2211 	long ln = FIX2LONG(n);
2212 
2213 	if (ln == 0)
2214 	    return rb_rational_new1(f);
2215 	if (ln > 0)
2216 	    return rb_rational_new1(rb_int_lshift(f, n));
2217 	ln = -ln;
2218 	return rb_rational_new2(f, rb_int_lshift(ONE, INT2FIX(ln)));
2219     }
2220 #else
2221     f = rb_int_mul(f, rb_int_pow(INT2FIX(FLT_RADIX), n));
2222     if (RB_TYPE_P(f, T_RATIONAL))
2223 	return f;
2224     return rb_rational_new1(f);
2225 #endif
2226 }
2227 
2228 VALUE
rb_flt_rationalize_with_prec(VALUE flt,VALUE prec)2229 rb_flt_rationalize_with_prec(VALUE flt, VALUE prec)
2230 {
2231     VALUE e, a, b, p, q;
2232 
2233     e = f_abs(prec);
2234     a = f_sub(flt, e);
2235     b = f_add(flt, e);
2236 
2237     if (f_eqeq_p(a, b))
2238         return float_to_r(flt);
2239 
2240     nurat_rationalize_internal(a, b, &p, &q);
2241     return rb_rational_new2(p, q);
2242 }
2243 
2244 VALUE
rb_flt_rationalize(VALUE flt)2245 rb_flt_rationalize(VALUE flt)
2246 {
2247     VALUE a, b, f, n, p, q;
2248 
2249     float_decode_internal(flt, &f, &n);
2250     if (INT_ZERO_P(f) || FIX2INT(n) >= 0)
2251         return rb_rational_new1(rb_int_lshift(f, n));
2252 
2253 #if FLT_RADIX == 2
2254     {
2255         VALUE two_times_f, den;
2256 
2257         two_times_f = rb_int_mul(TWO, f);
2258         den = rb_int_lshift(ONE, rb_int_minus(ONE, n));
2259 
2260         a = rb_rational_new2(rb_int_minus(two_times_f, ONE), den);
2261         b = rb_rational_new2(rb_int_plus(two_times_f, ONE), den);
2262     }
2263 #else
2264     {
2265         VALUE radix_times_f, den;
2266 
2267         radix_times_f = rb_int_mul(INT2FIX(FLT_RADIX), f);
2268         den = rb_int_pow(INT2FIX(FLT_RADIX), rb_int_minus(ONE, n));
2269 
2270         a = rb_rational_new2(rb_int_minus(radix_times_f, INT2FIX(FLT_RADIX - 1)), den);
2271         b = rb_rational_new2(rb_int_plus(radix_times_f, INT2FIX(FLT_RADIX - 1)), den);
2272     }
2273 #endif
2274 
2275     if (nurat_eqeq_p(a, b))
2276         return float_to_r(flt);
2277 
2278     nurat_rationalize_internal(a, b, &p, &q);
2279     return rb_rational_new2(p, q);
2280 }
2281 
2282 /*
2283  * call-seq:
2284  *    flt.rationalize([eps])  ->  rational
2285  *
2286  * Returns a simpler approximation of the value (flt-|eps| <= result
2287  * <= flt+|eps|).  If the optional argument +eps+ is not given,
2288  * it will be chosen automatically.
2289  *
2290  *    0.3.rationalize          #=> (3/10)
2291  *    1.333.rationalize        #=> (1333/1000)
2292  *    1.333.rationalize(0.01)  #=> (4/3)
2293  *
2294  * See also Float#to_r.
2295  */
2296 static VALUE
float_rationalize(int argc,VALUE * argv,VALUE self)2297 float_rationalize(int argc, VALUE *argv, VALUE self)
2298 {
2299     double d = RFLOAT_VALUE(self);
2300 
2301     if (d < 0.0)
2302         return rb_rational_uminus(float_rationalize(argc, argv, DBL2NUM(-d)));
2303 
2304     if (rb_check_arity(argc, 0, 1)) {
2305         return rb_flt_rationalize_with_prec(self, argv[0]);
2306     }
2307     else {
2308         return rb_flt_rationalize(self);
2309     }
2310 }
2311 
2312 #include <ctype.h>
2313 
2314 inline static int
issign(int c)2315 issign(int c)
2316 {
2317     return (c == '-' || c == '+');
2318 }
2319 
2320 static int
read_sign(const char ** s,const char * const e)2321 read_sign(const char **s, const char *const e)
2322 {
2323     int sign = '?';
2324 
2325     if (*s < e && issign(**s)) {
2326 	sign = **s;
2327 	(*s)++;
2328     }
2329     return sign;
2330 }
2331 
2332 inline static int
islettere(int c)2333 islettere(int c)
2334 {
2335     return (c == 'e' || c == 'E');
2336 }
2337 
2338 static VALUE
negate_num(VALUE num)2339 negate_num(VALUE num)
2340 {
2341     if (FIXNUM_P(num)) {
2342 	return rb_int_uminus(num);
2343     }
2344     else {
2345 	BIGNUM_NEGATE(num);
2346 	return rb_big_norm(num);
2347     }
2348 }
2349 
2350 static int
read_num(const char ** s,const char * const end,VALUE * num,VALUE * nexp)2351 read_num(const char **s, const char *const end, VALUE *num, VALUE *nexp)
2352 {
2353     VALUE fp = ONE, exp, fn = ZERO, n = ZERO;
2354     int expsign = 0, ok = 0;
2355     char *e;
2356 
2357     *nexp = ZERO;
2358     *num = ZERO;
2359     if (*s < end && **s != '.') {
2360 	n = rb_int_parse_cstr(*s, end-*s, &e, NULL,
2361 			      10, RB_INT_PARSE_UNDERSCORE);
2362 	if (NIL_P(n))
2363 	    return 0;
2364 	*s = e;
2365 	*num = n;
2366 	ok = 1;
2367     }
2368 
2369     if (*s < end && **s == '.') {
2370 	size_t count = 0;
2371 
2372 	(*s)++;
2373 	fp = rb_int_parse_cstr(*s, end-*s, &e, &count,
2374 			       10, RB_INT_PARSE_UNDERSCORE);
2375 	if (NIL_P(fp))
2376 	    return 1;
2377 	*s = e;
2378 	{
2379             VALUE l = f_expt10(*nexp = SIZET2NUM(count));
2380 	    n = n == ZERO ? fp : rb_int_plus(rb_int_mul(*num, l), fp);
2381 	    *num = n;
2382 	    fn = SIZET2NUM(count);
2383 	}
2384 	ok = 1;
2385     }
2386 
2387     if (ok && *s + 1 < end && islettere(**s)) {
2388 	(*s)++;
2389 	expsign = read_sign(s, end);
2390 	exp = rb_int_parse_cstr(*s, end-*s, &e, NULL,
2391 				10, RB_INT_PARSE_UNDERSCORE);
2392 	if (NIL_P(exp))
2393 	    return 1;
2394 	*s = e;
2395 	if (exp != ZERO) {
2396 	    if (expsign == '-') {
2397 		if (fn != ZERO) exp = rb_int_plus(exp, fn);
2398 	    }
2399 	    else {
2400 		if (fn != ZERO) exp = rb_int_minus(exp, fn);
2401                 exp = negate_num(exp);
2402 	    }
2403             *nexp = exp;
2404 	}
2405     }
2406 
2407     return ok;
2408 }
2409 
2410 inline static const char *
skip_ws(const char * s,const char * e)2411 skip_ws(const char *s, const char *e)
2412 {
2413     while (s < e && isspace((unsigned char)*s))
2414 	++s;
2415     return s;
2416 }
2417 
2418 static VALUE
parse_rat(const char * s,const char * const e,int strict,int raise)2419 parse_rat(const char *s, const char *const e, int strict, int raise)
2420 {
2421     int sign;
2422     VALUE num, den, nexp, dexp;
2423 
2424     s = skip_ws(s, e);
2425     sign = read_sign(&s, e);
2426 
2427     if (!read_num(&s, e, &num, &nexp)) {
2428 	if (strict) return Qnil;
2429 	return canonicalization ? ZERO : nurat_s_alloc(rb_cRational);
2430     }
2431     den = ONE;
2432     if (s < e && *s == '/') {
2433 	s++;
2434         if (!read_num(&s, e, &den, &dexp)) {
2435 	    if (strict) return Qnil;
2436             den = ONE;
2437 	}
2438 	else if (den == ZERO) {
2439             if (!raise) return Qnil;
2440 	    rb_num_zerodiv();
2441 	}
2442 	else if (strict && skip_ws(s, e) != e) {
2443 	    return Qnil;
2444 	}
2445 	else {
2446             nexp = rb_int_minus(nexp, dexp);
2447 	    nurat_reduce(&num, &den);
2448 	}
2449     }
2450     else if (strict && skip_ws(s, e) != e) {
2451 	return Qnil;
2452     }
2453 
2454     if (nexp != ZERO) {
2455         if (INT_NEGATIVE_P(nexp)) {
2456             VALUE mul;
2457             if (!FIXNUM_P(nexp)) {
2458               overflow:
2459                 return sign == '-' ? DBL2NUM(-HUGE_VAL) : DBL2NUM(HUGE_VAL);
2460             }
2461             mul = f_expt10(LONG2NUM(-FIX2LONG(nexp)));
2462             if (RB_FLOAT_TYPE_P(mul)) goto overflow;
2463             num = rb_int_mul(num, mul);
2464         }
2465         else {
2466             VALUE div;
2467             if (!FIXNUM_P(nexp)) {
2468               underflow:
2469                 return sign == '-' ? DBL2NUM(-0.0) : DBL2NUM(+0.0);
2470             }
2471             div = f_expt10(nexp);
2472             if (RB_FLOAT_TYPE_P(div)) goto underflow;
2473             den = rb_int_mul(den, div);
2474         }
2475         nurat_reduce(&num, &den);
2476     }
2477 
2478     if (sign == '-') {
2479 	num = negate_num(num);
2480     }
2481 
2482     if (!canonicalization || den != ONE)
2483 	num = rb_rational_raw(num, den);
2484     return num;
2485 }
2486 
2487 #define FLOAT_ZERO_P(x) (rb_float_value(x) == 0.0)
2488 
2489 static VALUE
string_to_r_strict(VALUE self,int raise)2490 string_to_r_strict(VALUE self, int raise)
2491 {
2492     VALUE num;
2493 
2494     rb_must_asciicompat(self);
2495 
2496     num = parse_rat(RSTRING_PTR(self), RSTRING_END(self), 1, raise);
2497     if (NIL_P(num)) {
2498         if (!raise) return Qnil;
2499         rb_raise(rb_eArgError, "invalid value for convert(): %+"PRIsVALUE,
2500                  self);
2501     }
2502 
2503     if (RB_FLOAT_TYPE_P(num) && !FLOAT_ZERO_P(num)) {
2504         if (!raise) return Qnil;
2505         rb_raise(rb_eFloatDomainError, "Infinity");
2506     }
2507     return num;
2508 }
2509 
2510 /*
2511  * call-seq:
2512  *    str.to_r  ->  rational
2513  *
2514  * Returns the result of interpreting leading characters in +str+
2515  * as a rational.  Leading whitespace and extraneous characters
2516  * past the end of a valid number are ignored.
2517  * Digit sequences can be separated by an underscore.
2518  * If there is not a valid number at the start of +str+,
2519  * zero is returned.  This method never raises an exception.
2520  *
2521  *    '  2  '.to_r       #=> (2/1)
2522  *    '300/2'.to_r       #=> (150/1)
2523  *    '-9.2'.to_r        #=> (-46/5)
2524  *    '-9.2e2'.to_r      #=> (-920/1)
2525  *    '1_234_567'.to_r   #=> (1234567/1)
2526  *    '21 June 09'.to_r  #=> (21/1)
2527  *    '21/06/09'.to_r    #=> (7/2)
2528  *    'BWV 1079'.to_r    #=> (0/1)
2529  *
2530  * NOTE: "0.3".to_r isn't the same as 0.3.to_r.  The former is
2531  * equivalent to "3/10".to_r, but the latter isn't so.
2532  *
2533  *    "0.3".to_r == 3/10r  #=> true
2534  *    0.3.to_r   == 3/10r  #=> false
2535  *
2536  * See also Kernel#Rational.
2537  */
2538 static VALUE
string_to_r(VALUE self)2539 string_to_r(VALUE self)
2540 {
2541     VALUE num;
2542 
2543     rb_must_asciicompat(self);
2544 
2545     num = parse_rat(RSTRING_PTR(self), RSTRING_END(self), 0, TRUE);
2546 
2547     if (RB_FLOAT_TYPE_P(num) && !FLOAT_ZERO_P(num))
2548 	rb_raise(rb_eFloatDomainError, "Infinity");
2549     return num;
2550 }
2551 
2552 VALUE
rb_cstr_to_rat(const char * s,int strict)2553 rb_cstr_to_rat(const char *s, int strict) /* for complex's internal */
2554 {
2555     VALUE num;
2556 
2557     num = parse_rat(s, s + strlen(s), strict, TRUE);
2558 
2559     if (RB_FLOAT_TYPE_P(num) && !FLOAT_ZERO_P(num))
2560 	rb_raise(rb_eFloatDomainError, "Infinity");
2561     return num;
2562 }
2563 
2564 static VALUE
to_rational(VALUE val)2565 to_rational(VALUE val)
2566 {
2567     return rb_convert_type_with_id(val, T_RATIONAL, "Rational", idTo_r);
2568 }
2569 
2570 static VALUE
nurat_convert(VALUE klass,VALUE numv,VALUE denv,int raise)2571 nurat_convert(VALUE klass, VALUE numv, VALUE denv, int raise)
2572 {
2573     VALUE a1 = numv, a2 = denv;
2574     int state;
2575 
2576     if (NIL_P(a1) || NIL_P(a2)) {
2577         if (!raise) return Qnil;
2578         rb_raise(rb_eTypeError, "can't convert nil into Rational");
2579     }
2580 
2581     if (RB_TYPE_P(a1, T_COMPLEX)) {
2582         if (k_exact_zero_p(RCOMPLEX(a1)->imag))
2583             a1 = RCOMPLEX(a1)->real;
2584     }
2585 
2586     if (RB_TYPE_P(a2, T_COMPLEX)) {
2587         if (k_exact_zero_p(RCOMPLEX(a2)->imag))
2588             a2 = RCOMPLEX(a2)->real;
2589     }
2590 
2591     if (RB_FLOAT_TYPE_P(a1)) {
2592         a1 = float_to_r(a1);
2593     }
2594     else if (RB_TYPE_P(a1, T_STRING)) {
2595         a1 = string_to_r_strict(a1, raise);
2596         if (!raise && NIL_P(a1)) return Qnil;
2597     }
2598 
2599     if (RB_FLOAT_TYPE_P(a2)) {
2600         a2 = float_to_r(a2);
2601     }
2602     else if (RB_TYPE_P(a2, T_STRING)) {
2603         a2 = string_to_r_strict(a2, raise);
2604         if (!raise && NIL_P(a2)) return Qnil;
2605     }
2606 
2607     if (RB_TYPE_P(a1, T_RATIONAL)) {
2608         if (a2 == Qundef || (k_exact_one_p(a2)))
2609             return a1;
2610     }
2611 
2612     if (a2 == Qundef) {
2613         if (!k_integer_p(a1)) {
2614             if (!raise) {
2615                 VALUE result = rb_protect(to_rational, a1, NULL);
2616                 rb_set_errinfo(Qnil);
2617                 return result;
2618             }
2619             return to_rational(a1);
2620         }
2621     }
2622     else {
2623         if (!k_numeric_p(a1)) {
2624             if (!raise) {
2625                 a1 = rb_protect(to_rational, a1, &state);
2626                 if (state) {
2627                     rb_set_errinfo(Qnil);
2628                     return Qnil;
2629                 }
2630             }
2631             else {
2632                 a1 = rb_check_convert_type_with_id(a1, T_RATIONAL, "Rational", idTo_r);
2633             }
2634         }
2635         if (!k_numeric_p(a2)) {
2636             if (!raise) {
2637                 a2 = rb_protect(to_rational, a2, &state);
2638                 if (state) {
2639                     rb_set_errinfo(Qnil);
2640                     return Qnil;
2641                 }
2642             }
2643             else {
2644                 a2 = rb_check_convert_type_with_id(a2, T_RATIONAL, "Rational", idTo_r);
2645             }
2646         }
2647         if ((k_numeric_p(a1) && k_numeric_p(a2)) &&
2648                 (!f_integer_p(a1) || !f_integer_p(a2)))
2649             return f_div(a1, a2);
2650     }
2651 
2652     {
2653         int argc;
2654         VALUE argv2[2];
2655         argv2[0] = a1;
2656         if (a2 == Qundef) {
2657             argv2[1] = Qnil;
2658             argc = 1;
2659         }
2660         else {
2661             if (!k_integer_p(a2) && !raise) return Qnil;
2662             argv2[1] = a2;
2663             argc = 2;
2664         }
2665         return nurat_s_new(argc, argv2, klass);
2666     }
2667 }
2668 
2669 static VALUE
nurat_s_convert(int argc,VALUE * argv,VALUE klass)2670 nurat_s_convert(int argc, VALUE *argv, VALUE klass)
2671 {
2672     VALUE a1, a2;
2673 
2674     if (rb_scan_args(argc, argv, "11", &a1, &a2) == 1) {
2675         a2 = Qundef;
2676     }
2677 
2678     return nurat_convert(klass, a1, a2, TRUE);
2679 }
2680 
2681 /*
2682  * A rational number can be represented as a pair of integer numbers:
2683  * a/b (b>0), where a is the numerator and b is the denominator.
2684  * Integer a equals rational a/1 mathematically.
2685  *
2686  * In Ruby, you can create rational objects with the Kernel#Rational,
2687  * to_r, or rationalize methods or by suffixing +r+ to a literal.
2688  * The return values will be irreducible fractions.
2689  *
2690  *    Rational(1)      #=> (1/1)
2691  *    Rational(2, 3)   #=> (2/3)
2692  *    Rational(4, -6)  #=> (-2/3)
2693  *    3.to_r           #=> (3/1)
2694  *    2/3r             #=> (2/3)
2695  *
2696  * You can also create rational objects from floating-point numbers or
2697  * strings.
2698  *
2699  *    Rational(0.3)    #=> (5404319552844595/18014398509481984)
2700  *    Rational('0.3')  #=> (3/10)
2701  *    Rational('2/3')  #=> (2/3)
2702  *
2703  *    0.3.to_r         #=> (5404319552844595/18014398509481984)
2704  *    '0.3'.to_r       #=> (3/10)
2705  *    '2/3'.to_r       #=> (2/3)
2706  *    0.3.rationalize  #=> (3/10)
2707  *
2708  * A rational object is an exact number, which helps you to write
2709  * programs without any rounding errors.
2710  *
2711  *    10.times.inject(0) {|t| t + 0.1 }              #=> 0.9999999999999999
2712  *    10.times.inject(0) {|t| t + Rational('0.1') }  #=> (1/1)
2713  *
2714  * However, when an expression includes an inexact component (numerical value
2715  * or operation), it will produce an inexact result.
2716  *
2717  *    Rational(10) / 3   #=> (10/3)
2718  *    Rational(10) / 3.0 #=> 3.3333333333333335
2719  *
2720  *    Rational(-8) ** Rational(1, 3)
2721  *                       #=> (1.0000000000000002+1.7320508075688772i)
2722  */
2723 void
Init_Rational(void)2724 Init_Rational(void)
2725 {
2726     VALUE compat;
2727 #undef rb_intern
2728 #define rb_intern(str) rb_intern_const(str)
2729 
2730     id_abs = rb_intern("abs");
2731     id_idiv = rb_intern("div");
2732     id_integer_p = rb_intern("integer?");
2733     id_i_num = rb_intern("@numerator");
2734     id_i_den = rb_intern("@denominator");
2735 
2736     rb_cRational = rb_define_class("Rational", rb_cNumeric);
2737 
2738     rb_define_alloc_func(rb_cRational, nurat_s_alloc);
2739     rb_undef_method(CLASS_OF(rb_cRational), "allocate");
2740 
2741     rb_undef_method(CLASS_OF(rb_cRational), "new");
2742 
2743     rb_define_global_function("Rational", nurat_f_rational, -1);
2744 
2745     rb_define_method(rb_cRational, "numerator", nurat_numerator, 0);
2746     rb_define_method(rb_cRational, "denominator", nurat_denominator, 0);
2747 
2748     rb_define_method(rb_cRational, "-@", rb_rational_uminus, 0);
2749     rb_define_method(rb_cRational, "+", rb_rational_plus, 1);
2750     rb_define_method(rb_cRational, "-", rb_rational_minus, 1);
2751     rb_define_method(rb_cRational, "*", rb_rational_mul, 1);
2752     rb_define_method(rb_cRational, "/", rb_rational_div, 1);
2753     rb_define_method(rb_cRational, "quo", rb_rational_div, 1);
2754     rb_define_method(rb_cRational, "fdiv", nurat_fdiv, 1);
2755     rb_define_method(rb_cRational, "**", nurat_expt, 1);
2756 
2757     rb_define_method(rb_cRational, "<=>", rb_rational_cmp, 1);
2758     rb_define_method(rb_cRational, "==", nurat_eqeq_p, 1);
2759     rb_define_method(rb_cRational, "coerce", nurat_coerce, 1);
2760 
2761     rb_define_method(rb_cRational, "positive?", nurat_positive_p, 0);
2762     rb_define_method(rb_cRational, "negative?", nurat_negative_p, 0);
2763     rb_define_method(rb_cRational, "abs", rb_rational_abs, 0);
2764     rb_define_method(rb_cRational, "magnitude", rb_rational_abs, 0);
2765 
2766     rb_define_method(rb_cRational, "floor", nurat_floor_n, -1);
2767     rb_define_method(rb_cRational, "ceil", nurat_ceil_n, -1);
2768     rb_define_method(rb_cRational, "truncate", nurat_truncate_n, -1);
2769     rb_define_method(rb_cRational, "round", nurat_round_n, -1);
2770 
2771     rb_define_method(rb_cRational, "to_i", nurat_truncate, 0);
2772     rb_define_method(rb_cRational, "to_f", nurat_to_f, 0);
2773     rb_define_method(rb_cRational, "to_r", nurat_to_r, 0);
2774     rb_define_method(rb_cRational, "rationalize", nurat_rationalize, -1);
2775 
2776     rb_define_method(rb_cRational, "hash", nurat_hash, 0);
2777 
2778     rb_define_method(rb_cRational, "to_s", nurat_to_s, 0);
2779     rb_define_method(rb_cRational, "inspect", nurat_inspect, 0);
2780 
2781     rb_define_private_method(rb_cRational, "marshal_dump", nurat_marshal_dump, 0);
2782     /* :nodoc: */
2783     compat = rb_define_class_under(rb_cRational, "compatible", rb_cObject);
2784     rb_define_private_method(compat, "marshal_load", nurat_marshal_load, 1);
2785     rb_marshal_define_compat(rb_cRational, compat, nurat_dumper, nurat_loader);
2786 
2787     /* --- */
2788 
2789     rb_define_method(rb_cInteger, "gcd", rb_gcd, 1);
2790     rb_define_method(rb_cInteger, "lcm", rb_lcm, 1);
2791     rb_define_method(rb_cInteger, "gcdlcm", rb_gcdlcm, 1);
2792 
2793     rb_define_method(rb_cNumeric, "numerator", numeric_numerator, 0);
2794     rb_define_method(rb_cNumeric, "denominator", numeric_denominator, 0);
2795     rb_define_method(rb_cNumeric, "quo", rb_numeric_quo, 1);
2796 
2797     rb_define_method(rb_cInteger, "numerator", integer_numerator, 0);
2798     rb_define_method(rb_cInteger, "denominator", integer_denominator, 0);
2799 
2800     rb_define_method(rb_cFloat, "numerator", float_numerator, 0);
2801     rb_define_method(rb_cFloat, "denominator", float_denominator, 0);
2802 
2803     rb_define_method(rb_cNilClass, "to_r", nilclass_to_r, 0);
2804     rb_define_method(rb_cNilClass, "rationalize", nilclass_rationalize, -1);
2805     rb_define_method(rb_cInteger, "to_r", integer_to_r, 0);
2806     rb_define_method(rb_cInteger, "rationalize", integer_rationalize, -1);
2807     rb_define_method(rb_cFloat, "to_r", float_to_r, 0);
2808     rb_define_method(rb_cFloat, "rationalize", float_rationalize, -1);
2809 
2810     rb_define_method(rb_cString, "to_r", string_to_r, 0);
2811 
2812     rb_define_private_method(CLASS_OF(rb_cRational), "convert", nurat_s_convert, -1);
2813 
2814     rb_provide("rational.so");	/* for backward compatibility */
2815 }
2816 
2817 /*
2818 Local variables:
2819 c-file-style: "ruby"
2820 End:
2821 */
2822