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