Ruby  2.1.4p265(2014-10-27revision48166)
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  *
588  * Syntax of string form:
589  *
590  * string form = extra spaces , rational , extra spaces ;
591  * rational = [ sign ] , unsigned rational ;
592  * unsigned rational = numerator | numerator , "/" , denominator ;
593  * numerator = integer part | fractional part | integer part , fractional part ;
594  * denominator = digits ;
595  * integer part = digits ;
596  * fractional part = "." , digits , [ ( "e" | "E" ) , [ sign ] , digits ] ;
597  * sign = "-" | "+" ;
598  * digits = digit , { digit | "_" , digit } ;
599  * digit = "0" | "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9" ;
600  * extra spaces = ? \s* ? ;
601  *
602  * See String#to_r.
603  */
604 static VALUE
606 {
607  return rb_funcall2(rb_cRational, id_convert, argc, argv);
608 }
609 
610 /*
611  * call-seq:
612  * rat.numerator -> integer
613  *
614  * Returns the numerator.
615  *
616  * Rational(7).numerator #=> 7
617  * Rational(7, 1).numerator #=> 7
618  * Rational(9, -4).numerator #=> -9
619  * Rational(-2, -10).numerator #=> 1
620  */
621 static VALUE
623 {
624  get_dat1(self);
625  return dat->num;
626 }
627 
628 /*
629  * call-seq:
630  * rat.denominator -> integer
631  *
632  * Returns the denominator (always positive).
633  *
634  * Rational(7).denominator #=> 1
635  * Rational(7, 1).denominator #=> 1
636  * Rational(9, -4).denominator #=> 4
637  * Rational(-2, -10).denominator #=> 5
638  * rat.numerator.gcd(rat.denominator) #=> 1
639  */
640 static VALUE
642 {
643  get_dat1(self);
644  return dat->den;
645 }
646 
647 #ifndef NDEBUG
648 #define f_imul f_imul_orig
649 #endif
650 
651 inline static VALUE
652 f_imul(long a, long b)
653 {
654  VALUE r;
655 
656  if (a == 0 || b == 0)
657  return ZERO;
658  else if (a == 1)
659  return LONG2NUM(b);
660  else if (b == 1)
661  return LONG2NUM(a);
662 
663  if (MUL_OVERFLOW_LONG_P(a, b))
664  r = rb_big_mul(rb_int2big(a), rb_int2big(b));
665  else
666  r = LONG2NUM(a * b);
667  return r;
668 }
669 
670 #ifndef NDEBUG
671 #undef f_imul
672 
673 inline static VALUE
674 f_imul(long x, long y)
675 {
676  VALUE r = f_imul_orig(x, y);
677  assert(f_eqeq_p(r, f_mul(LONG2NUM(x), LONG2NUM(y))));
678  return r;
679 }
680 #endif
681 
682 inline static VALUE
683 f_addsub(VALUE self, VALUE anum, VALUE aden, VALUE bnum, VALUE bden, int k)
684 {
685  VALUE num, den;
686 
687  if (FIXNUM_P(anum) && FIXNUM_P(aden) &&
688  FIXNUM_P(bnum) && FIXNUM_P(bden)) {
689  long an = FIX2LONG(anum);
690  long ad = FIX2LONG(aden);
691  long bn = FIX2LONG(bnum);
692  long bd = FIX2LONG(bden);
693  long ig = i_gcd(ad, bd);
694 
695  VALUE g = LONG2NUM(ig);
696  VALUE a = f_imul(an, bd / ig);
697  VALUE b = f_imul(bn, ad / ig);
698  VALUE c;
699 
700  if (k == '+')
701  c = f_add(a, b);
702  else
703  c = f_sub(a, b);
704 
705  b = f_idiv(aden, g);
706  g = f_gcd(c, g);
707  num = f_idiv(c, g);
708  a = f_idiv(bden, g);
709  den = f_mul(a, b);
710  }
711  else {
712  VALUE g = f_gcd(aden, bden);
713  VALUE a = f_mul(anum, f_idiv(bden, g));
714  VALUE b = f_mul(bnum, f_idiv(aden, g));
715  VALUE c;
716 
717  if (k == '+')
718  c = f_add(a, b);
719  else
720  c = f_sub(a, b);
721 
722  b = f_idiv(aden, g);
723  g = f_gcd(c, g);
724  num = f_idiv(c, g);
725  a = f_idiv(bden, g);
726  den = f_mul(a, b);
727  }
728  return f_rational_new_no_reduce2(CLASS_OF(self), num, den);
729 }
730 
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) #=> (900/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 static VALUE
744 nurat_add(VALUE self, VALUE other)
745 {
746  if (RB_TYPE_P(other, T_FIXNUM) || RB_TYPE_P(other, T_BIGNUM)) {
747  {
748  get_dat1(self);
749 
750  return f_addsub(self,
751  dat->num, dat->den,
752  other, ONE, '+');
753  }
754  }
755  else if (RB_TYPE_P(other, T_FLOAT)) {
756  return f_add(f_to_f(self), 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 static VALUE
785 nurat_sub(VALUE self, VALUE other)
786 {
787  if (RB_TYPE_P(other, T_FIXNUM) || RB_TYPE_P(other, T_BIGNUM)) {
788  {
789  get_dat1(self);
790 
791  return f_addsub(self,
792  dat->num, dat->den,
793  other, ONE, '-');
794  }
795  }
796  else if (RB_TYPE_P(other, T_FLOAT)) {
797  return f_sub(f_to_f(self), 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
814 f_muldiv(VALUE self, VALUE anum, VALUE aden, VALUE bnum, VALUE bden, int k)
815 {
816  VALUE num, den;
817 
818  if (k == '/') {
819  VALUE t;
820 
821  if (f_negative_p(bnum)) {
822  anum = f_negate(anum);
823  bnum = f_negate(bnum);
824  }
825  t = bnum;
826  bnum = bden;
827  bden = t;
828  }
829 
830  if (FIXNUM_P(anum) && FIXNUM_P(aden) &&
831  FIXNUM_P(bnum) && FIXNUM_P(bden)) {
832  long an = FIX2LONG(anum);
833  long ad = FIX2LONG(aden);
834  long bn = FIX2LONG(bnum);
835  long bd = FIX2LONG(bden);
836  long g1 = i_gcd(an, bd);
837  long g2 = i_gcd(ad, bn);
838 
839  num = f_imul(an / g1, bn / g2);
840  den = f_imul(ad / g2, bd / g1);
841  }
842  else {
843  VALUE g1 = f_gcd(anum, bden);
844  VALUE g2 = f_gcd(aden, bnum);
845 
846  num = f_mul(f_idiv(anum, g1), f_idiv(bnum, g2));
847  den = f_mul(f_idiv(aden, g2), f_idiv(bden, g1));
848  }
849  return f_rational_new_no_reduce2(CLASS_OF(self), num, den);
850 }
851 
852 /*
853  * call-seq:
854  * rat * numeric -> numeric
855  *
856  * Performs multiplication.
857  *
858  * Rational(2, 3) * Rational(2, 3) #=> (4/9)
859  * Rational(900) * Rational(1) #=> (900/1)
860  * Rational(-2, 9) * Rational(-9, 2) #=> (1/1)
861  * Rational(9, 8) * 4 #=> (9/2)
862  * Rational(20, 9) * 9.8 #=> 21.77777777777778
863  */
864 static VALUE
865 nurat_mul(VALUE self, VALUE other)
866 {
867  if (RB_TYPE_P(other, T_FIXNUM) || RB_TYPE_P(other, T_BIGNUM)) {
868  {
869  get_dat1(self);
870 
871  return f_muldiv(self,
872  dat->num, dat->den,
873  other, ONE, '*');
874  }
875  }
876  else if (RB_TYPE_P(other, T_FLOAT)) {
877  return f_mul(f_to_f(self), other);
878  }
879  else if (RB_TYPE_P(other, T_RATIONAL)) {
880  {
881  get_dat2(self, other);
882 
883  return f_muldiv(self,
884  adat->num, adat->den,
885  bdat->num, bdat->den, '*');
886  }
887  }
888  else {
889  return rb_num_coerce_bin(self, other, '*');
890  }
891 }
892 
893 /*
894  * call-seq:
895  * rat / numeric -> numeric
896  * rat.quo(numeric) -> numeric
897  *
898  * Performs division.
899  *
900  * Rational(2, 3) / Rational(2, 3) #=> (1/1)
901  * Rational(900) / Rational(1) #=> (900/1)
902  * Rational(-2, 9) / Rational(-9, 2) #=> (4/81)
903  * Rational(9, 8) / 4 #=> (9/32)
904  * Rational(20, 9) / 9.8 #=> 0.22675736961451246
905  */
906 static VALUE
907 nurat_div(VALUE self, VALUE other)
908 {
909  if (RB_TYPE_P(other, T_FIXNUM) || RB_TYPE_P(other, T_BIGNUM)) {
910  if (f_zero_p(other))
912  {
913  get_dat1(self);
914 
915  return f_muldiv(self,
916  dat->num, dat->den,
917  other, ONE, '/');
918  }
919  }
920  else if (RB_TYPE_P(other, T_FLOAT))
921  return rb_funcall(f_to_f(self), '/', 1, other);
922  else if (RB_TYPE_P(other, T_RATIONAL)) {
923  if (f_zero_p(other))
925  {
926  get_dat2(self, other);
927 
928  if (f_one_p(self))
929  return f_rational_new_no_reduce2(CLASS_OF(self),
930  bdat->den, bdat->num);
931 
932  return f_muldiv(self,
933  adat->num, adat->den,
934  bdat->num, bdat->den, '/');
935  }
936  }
937  else {
938  return rb_num_coerce_bin(self, other, '/');
939  }
940 }
941 
942 /*
943  * call-seq:
944  * rat.fdiv(numeric) -> float
945  *
946  * Performs division and returns the value as a float.
947  *
948  * Rational(2, 3).fdiv(1) #=> 0.6666666666666666
949  * Rational(2, 3).fdiv(0.5) #=> 1.3333333333333333
950  * Rational(2).fdiv(3) #=> 0.6666666666666666
951  */
952 static VALUE
953 nurat_fdiv(VALUE self, VALUE other)
954 {
955  if (f_zero_p(other))
956  return f_div(self, f_to_f(other));
957  return f_to_f(f_div(self, other));
958 }
959 
960 inline static VALUE
961 f_odd_p(VALUE integer)
962 {
963  if (rb_funcall(integer, '%', 1, INT2FIX(2)) != INT2FIX(0)) {
964  return Qtrue;
965  }
966  return Qfalse;
967 }
968 
969 /*
970  * call-seq:
971  * rat ** numeric -> numeric
972  *
973  * Performs exponentiation.
974  *
975  * Rational(2) ** Rational(3) #=> (8/1)
976  * Rational(10) ** -2 #=> (1/100)
977  * Rational(10) ** -2.0 #=> 0.01
978  * Rational(-4) ** Rational(1,2) #=> (1.2246063538223773e-16+2.0i)
979  * Rational(1, 2) ** 0 #=> (1/1)
980  * Rational(1, 2) ** 0.0 #=> 1.0
981  */
982 static VALUE
983 nurat_expt(VALUE self, VALUE other)
984 {
985  if (k_numeric_p(other) && k_exact_zero_p(other))
986  return f_rational_new_bang1(CLASS_OF(self), ONE);
987 
988  if (k_rational_p(other)) {
989  get_dat1(other);
990 
991  if (f_one_p(dat->den))
992  other = dat->num; /* c14n */
993  }
994 
995  /* Deal with special cases of 0**n and 1**n */
996  if (k_numeric_p(other) && k_exact_p(other)) {
997  get_dat1(self);
998  if (f_one_p(dat->den)) {
999  if (f_one_p(dat->num)) {
1000  return f_rational_new_bang1(CLASS_OF(self), ONE);
1001  }
1002  else if (f_minus_one_p(dat->num) && k_integer_p(other)) {
1003  return f_rational_new_bang1(CLASS_OF(self), INT2FIX(f_odd_p(other) ? -1 : 1));
1004  }
1005  else if (f_zero_p(dat->num)) {
1006  if (FIX2INT(f_cmp(other, ZERO)) == -1) {
1007  rb_raise_zerodiv();
1008  }
1009  else {
1010  return f_rational_new_bang1(CLASS_OF(self), ZERO);
1011  }
1012  }
1013  }
1014  }
1015 
1016  /* General case */
1017  if (RB_TYPE_P(other, T_FIXNUM)) {
1018  {
1019  VALUE num, den;
1020 
1021  get_dat1(self);
1022 
1023  switch (FIX2INT(f_cmp(other, ZERO))) {
1024  case 1:
1025  num = f_expt(dat->num, other);
1026  den = f_expt(dat->den, other);
1027  break;
1028  case -1:
1029  num = f_expt(dat->den, f_negate(other));
1030  den = f_expt(dat->num, f_negate(other));
1031  break;
1032  default:
1033  num = ONE;
1034  den = ONE;
1035  break;
1036  }
1037  return f_rational_new2(CLASS_OF(self), num, den);
1038  }
1039  }
1040  else if (RB_TYPE_P(other, T_BIGNUM)) {
1041  rb_warn("in a**b, b may be too big");
1042  return f_expt(f_to_f(self), other);
1043  }
1044  else if (RB_TYPE_P(other, T_FLOAT) || RB_TYPE_P(other, T_RATIONAL)) {
1045  return f_expt(f_to_f(self), other);
1046  }
1047  else {
1048  return rb_num_coerce_bin(self, other, id_expt);
1049  }
1050 }
1051 
1052 /*
1053  * call-seq:
1054  * rational <=> numeric -> -1, 0, +1 or nil
1055  *
1056  * Performs comparison and returns -1, 0, or +1.
1057  *
1058  * +nil+ is returned if the two values are incomparable.
1059  *
1060  * Rational(2, 3) <=> Rational(2, 3) #=> 0
1061  * Rational(5) <=> 5 #=> 0
1062  * Rational(2,3) <=> Rational(1,3) #=> 1
1063  * Rational(1,3) <=> 1 #=> -1
1064  * Rational(1,3) <=> 0.3 #=> 1
1065  */
1066 static VALUE
1067 nurat_cmp(VALUE self, VALUE other)
1068 {
1069  if (RB_TYPE_P(other, T_FIXNUM) || RB_TYPE_P(other, T_BIGNUM)) {
1070  {
1071  get_dat1(self);
1072 
1073  if (FIXNUM_P(dat->den) && FIX2LONG(dat->den) == 1)
1074  return f_cmp(dat->num, other); /* c14n */
1075  return f_cmp(self, f_rational_new_bang1(CLASS_OF(self), other));
1076  }
1077  }
1078  else if (RB_TYPE_P(other, T_FLOAT)) {
1079  return f_cmp(f_to_f(self), other);
1080  }
1081  else if (RB_TYPE_P(other, T_RATIONAL)) {
1082  {
1083  VALUE num1, num2;
1084 
1085  get_dat2(self, other);
1086 
1087  if (FIXNUM_P(adat->num) && FIXNUM_P(adat->den) &&
1088  FIXNUM_P(bdat->num) && FIXNUM_P(bdat->den)) {
1089  num1 = f_imul(FIX2LONG(adat->num), FIX2LONG(bdat->den));
1090  num2 = f_imul(FIX2LONG(bdat->num), FIX2LONG(adat->den));
1091  }
1092  else {
1093  num1 = f_mul(adat->num, bdat->den);
1094  num2 = f_mul(bdat->num, adat->den);
1095  }
1096  return f_cmp(f_sub(num1, num2), ZERO);
1097  }
1098  }
1099  else {
1100  return rb_num_coerce_cmp(self, other, id_cmp);
1101  }
1102 }
1103 
1104 /*
1105  * call-seq:
1106  * rat == object -> true or false
1107  *
1108  * Returns true if rat equals object numerically.
1109  *
1110  * Rational(2, 3) == Rational(2, 3) #=> true
1111  * Rational(5) == 5 #=> true
1112  * Rational(0) == 0.0 #=> true
1113  * Rational('1/3') == 0.33 #=> false
1114  * Rational('1/2') == '1/2' #=> false
1115  */
1116 static VALUE
1118 {
1119  if (RB_TYPE_P(other, T_FIXNUM) || RB_TYPE_P(other, T_BIGNUM)) {
1120  {
1121  get_dat1(self);
1122 
1123  if (f_zero_p(dat->num) && f_zero_p(other))
1124  return Qtrue;
1125 
1126  if (!FIXNUM_P(dat->den))
1127  return Qfalse;
1128  if (FIX2LONG(dat->den) != 1)
1129  return Qfalse;
1130  if (f_eqeq_p(dat->num, other))
1131  return Qtrue;
1132  return Qfalse;
1133  }
1134  }
1135  else if (RB_TYPE_P(other, T_FLOAT)) {
1136  return f_eqeq_p(f_to_f(self), other);
1137  }
1138  else if (RB_TYPE_P(other, T_RATIONAL)) {
1139  {
1140  get_dat2(self, other);
1141 
1142  if (f_zero_p(adat->num) && f_zero_p(bdat->num))
1143  return Qtrue;
1144 
1145  return f_boolcast(f_eqeq_p(adat->num, bdat->num) &&
1146  f_eqeq_p(adat->den, bdat->den));
1147  }
1148  }
1149  else {
1150  return f_eqeq_p(other, self);
1151  }
1152 }
1153 
1154 /* :nodoc: */
1155 static VALUE
1157 {
1158  if (RB_TYPE_P(other, T_FIXNUM) || RB_TYPE_P(other, T_BIGNUM)) {
1159  return rb_assoc_new(f_rational_new_bang1(CLASS_OF(self), other), self);
1160  }
1161  else if (RB_TYPE_P(other, T_FLOAT)) {
1162  return rb_assoc_new(other, f_to_f(self));
1163  }
1164  else if (RB_TYPE_P(other, T_RATIONAL)) {
1165  return rb_assoc_new(other, self);
1166  }
1167  else if (RB_TYPE_P(other, T_COMPLEX)) {
1168  if (k_exact_zero_p(RCOMPLEX(other)->imag))
1170  (CLASS_OF(self), RCOMPLEX(other)->real), self);
1171  else
1172  return rb_assoc_new(other, rb_Complex(self, INT2FIX(0)));
1173  }
1174 
1175  rb_raise(rb_eTypeError, "%s can't be coerced into %s",
1176  rb_obj_classname(other), rb_obj_classname(self));
1177  return Qnil;
1178 }
1179 
1180 #if 0
1181 /* :nodoc: */
1182 static VALUE
1183 nurat_idiv(VALUE self, VALUE other)
1184 {
1185  return f_idiv(self, other);
1186 }
1187 
1188 /* :nodoc: */
1189 static VALUE
1190 nurat_quot(VALUE self, VALUE other)
1191 {
1192  return f_truncate(f_div(self, other));
1193 }
1194 
1195 /* :nodoc: */
1196 static VALUE
1197 nurat_quotrem(VALUE self, VALUE other)
1198 {
1199  VALUE val = f_truncate(f_div(self, other));
1200  return rb_assoc_new(val, f_sub(self, f_mul(other, val)));
1201 }
1202 #endif
1203 
1204 #if 0
1205 /* :nodoc: */
1206 static VALUE
1207 nurat_true(VALUE self)
1208 {
1209  return Qtrue;
1210 }
1211 #endif
1212 
1213 static VALUE
1215 {
1216  get_dat1(self);
1217  return f_idiv(dat->num, dat->den);
1218 }
1219 
1220 static VALUE
1222 {
1223  get_dat1(self);
1224  return f_negate(f_idiv(f_negate(dat->num), dat->den));
1225 }
1226 
1227 /*
1228  * call-seq:
1229  * rat.to_i -> integer
1230  *
1231  * Returns the truncated value as an integer.
1232  *
1233  * Equivalent to
1234  * rat.truncate.
1235  *
1236  * Rational(2, 3).to_i #=> 0
1237  * Rational(3).to_i #=> 3
1238  * Rational(300.6).to_i #=> 300
1239  * Rational(98,71).to_i #=> 1
1240  * Rational(-30,2).to_i #=> -15
1241  */
1242 static VALUE
1244 {
1245  get_dat1(self);
1246  if (f_negative_p(dat->num))
1247  return f_negate(f_idiv(f_negate(dat->num), dat->den));
1248  return f_idiv(dat->num, dat->den);
1249 }
1250 
1251 static VALUE
1253 {
1254  VALUE num, den, neg;
1255 
1256  get_dat1(self);
1257 
1258  num = dat->num;
1259  den = dat->den;
1260  neg = f_negative_p(num);
1261 
1262  if (neg)
1263  num = f_negate(num);
1264 
1265  num = f_add(f_mul(num, TWO), den);
1266  den = f_mul(den, TWO);
1267  num = f_idiv(num, den);
1268 
1269  if (neg)
1270  num = f_negate(num);
1271 
1272  return num;
1273 }
1274 
1275 static VALUE
1277 {
1278  VALUE n, b, s;
1279 
1280  if (argc == 0)
1281  return (*func)(self);
1282 
1283  rb_scan_args(argc, argv, "01", &n);
1284 
1285  if (!k_integer_p(n))
1286  rb_raise(rb_eTypeError, "not an integer");
1287 
1288  b = f_expt10(n);
1289  s = f_mul(self, b);
1290 
1291  if (k_float_p(s)) {
1292  if (f_lt_p(n, ZERO))
1293  return ZERO;
1294  return self;
1295  }
1296 
1297  if (!k_rational_p(s)) {
1298  s = f_rational_new_bang1(CLASS_OF(self), s);
1299  }
1300 
1301  s = (*func)(s);
1302 
1303  s = f_div(f_rational_new_bang1(CLASS_OF(self), s), b);
1304 
1305  if (f_lt_p(n, ONE))
1306  s = f_to_i(s);
1307 
1308  return s;
1309 }
1310 
1311 /*
1312  * call-seq:
1313  * rat.floor -> integer
1314  * rat.floor(precision=0) -> rational
1315  *
1316  * Returns the truncated value (toward negative infinity).
1317  *
1318  * Rational(3).floor #=> 3
1319  * Rational(2, 3).floor #=> 0
1320  * Rational(-3, 2).floor #=> -1
1321  *
1322  * decimal - 1 2 3 . 4 5 6
1323  * ^ ^ ^ ^ ^ ^
1324  * precision -3 -2 -1 0 +1 +2
1325  *
1326  * '%f' % Rational('-123.456').floor(+1) #=> "-123.500000"
1327  * '%f' % Rational('-123.456').floor(-1) #=> "-130.000000"
1328  */
1329 static VALUE
1330 nurat_floor_n(int argc, VALUE *argv, VALUE self)
1331 {
1332  return f_round_common(argc, argv, self, nurat_floor);
1333 }
1334 
1335 /*
1336  * call-seq:
1337  * rat.ceil -> integer
1338  * rat.ceil(precision=0) -> rational
1339  *
1340  * Returns the truncated value (toward positive infinity).
1341  *
1342  * Rational(3).ceil #=> 3
1343  * Rational(2, 3).ceil #=> 1
1344  * Rational(-3, 2).ceil #=> -1
1345  *
1346  * decimal - 1 2 3 . 4 5 6
1347  * ^ ^ ^ ^ ^ ^
1348  * precision -3 -2 -1 0 +1 +2
1349  *
1350  * '%f' % Rational('-123.456').ceil(+1) #=> "-123.400000"
1351  * '%f' % Rational('-123.456').ceil(-1) #=> "-120.000000"
1352  */
1353 static VALUE
1354 nurat_ceil_n(int argc, VALUE *argv, VALUE self)
1355 {
1356  return f_round_common(argc, argv, self, nurat_ceil);
1357 }
1358 
1359 /*
1360  * call-seq:
1361  * rat.truncate -> integer
1362  * rat.truncate(precision=0) -> rational
1363  *
1364  * Returns the truncated value (toward zero).
1365  *
1366  * Rational(3).truncate #=> 3
1367  * Rational(2, 3).truncate #=> 0
1368  * Rational(-3, 2).truncate #=> -1
1369  *
1370  * decimal - 1 2 3 . 4 5 6
1371  * ^ ^ ^ ^ ^ ^
1372  * precision -3 -2 -1 0 +1 +2
1373  *
1374  * '%f' % Rational('-123.456').truncate(+1) #=> "-123.400000"
1375  * '%f' % Rational('-123.456').truncate(-1) #=> "-120.000000"
1376  */
1377 static VALUE
1378 nurat_truncate_n(int argc, VALUE *argv, VALUE self)
1379 {
1380  return f_round_common(argc, argv, self, nurat_truncate);
1381 }
1382 
1383 /*
1384  * call-seq:
1385  * rat.round -> integer
1386  * rat.round(precision=0) -> rational
1387  *
1388  * Returns the truncated value (toward the nearest integer;
1389  * 0.5 => 1; -0.5 => -1).
1390  *
1391  * Rational(3).round #=> 3
1392  * Rational(2, 3).round #=> 1
1393  * Rational(-3, 2).round #=> -2
1394  *
1395  * decimal - 1 2 3 . 4 5 6
1396  * ^ ^ ^ ^ ^ ^
1397  * precision -3 -2 -1 0 +1 +2
1398  *
1399  * '%f' % Rational('-123.456').round(+1) #=> "-123.500000"
1400  * '%f' % Rational('-123.456').round(-1) #=> "-120.000000"
1401  */
1402 static VALUE
1403 nurat_round_n(int argc, VALUE *argv, VALUE self)
1404 {
1405  return f_round_common(argc, argv, self, nurat_round);
1406 }
1407 
1408 /*
1409  * call-seq:
1410  * rat.to_f -> float
1411  *
1412  * Return the value as a float.
1413  *
1414  * Rational(2).to_f #=> 2.0
1415  * Rational(9, 4).to_f #=> 2.25
1416  * Rational(-3, 4).to_f #=> -0.75
1417  * Rational(20, 3).to_f #=> 6.666666666666667
1418  */
1419 static VALUE
1421 {
1422  get_dat1(self);
1423  return f_fdiv(dat->num, dat->den);
1424 }
1425 
1426 /*
1427  * call-seq:
1428  * rat.to_r -> self
1429  *
1430  * Returns self.
1431  *
1432  * Rational(2).to_r #=> (2/1)
1433  * Rational(-8, 6).to_r #=> (-4/3)
1434  */
1435 static VALUE
1437 {
1438  return self;
1439 }
1440 
1441 #define id_ceil rb_intern("ceil")
1442 #define f_ceil(x) rb_funcall((x), id_ceil, 0)
1443 
1444 #define id_quo rb_intern("quo")
1445 #define f_quo(x,y) rb_funcall((x), id_quo, 1, (y))
1446 
1447 #define f_reciprocal(x) f_quo(ONE, (x))
1448 
1449 /*
1450  The algorithm here is the method described in CLISP. Bruno Haible has
1451  graciously given permission to use this algorithm. He says, "You can use
1452  it, if you present the following explanation of the algorithm."
1453 
1454  Algorithm (recursively presented):
1455  If x is a rational number, return x.
1456  If x = 0.0, return 0.
1457  If x < 0.0, return (- (rationalize (- x))).
1458  If x > 0.0:
1459  Call (integer-decode-float x). It returns a m,e,s=1 (mantissa,
1460  exponent, sign).
1461  If m = 0 or e >= 0: return x = m*2^e.
1462  Search a rational number between a = (m-1/2)*2^e and b = (m+1/2)*2^e
1463  with smallest possible numerator and denominator.
1464  Note 1: If m is a power of 2, we ought to take a = (m-1/4)*2^e.
1465  But in this case the result will be x itself anyway, regardless of
1466  the choice of a. Therefore we can simply ignore this case.
1467  Note 2: At first, we need to consider the closed interval [a,b].
1468  but since a and b have the denominator 2^(|e|+1) whereas x itself
1469  has a denominator <= 2^|e|, we can restrict the search to the open
1470  interval (a,b).
1471  So, for given a and b (0 < a < b) we are searching a rational number
1472  y with a <= y <= b.
1473  Recursive algorithm fraction_between(a,b):
1474  c := (ceiling a)
1475  if c < b
1476  then return c ; because a <= c < b, c integer
1477  else
1478  ; a is not integer (otherwise we would have had c = a < b)
1479  k := c-1 ; k = floor(a), k < a < b <= k+1
1480  return y = k + 1/fraction_between(1/(b-k), 1/(a-k))
1481  ; note 1 <= 1/(b-k) < 1/(a-k)
1482 
1483  You can see that we are actually computing a continued fraction expansion.
1484 
1485  Algorithm (iterative):
1486  If x is rational, return x.
1487  Call (integer-decode-float x). It returns a m,e,s (mantissa,
1488  exponent, sign).
1489  If m = 0 or e >= 0, return m*2^e*s. (This includes the case x = 0.0.)
1490  Create rational numbers a := (2*m-1)*2^(e-1) and b := (2*m+1)*2^(e-1)
1491  (positive and already in lowest terms because the denominator is a
1492  power of two and the numerator is odd).
1493  Start a continued fraction expansion
1494  p[-1] := 0, p[0] := 1, q[-1] := 1, q[0] := 0, i := 0.
1495  Loop
1496  c := (ceiling a)
1497  if c >= b
1498  then k := c-1, partial_quotient(k), (a,b) := (1/(b-k),1/(a-k)),
1499  goto Loop
1500  finally partial_quotient(c).
1501  Here partial_quotient(c) denotes the iteration
1502  i := i+1, p[i] := c*p[i-1]+p[i-2], q[i] := c*q[i-1]+q[i-2].
1503  At the end, return s * (p[i]/q[i]).
1504  This rational number is already in lowest terms because
1505  p[i]*q[i-1]-p[i-1]*q[i] = (-1)^i.
1506 */
1507 
1508 static void
1510 {
1511  VALUE c, k, t, p0, p1, p2, q0, q1, q2;
1512 
1513  p0 = ZERO;
1514  p1 = ONE;
1515  q0 = ONE;
1516  q1 = ZERO;
1517 
1518  while (1) {
1519  c = f_ceil(a);
1520  if (f_lt_p(c, b))
1521  break;
1522  k = f_sub(c, ONE);
1523  p2 = f_add(f_mul(k, p1), p0);
1524  q2 = f_add(f_mul(k, q1), q0);
1525  t = f_reciprocal(f_sub(b, k));
1526  b = f_reciprocal(f_sub(a, k));
1527  a = t;
1528  p0 = p1;
1529  q0 = q1;
1530  p1 = p2;
1531  q1 = q2;
1532  }
1533  *p = f_add(f_mul(c, p1), p0);
1534  *q = f_add(f_mul(c, q1), q0);
1535 }
1536 
1537 /*
1538  * call-seq:
1539  * rat.rationalize -> self
1540  * rat.rationalize(eps) -> rational
1541  *
1542  * Returns a simpler approximation of the value if the optional
1543  * argument eps is given (rat-|eps| <= result <= rat+|eps|), self
1544  * otherwise.
1545  *
1546  * r = Rational(5033165, 16777216)
1547  * r.rationalize #=> (5033165/16777216)
1548  * r.rationalize(Rational('0.01')) #=> (3/10)
1549  * r.rationalize(Rational('0.1')) #=> (1/3)
1550  */
1551 static VALUE
1552 nurat_rationalize(int argc, VALUE *argv, VALUE self)
1553 {
1554  VALUE e, a, b, p, q;
1555 
1556  if (argc == 0)
1557  return self;
1558 
1559  if (f_negative_p(self))
1560  return f_negate(nurat_rationalize(argc, argv, f_abs(self)));
1561 
1562  rb_scan_args(argc, argv, "01", &e);
1563  e = f_abs(e);
1564  a = f_sub(self, e);
1565  b = f_add(self, e);
1566 
1567  if (f_eqeq_p(a, b))
1568  return self;
1569 
1570  nurat_rationalize_internal(a, b, &p, &q);
1571  return f_rational_new2(CLASS_OF(self), p, q);
1572 }
1573 
1574 /* :nodoc: */
1575 static VALUE
1577 {
1578  st_index_t v, h[2];
1579  VALUE n;
1580 
1581  get_dat1(self);
1582  n = rb_hash(dat->num);
1583  h[0] = NUM2LONG(n);
1584  n = rb_hash(dat->den);
1585  h[1] = NUM2LONG(n);
1586  v = rb_memhash(h, sizeof(h));
1587  return LONG2FIX(v);
1588 }
1589 
1590 static VALUE
1592 {
1593  VALUE s;
1594  get_dat1(self);
1595 
1596  s = (*func)(dat->num);
1597  rb_str_cat2(s, "/");
1598  rb_str_concat(s, (*func)(dat->den));
1599 
1600  return s;
1601 }
1602 
1603 /*
1604  * call-seq:
1605  * rat.to_s -> string
1606  *
1607  * Returns the value as a string.
1608  *
1609  * Rational(2).to_s #=> "2/1"
1610  * Rational(-8, 6).to_s #=> "-4/3"
1611  * Rational('1/2').to_s #=> "1/2"
1612  */
1613 static VALUE
1615 {
1616  return f_format(self, f_to_s);
1617 }
1618 
1619 /*
1620  * call-seq:
1621  * rat.inspect -> string
1622  *
1623  * Returns the value as a string for inspection.
1624  *
1625  * Rational(2).inspect #=> "(2/1)"
1626  * Rational(-8, 6).inspect #=> "(-4/3)"
1627  * Rational('1/2').inspect #=> "(1/2)"
1628  */
1629 static VALUE
1631 {
1632  VALUE s;
1633 
1634  s = rb_usascii_str_new2("(");
1635  rb_str_concat(s, f_format(self, f_inspect));
1636  rb_str_cat2(s, ")");
1637 
1638  return s;
1639 }
1640 
1641 /* :nodoc: */
1642 static VALUE
1644 {
1645  return self;
1646 }
1647 
1648 /* :nodoc: */
1649 static VALUE
1651 {
1652  get_dat1(self);
1653 
1656 
1657  return self;
1658 }
1659 
1660 /* :nodoc: */
1661 static VALUE
1663 {
1664  VALUE a;
1665  get_dat1(self);
1666 
1667  a = rb_assoc_new(dat->num, dat->den);
1668  rb_copy_generic_ivar(a, self);
1669  return a;
1670 }
1671 
1672 /* :nodoc: */
1673 static VALUE
1675 {
1676  rb_check_frozen(self);
1677  rb_check_trusted(self);
1678 
1679  Check_Type(a, T_ARRAY);
1680  if (RARRAY_LEN(a) != 2)
1681  rb_raise(rb_eArgError, "marshaled rational must have an array whose length is 2 but %ld", RARRAY_LEN(a));
1682  if (f_zero_p(RARRAY_AREF(a, 1)))
1683  rb_raise_zerodiv();
1684 
1685  rb_ivar_set(self, id_i_num, RARRAY_AREF(a, 0));
1686  rb_ivar_set(self, id_i_den, RARRAY_AREF(a, 1));
1687 
1688  return self;
1689 }
1690 
1691 /* --- */
1692 
1693 VALUE
1695 {
1696  get_dat1(x);
1697  return f_rational_new_no_reduce2(CLASS_OF(x), dat->den, dat->num);
1698 }
1699 
1700 /*
1701  * call-seq:
1702  * int.gcd(int2) -> integer
1703  *
1704  * Returns the greatest common divisor (always positive). 0.gcd(x)
1705  * and x.gcd(0) return abs(x).
1706  *
1707  * 2.gcd(2) #=> 2
1708  * 3.gcd(-7) #=> 1
1709  * ((1<<31)-1).gcd((1<<61)-1) #=> 1
1710  */
1711 VALUE
1712 rb_gcd(VALUE self, VALUE other)
1713 {
1714  other = nurat_int_value(other);
1715  return f_gcd(self, other);
1716 }
1717 
1718 /*
1719  * call-seq:
1720  * int.lcm(int2) -> integer
1721  *
1722  * Returns the least common multiple (always positive). 0.lcm(x) and
1723  * x.lcm(0) return zero.
1724  *
1725  * 2.lcm(2) #=> 2
1726  * 3.lcm(-7) #=> 21
1727  * ((1<<31)-1).lcm((1<<61)-1) #=> 4951760154835678088235319297
1728  */
1729 VALUE
1730 rb_lcm(VALUE self, VALUE other)
1731 {
1732  other = nurat_int_value(other);
1733  return f_lcm(self, other);
1734 }
1735 
1736 /*
1737  * call-seq:
1738  * int.gcdlcm(int2) -> array
1739  *
1740  * Returns an array; [int.gcd(int2), int.lcm(int2)].
1741  *
1742  * 2.gcdlcm(2) #=> [2, 2]
1743  * 3.gcdlcm(-7) #=> [1, 21]
1744  * ((1<<31)-1).gcdlcm((1<<61)-1) #=> [1, 4951760154835678088235319297]
1745  */
1746 VALUE
1747 rb_gcdlcm(VALUE self, VALUE other)
1748 {
1749  other = nurat_int_value(other);
1750  return rb_assoc_new(f_gcd(self, other), f_lcm(self, other));
1751 }
1752 
1753 VALUE
1755 {
1756  return nurat_s_new_internal(rb_cRational, x, y);
1757 }
1758 
1759 VALUE
1761 {
1763 }
1764 
1765 static VALUE nurat_s_convert(int argc, VALUE *argv, VALUE klass);
1766 
1767 VALUE
1769 {
1770  VALUE a[2];
1771  a[0] = x;
1772  a[1] = y;
1773  return nurat_s_convert(2, a, rb_cRational);
1774 }
1775 
1776 #define id_numerator rb_intern("numerator")
1777 #define f_numerator(x) rb_funcall((x), id_numerator, 0)
1778 
1779 #define id_denominator rb_intern("denominator")
1780 #define f_denominator(x) rb_funcall((x), id_denominator, 0)
1781 
1782 #define id_to_r rb_intern("to_r")
1783 #define f_to_r(x) rb_funcall((x), id_to_r, 0)
1784 
1785 /*
1786  * call-seq:
1787  * num.numerator -> integer
1788  *
1789  * Returns the numerator.
1790  */
1791 static VALUE
1793 {
1794  return f_numerator(f_to_r(self));
1795 }
1796 
1797 /*
1798  * call-seq:
1799  * num.denominator -> integer
1800  *
1801  * Returns the denominator (always positive).
1802  */
1803 static VALUE
1805 {
1806  return f_denominator(f_to_r(self));
1807 }
1808 
1809 
1810 /*
1811  * call-seq:
1812  * num.quo(int_or_rat) -> rat
1813  * num.quo(flo) -> flo
1814  *
1815  * Returns most exact division (rational for integers, float for floats).
1816  */
1817 
1818 static VALUE
1820 {
1821  if (RB_TYPE_P(y, T_FLOAT)) {
1822  return f_fdiv(x, y);
1823  }
1824 
1825 #ifdef CANON
1826  if (canonicalization) {
1827  x = rb_rational_raw1(x);
1828  }
1829  else
1830 #endif
1831  {
1832  x = rb_convert_type(x, T_RATIONAL, "Rational", "to_r");
1833  }
1834  return rb_funcall(x, '/', 1, y);
1835 }
1836 
1837 
1838 /*
1839  * call-seq:
1840  * int.numerator -> self
1841  *
1842  * Returns self.
1843  */
1844 static VALUE
1846 {
1847  return self;
1848 }
1849 
1850 /*
1851  * call-seq:
1852  * int.denominator -> 1
1853  *
1854  * Returns 1.
1855  */
1856 static VALUE
1858 {
1859  return INT2FIX(1);
1860 }
1861 
1862 /*
1863  * call-seq:
1864  * flo.numerator -> integer
1865  *
1866  * Returns the numerator. The result is machine dependent.
1867  *
1868  * n = 0.3.numerator #=> 5404319552844595
1869  * d = 0.3.denominator #=> 18014398509481984
1870  * n.fdiv(d) #=> 0.3
1871  */
1872 static VALUE
1874 {
1875  double d = RFLOAT_VALUE(self);
1876  if (isinf(d) || isnan(d))
1877  return self;
1878  return rb_call_super(0, 0);
1879 }
1880 
1881 /*
1882  * call-seq:
1883  * flo.denominator -> integer
1884  *
1885  * Returns the denominator (always positive). The result is machine
1886  * dependent.
1887  *
1888  * See numerator.
1889  */
1890 static VALUE
1892 {
1893  double d = RFLOAT_VALUE(self);
1894  if (isinf(d) || isnan(d))
1895  return INT2FIX(1);
1896  return rb_call_super(0, 0);
1897 }
1898 
1899 /*
1900  * call-seq:
1901  * nil.to_r -> (0/1)
1902  *
1903  * Returns zero as a rational.
1904  */
1905 static VALUE
1907 {
1908  return rb_rational_new1(INT2FIX(0));
1909 }
1910 
1911 /*
1912  * call-seq:
1913  * nil.rationalize([eps]) -> (0/1)
1914  *
1915  * Returns zero as a rational. The optional argument eps is always
1916  * ignored.
1917  */
1918 static VALUE
1919 nilclass_rationalize(int argc, VALUE *argv, VALUE self)
1920 {
1921  rb_scan_args(argc, argv, "01", NULL);
1922  return nilclass_to_r(self);
1923 }
1924 
1925 /*
1926  * call-seq:
1927  * int.to_r -> rational
1928  *
1929  * Returns the value as a rational.
1930  *
1931  * 1.to_r #=> (1/1)
1932  * (1<<64).to_r #=> (18446744073709551616/1)
1933  */
1934 static VALUE
1936 {
1937  return rb_rational_new1(self);
1938 }
1939 
1940 /*
1941  * call-seq:
1942  * int.rationalize([eps]) -> rational
1943  *
1944  * Returns the value as a rational. The optional argument eps is
1945  * always ignored.
1946  */
1947 static VALUE
1948 integer_rationalize(int argc, VALUE *argv, VALUE self)
1949 {
1950  rb_scan_args(argc, argv, "01", NULL);
1951  return integer_to_r(self);
1952 }
1953 
1954 static void
1956 {
1957  double f;
1958  int n;
1959 
1960  f = frexp(RFLOAT_VALUE(self), &n);
1961  f = ldexp(f, DBL_MANT_DIG);
1962  n -= DBL_MANT_DIG;
1963  *rf = rb_dbl2big(f);
1964  *rn = INT2FIX(n);
1965 }
1966 
1967 #if 0
1968 static VALUE
1969 float_decode(VALUE self)
1970 {
1971  VALUE f, n;
1972 
1973  float_decode_internal(self, &f, &n);
1974  return rb_assoc_new(f, n);
1975 }
1976 #endif
1977 
1978 #define id_lshift rb_intern("<<")
1979 #define f_lshift(x,n) rb_funcall((x), id_lshift, 1, (n))
1980 
1981 /*
1982  * call-seq:
1983  * flt.to_r -> rational
1984  *
1985  * Returns the value as a rational.
1986  *
1987  * NOTE: 0.3.to_r isn't the same as '0.3'.to_r. The latter is
1988  * equivalent to '3/10'.to_r, but the former isn't so.
1989  *
1990  * 2.0.to_r #=> (2/1)
1991  * 2.5.to_r #=> (5/2)
1992  * -0.75.to_r #=> (-3/4)
1993  * 0.0.to_r #=> (0/1)
1994  *
1995  * See rationalize.
1996  */
1997 static VALUE
1999 {
2000  VALUE f, n;
2001 
2002  float_decode_internal(self, &f, &n);
2003 #if FLT_RADIX == 2
2004  {
2005  long ln = FIX2LONG(n);
2006 
2007  if (ln == 0)
2008  return f_to_r(f);
2009  if (ln > 0)
2010  return f_to_r(f_lshift(f, n));
2011  ln = -ln;
2012  return rb_rational_new2(f, f_lshift(ONE, INT2FIX(ln)));
2013  }
2014 #else
2015  return f_to_r(f_mul(f, f_expt(INT2FIX(FLT_RADIX), n)));
2016 #endif
2017 }
2018 
2019 VALUE
2021 {
2022  VALUE e, a, b, p, q;
2023 
2024  e = f_abs(prec);
2025  a = f_sub(flt, e);
2026  b = f_add(flt, e);
2027 
2028  if (f_eqeq_p(a, b))
2029  return f_to_r(flt);
2030 
2031  nurat_rationalize_internal(a, b, &p, &q);
2032  return rb_rational_new2(p, q);
2033 }
2034 
2035 VALUE
2037 {
2038  VALUE a, b, f, n, p, q;
2039 
2040  float_decode_internal(flt, &f, &n);
2041  if (f_zero_p(f) || f_positive_p(n))
2042  return rb_rational_new1(f_lshift(f, n));
2043 
2044 #if FLT_RADIX == 2
2045  {
2046  VALUE two_times_f, den;
2047 
2048  two_times_f = f_mul(TWO, f);
2049  den = f_lshift(ONE, f_sub(ONE, n));
2050 
2051  a = rb_rational_new2(f_sub(two_times_f, ONE), den);
2052  b = rb_rational_new2(f_add(two_times_f, ONE), den);
2053  }
2054 #else
2055  {
2056  VALUE radix_times_f, den;
2057 
2058  radix_times_f = f_mul(INT2FIX(FLT_RADIX), f);
2059  den = f_expt(INT2FIX(FLT_RADIX), f_sub(ONE, n));
2060 
2061  a = rb_rational_new2(f_sub(radix_times_f, INT2FIX(FLT_RADIX - 1)), den);
2062  b = rb_rational_new2(f_add(radix_times_f, INT2FIX(FLT_RADIX - 1)), den);
2063  }
2064 #endif
2065 
2066  if (f_eqeq_p(a, b))
2067  return f_to_r(flt);
2068 
2069  nurat_rationalize_internal(a, b, &p, &q);
2070  return rb_rational_new2(p, q);
2071 }
2072 
2073 /*
2074  * call-seq:
2075  * flt.rationalize([eps]) -> rational
2076  *
2077  * Returns a simpler approximation of the value (flt-|eps| <= result
2078  * <= flt+|eps|). if the optional eps is not given, it will be chosen
2079  * automatically.
2080  *
2081  * 0.3.rationalize #=> (3/10)
2082  * 1.333.rationalize #=> (1333/1000)
2083  * 1.333.rationalize(0.01) #=> (4/3)
2084  *
2085  * See to_r.
2086  */
2087 static VALUE
2088 float_rationalize(int argc, VALUE *argv, VALUE self)
2089 {
2090  VALUE e;
2091 
2092  if (f_negative_p(self))
2093  return f_negate(float_rationalize(argc, argv, f_abs(self)));
2094 
2095  rb_scan_args(argc, argv, "01", &e);
2096 
2097  if (argc != 0) {
2098  return rb_flt_rationalize_with_prec(self, e);
2099  }
2100  else {
2101  return rb_flt_rationalize(self);
2102  }
2103 }
2104 
2105 #include <ctype.h>
2106 
2107 inline static int
2108 issign(int c)
2109 {
2110  return (c == '-' || c == '+');
2111 }
2112 
2113 static int
2114 read_sign(const char **s)
2115 {
2116  int sign = '?';
2117 
2118  if (issign(**s)) {
2119  sign = **s;
2120  (*s)++;
2121  }
2122  return sign;
2123 }
2124 
2125 inline static int
2127 {
2128  return isdigit((unsigned char)c);
2129 }
2130 
2131 static int
2132 read_digits(const char **s, int strict,
2133  VALUE *num, int *count)
2134 {
2135  char *b, *bb;
2136  int us = 1, ret = 1;
2137  VALUE tmp;
2138 
2139  if (!isdecimal(**s)) {
2140  *num = ZERO;
2141  return 0;
2142  }
2143 
2144  bb = b = ALLOCV_N(char, tmp, strlen(*s) + 1);
2145 
2146  while (isdecimal(**s) || **s == '_') {
2147  if (**s == '_') {
2148  if (strict) {
2149  if (us) {
2150  ret = 0;
2151  goto conv;
2152  }
2153  }
2154  us = 1;
2155  }
2156  else {
2157  if (count)
2158  (*count)++;
2159  *b++ = **s;
2160  us = 0;
2161  }
2162  (*s)++;
2163  }
2164  if (us)
2165  do {
2166  (*s)--;
2167  } while (**s == '_');
2168  conv:
2169  *b = '\0';
2170  *num = rb_cstr_to_inum(bb, 10, 0);
2171  ALLOCV_END(tmp);
2172  return ret;
2173 }
2174 
2175 inline static int
2177 {
2178  return (c == 'e' || c == 'E');
2179 }
2180 
2181 static int
2182 read_num(const char **s, int numsign, int strict,
2183  VALUE *num)
2184 {
2185  VALUE ip, fp, exp;
2186 
2187  *num = rb_rational_new2(ZERO, ONE);
2188  exp = Qnil;
2189 
2190  if (**s != '.') {
2191  if (!read_digits(s, strict, &ip, NULL))
2192  return 0;
2193  *num = rb_rational_new2(ip, ONE);
2194  }
2195 
2196  if (**s == '.') {
2197  int count = 0;
2198 
2199  (*s)++;
2200  if (!read_digits(s, strict, &fp, &count))
2201  return 0;
2202  {
2203  VALUE l = f_expt10(INT2NUM(count));
2204  *num = f_mul(*num, l);
2205  *num = f_add(*num, fp);
2206  *num = f_div(*num, l);
2207  }
2208  }
2209 
2210  if (islettere(**s)) {
2211  int expsign;
2212 
2213  (*s)++;
2214  expsign = read_sign(s);
2215  if (!read_digits(s, strict, &exp, NULL))
2216  return 0;
2217  if (expsign == '-')
2218  exp = f_negate(exp);
2219  }
2220 
2221  if (numsign == '-')
2222  *num = f_negate(*num);
2223  if (!NIL_P(exp)) {
2224  VALUE l = f_expt10(exp);
2225  *num = f_mul(*num, l);
2226  }
2227  return 1;
2228 }
2229 
2230 inline static int
2231 read_den(const char **s, int strict,
2232  VALUE *num)
2233 {
2234  if (!read_digits(s, strict, num, NULL))
2235  return 0;
2236  return 1;
2237 }
2238 
2239 static int
2240 read_rat_nos(const char **s, int sign, int strict,
2241  VALUE *num)
2242 {
2243  VALUE den;
2244 
2245  if (!read_num(s, sign, strict, num))
2246  return 0;
2247  if (**s == '/') {
2248  (*s)++;
2249  if (!read_den(s, strict, &den))
2250  return 0;
2251  if (!(FIXNUM_P(den) && FIX2LONG(den) == 1))
2252  *num = f_div(*num, den);
2253  }
2254  return 1;
2255 }
2256 
2257 static int
2258 read_rat(const char **s, int strict,
2259  VALUE *num)
2260 {
2261  int sign;
2262 
2263  sign = read_sign(s);
2264  if (!read_rat_nos(s, sign, strict, num))
2265  return 0;
2266  return 1;
2267 }
2268 
2269 inline static void
2270 skip_ws(const char **s)
2271 {
2272  while (isspace((unsigned char)**s))
2273  (*s)++;
2274 }
2275 
2276 static int
2277 parse_rat(const char *s, int strict,
2278  VALUE *num)
2279 {
2280  skip_ws(&s);
2281  if (!read_rat(&s, strict, num))
2282  return 0;
2283  skip_ws(&s);
2284 
2285  if (strict)
2286  if (*s != '\0')
2287  return 0;
2288  return 1;
2289 }
2290 
2291 static VALUE
2293 {
2294  char *s;
2295  VALUE num;
2296 
2297  rb_must_asciicompat(self);
2298 
2299  s = RSTRING_PTR(self);
2300 
2301  if (!s || memchr(s, '\0', RSTRING_LEN(self)))
2302  rb_raise(rb_eArgError, "string contains null byte");
2303 
2304  if (s && s[RSTRING_LEN(self)]) {
2305  rb_str_modify(self);
2306  s = RSTRING_PTR(self);
2307  s[RSTRING_LEN(self)] = '\0';
2308  }
2309 
2310  if (!s)
2311  s = (char *)"";
2312 
2313  if (!parse_rat(s, 1, &num)) {
2314  VALUE ins = f_inspect(self);
2315  rb_raise(rb_eArgError, "invalid value for convert(): %s",
2316  StringValuePtr(ins));
2317  }
2318 
2319  if (RB_TYPE_P(num, T_FLOAT))
2320  rb_raise(rb_eFloatDomainError, "Infinity");
2321  return num;
2322 }
2323 
2324 /*
2325  * call-seq:
2326  * str.to_r -> rational
2327  *
2328  * Returns a rational which denotes the string form. The parser
2329  * ignores leading whitespaces and trailing garbage. Any digit
2330  * sequences can be separated by an underscore. Returns zero for null
2331  * or garbage string.
2332  *
2333  * NOTE: '0.3'.to_r isn't the same as 0.3.to_r. The former is
2334  * equivalent to '3/10'.to_r, but the latter isn't so.
2335  *
2336  * ' 2 '.to_r #=> (2/1)
2337  * '300/2'.to_r #=> (150/1)
2338  * '-9.2'.to_r #=> (-46/5)
2339  * '-9.2e2'.to_r #=> (-920/1)
2340  * '1_234_567'.to_r #=> (1234567/1)
2341  * '21 june 09'.to_r #=> (21/1)
2342  * '21/06/09'.to_r #=> (7/2)
2343  * 'bwv 1079'.to_r #=> (0/1)
2344  *
2345  * See Kernel.Rational.
2346  */
2347 static VALUE
2349 {
2350  char *s;
2351  VALUE num;
2352 
2353  rb_must_asciicompat(self);
2354 
2355  s = RSTRING_PTR(self);
2356 
2357  if (s && s[RSTRING_LEN(self)]) {
2358  rb_str_modify(self);
2359  s = RSTRING_PTR(self);
2360  s[RSTRING_LEN(self)] = '\0';
2361  }
2362 
2363  if (!s)
2364  s = (char *)"";
2365 
2366  (void)parse_rat(s, 0, &num);
2367 
2368  if (RB_TYPE_P(num, T_FLOAT))
2369  rb_raise(rb_eFloatDomainError, "Infinity");
2370  return num;
2371 }
2372 
2373 VALUE
2374 rb_cstr_to_rat(const char *s, int strict) /* for complex's internal */
2375 {
2376  VALUE num;
2377 
2378  (void)parse_rat(s, strict, &num);
2379 
2380  if (RB_TYPE_P(num, T_FLOAT))
2381  rb_raise(rb_eFloatDomainError, "Infinity");
2382  return num;
2383 }
2384 
2385 static VALUE
2386 nurat_s_convert(int argc, VALUE *argv, VALUE klass)
2387 {
2388  VALUE a1, a2, backref;
2389 
2390  rb_scan_args(argc, argv, "11", &a1, &a2);
2391 
2392  if (NIL_P(a1) || (argc == 2 && NIL_P(a2)))
2393  rb_raise(rb_eTypeError, "can't convert nil into Rational");
2394 
2395  if (RB_TYPE_P(a1, T_COMPLEX)) {
2396  if (k_exact_zero_p(RCOMPLEX(a1)->imag))
2397  a1 = RCOMPLEX(a1)->real;
2398  }
2399 
2400  if (RB_TYPE_P(a2, T_COMPLEX)) {
2401  if (k_exact_zero_p(RCOMPLEX(a2)->imag))
2402  a2 = RCOMPLEX(a2)->real;
2403  }
2404 
2405  backref = rb_backref_get();
2406  rb_match_busy(backref);
2407 
2408  if (RB_TYPE_P(a1, T_FLOAT)) {
2409  a1 = f_to_r(a1);
2410  }
2411  else if (RB_TYPE_P(a1, T_STRING)) {
2412  a1 = string_to_r_strict(a1);
2413  }
2414 
2415  if (RB_TYPE_P(a2, T_FLOAT)) {
2416  a2 = f_to_r(a2);
2417  }
2418  else if (RB_TYPE_P(a2, T_STRING)) {
2419  a2 = string_to_r_strict(a2);
2420  }
2421 
2422  rb_backref_set(backref);
2423 
2424  if (RB_TYPE_P(a1, T_RATIONAL)) {
2425  if (argc == 1 || (k_exact_one_p(a2)))
2426  return a1;
2427  }
2428 
2429  if (argc == 1) {
2430  if (!(k_numeric_p(a1) && k_integer_p(a1)))
2431  return rb_convert_type(a1, T_RATIONAL, "Rational", "to_r");
2432  }
2433  else {
2434  if ((k_numeric_p(a1) && k_numeric_p(a2)) &&
2435  (!f_integer_p(a1) || !f_integer_p(a2)))
2436  return f_div(a1, a2);
2437  }
2438 
2439  {
2440  VALUE argv2[2];
2441  argv2[0] = a1;
2442  argv2[1] = a2;
2443  return nurat_s_new(argc, argv2, klass);
2444  }
2445 }
2446 
2447 /*
2448  * A rational number can be represented as a paired integer number;
2449  * a/b (b>0). Where a is numerator and b is denominator. Integer a
2450  * equals rational a/1 mathematically.
2451  *
2452  * In ruby, you can create rational object with Rational, to_r or
2453  * rationalize method. The return values will be irreducible.
2454  *
2455  * Rational(1) #=> (1/1)
2456  * Rational(2, 3) #=> (2/3)
2457  * Rational(4, -6) #=> (-2/3)
2458  * 3.to_r #=> (3/1)
2459  *
2460  * You can also create rational object from floating-point numbers or
2461  * strings.
2462  *
2463  * Rational(0.3) #=> (5404319552844595/18014398509481984)
2464  * Rational('0.3') #=> (3/10)
2465  * Rational('2/3') #=> (2/3)
2466  *
2467  * 0.3.to_r #=> (5404319552844595/18014398509481984)
2468  * '0.3'.to_r #=> (3/10)
2469  * '2/3'.to_r #=> (2/3)
2470  * 0.3.rationalize #=> (3/10)
2471  *
2472  * A rational object is an exact number, which helps you to write
2473  * program without any rounding errors.
2474  *
2475  * 10.times.inject(0){|t,| t + 0.1} #=> 0.9999999999999999
2476  * 10.times.inject(0){|t,| t + Rational('0.1')} #=> (1/1)
2477  *
2478  * However, when an expression has inexact factor (numerical value or
2479  * operation), will produce an inexact result.
2480  *
2481  * Rational(10) / 3 #=> (10/3)
2482  * Rational(10) / 3.0 #=> 3.3333333333333335
2483  *
2484  * Rational(-8) ** Rational(1, 3)
2485  * #=> (1.0000000000000002+1.7320508075688772i)
2486  */
2487 void
2489 {
2490  VALUE compat;
2491 #undef rb_intern
2492 #define rb_intern(str) rb_intern_const(str)
2493 
2494  assert(fprintf(stderr, "assert() is now active\n"));
2495 
2496  id_abs = rb_intern("abs");
2497  id_cmp = rb_intern("<=>");
2498  id_convert = rb_intern("convert");
2499  id_eqeq_p = rb_intern("==");
2500  id_expt = rb_intern("**");
2501  id_fdiv = rb_intern("fdiv");
2502  id_idiv = rb_intern("div");
2503  id_integer_p = rb_intern("integer?");
2504  id_negate = rb_intern("-@");
2505  id_to_f = rb_intern("to_f");
2506  id_to_i = rb_intern("to_i");
2507  id_truncate = rb_intern("truncate");
2508  id_i_num = rb_intern("@numerator");
2509  id_i_den = rb_intern("@denominator");
2510 
2511  rb_cRational = rb_define_class("Rational", rb_cNumeric);
2512 
2514  rb_undef_method(CLASS_OF(rb_cRational), "allocate");
2515 
2516 #if 0
2517  rb_define_private_method(CLASS_OF(rb_cRational), "new!", nurat_s_new_bang, -1);
2519 #else
2521 #endif
2522 
2524 
2525  rb_define_method(rb_cRational, "numerator", nurat_numerator, 0);
2526  rb_define_method(rb_cRational, "denominator", nurat_denominator, 0);
2527 
2535 
2539 
2540 #if 0 /* NUBY */
2541  rb_define_method(rb_cRational, "//", nurat_idiv, 1);
2542 #endif
2543 
2544 #if 0
2545  rb_define_method(rb_cRational, "quot", nurat_quot, 1);
2546  rb_define_method(rb_cRational, "quotrem", nurat_quotrem, 1);
2547 #endif
2548 
2549 #if 0
2550  rb_define_method(rb_cRational, "rational?", nurat_true, 0);
2551  rb_define_method(rb_cRational, "exact?", nurat_true, 0);
2552 #endif
2553 
2558 
2562  rb_define_method(rb_cRational, "rationalize", nurat_rationalize, -1);
2563 
2565 
2568 
2570  compat = rb_define_class_under(rb_cRational, "compatible", rb_cObject);
2571  rb_define_private_method(compat, "marshal_load", nurat_marshal_load, 1);
2573 
2574  /* --- */
2575 
2576  rb_define_method(rb_cInteger, "gcd", rb_gcd, 1);
2577  rb_define_method(rb_cInteger, "lcm", rb_lcm, 1);
2578  rb_define_method(rb_cInteger, "gcdlcm", rb_gcdlcm, 1);
2579 
2581  rb_define_method(rb_cNumeric, "denominator", numeric_denominator, 0);
2583 
2585  rb_define_method(rb_cInteger, "denominator", integer_denominator, 0);
2586 
2587  rb_define_method(rb_cFloat, "numerator", float_numerator, 0);
2588  rb_define_method(rb_cFloat, "denominator", float_denominator, 0);
2589 
2591  rb_define_method(rb_cNilClass, "rationalize", nilclass_rationalize, -1);
2593  rb_define_method(rb_cInteger, "rationalize", integer_rationalize, -1);
2594  rb_define_method(rb_cFloat, "to_r", float_to_r, 0);
2595  rb_define_method(rb_cFloat, "rationalize", float_rationalize, -1);
2596 
2598 
2600 }
2601 
2602 /*
2603 Local variables:
2604 c-file-style: "ruby"
2605 End:
2606 */
RUBY_EXTERN VALUE rb_cString
Definition: ruby.h:1583
static VALUE numeric_denominator(VALUE self)
Definition: rational.c:1804
VALUE rb_hash(VALUE obj)
Definition: hash.c:106
#define f_ceil(x)
Definition: rational.c:1442
#define FLT_RADIX
Definition: numeric.c:43
static VALUE string_to_r_strict(VALUE self)
Definition: rational.c:2292
static VALUE f_sub(VALUE x, VALUE y)
Definition: rational.c:129
static VALUE f_odd_p(VALUE integer)
Definition: rational.c:961
#define rb_rational_new2(x, y)
Definition: intern.h:171
RUBY_EXTERN VALUE rb_cFloat
Definition: ruby.h:1566
#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:280
static VALUE nurat_mul(VALUE self, VALUE other)
Definition: rational.c:865
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:1288
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:683
static int read_sign(const char **s)
Definition: rational.c:2114
#define T_FIXNUM
Definition: ruby.h:489
static VALUE nurat_expt(VALUE self, VALUE other)
Definition: rational.c:983
#define TWO
Definition: rational.c:27
VALUE rb_lcm(VALUE self, VALUE other)
Definition: rational.c:1730
static VALUE nurat_floor(VALUE self)
Definition: rational.c:1214
static VALUE float_rationalize(int argc, VALUE *argv, VALUE self)
Definition: rational.c:2088
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:1156
#define f_expt10(x)
VALUE rb_gcd(VALUE self, VALUE other)
Definition: rational.c:1712
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:1650
static VALUE nurat_fdiv(VALUE self, VALUE other)
Definition: rational.c:953
void rb_define_private_method(VALUE klass, const char *name, VALUE(*func)(ANYARGS), int argc)
Definition: class.c:1500
#define f_to_r(x)
Definition: rational.c:1783
VALUE rb_eTypeError
Definition: error.c:548
void rb_must_asciicompat(VALUE)
Definition: string.c:1580
#define T_RATIONAL
Definition: ruby.h:495
static ID id_to_i
Definition: rational.c:33
#define k_exact_zero_p(x)
Definition: rational.c:269
VALUE rb_str_concat(VALUE, VALUE)
Definition: string.c:2340
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:775
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:676
#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:2616
void rb_define_alloc_func(VALUE, rb_alloc_func_t)
static VALUE float_denominator(VALUE self)
Definition: rational.c:1891
VALUE rb_obj_is_kind_of(VALUE, VALUE)
Definition: object.c:652
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:1948
double rb_str_to_dbl(VALUE, int)
Definition: object.c:2867
void rb_define_global_function(const char *name, VALUE(*func)(ANYARGS), int argc)
Defines a global function.
Definition: class.c:1684
static VALUE nurat_floor_n(int argc, VALUE *argv, VALUE self)
Definition: rational.c:1330
void Init_Rational(void)
Definition: rational.c:2488
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:1506
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:1674
#define NEWOBJ_OF(obj, type, klass, flags)
Definition: ruby.h:694
static VALUE numeric_numerator(VALUE self)
Definition: rational.c:1792
static VALUE nurat_truncate_n(int argc, VALUE *argv, VALUE self)
Definition: rational.c:1378
#define f_to_s
Definition: rational.c:39
#define RB_TYPE_P(obj, type)
Definition: ruby.h:1664
static VALUE f_add(VALUE x, VALUE y)
Definition: rational.c:63
VALUE rb_rational_raw(VALUE x, VALUE y)
Definition: rational.c:1754
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:1221
static VALUE integer_numerator(VALUE self)
Definition: rational.c:1845
#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:1276
#define rb_rational_raw1(x)
Definition: intern.h:167
VALUE rb_dbl2big(double d)
Definition: bignum.c:5211
void nurat_canonicalization(int)
#define val
RUBY_EXTERN VALUE rb_cObject
Definition: ruby.h:1553
static VALUE f_imul(long a, long b)
Definition: rational.c:652
VALUE rb_str_to_inum(VALUE str, int base, int badcheck)
Definition: bignum.c:4127
static int read_den(const char **s, int strict, VALUE *num)
Definition: rational.c:2231
static ID id_idiv
Definition: rational.c:33
VALUE rb_str_cat2(VALUE, const char *)
Definition: string.c:2159
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:630
static VALUE nurat_dumper(VALUE self)
Definition: rational.c:1643
static int read_digits(const char **s, int strict, VALUE *num, int *count)
Definition: rational.c:2132
VALUE rb_gcdlcm(VALUE self, VALUE other)
Definition: rational.c:1747
static VALUE nurat_to_s(VALUE self)
Definition: rational.c:1614
VALUE rb_cstr_to_rat(const char *s, int strict)
Definition: rational.c:2374
#define T_FLOAT
Definition: ruby.h:481
static int parse_rat(const char *s, int strict, VALUE *num)
Definition: rational.c:2277
int argc
Definition: ruby.c:131
static VALUE nurat_s_convert(int argc, VALUE *argv, VALUE klass)
Definition: rational.c:2386
#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:1348
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:2126
static VALUE nurat_eqeq_p(VALUE self, VALUE other)
Definition: rational.c:1117
static VALUE nurat_sub(VALUE self, VALUE other)
Definition: rational.c:785
#define T_COMPLEX
Definition: ruby.h:496
#define ALLOCV_END(v)
Definition: ruby.h:1349
#define RBIGNUM_DIGITS(b)
Definition: ruby.h:1109
#define f_denominator(x)
Definition: rational.c:1780
static int read_rat_nos(const char **s, int sign, int strict, VALUE *num)
Definition: rational.c:2240
#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:1067
#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
SSL_METHOD *(* func)(void)
Definition: ossl_ssl.c:113
static void float_decode_internal(VALUE self, VALUE *rf, VALUE *rn)
Definition: rational.c:1955
#define f_reciprocal(x)
Definition: rational.c:1447
static VALUE f_minus_one_p(VALUE x)
Definition: rational.c:218
static VALUE float_numerator(VALUE self)
Definition: rational.c:1873
static VALUE nilclass_to_r(VALUE self)
Definition: rational.c:1906
static void skip_ws(const char **s)
Definition: rational.c:2270
int rb_scan_args(int argc, const VALUE *argv, const char *fmt,...)
Definition: class.c:1728
VALUE rb_ivar_set(VALUE, ID, VALUE)
Definition: variable.c:1133
VALUE rb_assoc_new(VALUE car, VALUE cdr)
Definition: array.c:616
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:1243
static VALUE string_to_r(VALUE self)
Definition: rational.c:2348
unsigned long VALUE
Definition: ruby.h:88
VALUE rb_big_mul(VALUE x, VALUE y)
Definition: bignum.c:5995
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:907
#define rb_funcall2
Definition: ruby.h:1456
RUBY_EXTERN VALUE rb_cInteger
Definition: ruby.h:1568
#define FIX2INT(x)
Definition: ruby.h:632
void rb_match_busy(VALUE)
Definition: re.c:1214
VALUE rb_call_super(int, const VALUE *)
Definition: vm_eval.c:274
VALUE rb_Complex(VALUE x, VALUE y)
Definition: complex.c:1337
static VALUE nurat_round_n(int argc, VALUE *argv, VALUE self)
Definition: rational.c:1403
static int read_rat(const char **s, int strict, VALUE *num)
Definition: rational.c:2258
#define isnan(x)
Definition: win32.h:376
RUBY_EXTERN VALUE rb_cNumeric
Definition: ruby.h:1575
static VALUE nurat_to_r(VALUE self)
Definition: rational.c:1436
#define DBL_MANT_DIG
Definition: acosh.c:19
#define f_lshift(x, n)
Definition: rational.c:1979
#define CHAR_BIT
Definition: ruby.h:198
#define LONG2NUM(x)
Definition: ruby.h:1309
static VALUE numeric_quo(VALUE x, VALUE y)
Definition: rational.c:1819
#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:1857
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:605
static VALUE f_to_f(VALUE x)
Definition: rational.c:148
void rb_str_modify(VALUE)
Definition: string.c:1484
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:1420
#define RFLOAT_VALUE(v)
Definition: ruby.h:814
static int islettere(int c)
Definition: rational.c:2176
#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:814
#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:2182
VALUE rb_rational_new(VALUE x, VALUE y)
Definition: rational.c:1760
#define f_expt(x, y)
Definition: date_core.c:39
static VALUE f_format(VALUE self, VALUE(*func)(VALUE))
Definition: rational.c:1591
static VALUE nurat_ceil_n(int argc, VALUE *argv, VALUE self)
Definition: rational.c:1354
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:113
#define T_STRING
Definition: ruby.h:482
static VALUE nilclass_rationalize(int argc, VALUE *argv, VALUE self)
Definition: rational.c:1919
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:1768
#define RCOMPLEX(obj)
Definition: ruby.h:1131
static VALUE nurat_add(VALUE self, VALUE other)
Definition: rational.c:744
static VALUE nurat_round(VALUE self)
Definition: rational.c:1252
VALUE rb_int2big(SIGNED_VALUE n)
Definition: bignum.c:3164
static VALUE nurat_denominator(VALUE self)
Definition: rational.c:641
static VALUE nurat_numerator(VALUE self)
Definition: rational.c:622
#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:1662
#define SIZEOF_BDIGITS
Definition: bigdecimal.h:50
#define StringValuePtr(v)
Definition: ruby.h:540
RUBY_EXTERN VALUE rb_eFloatDomainError
Definition: ruby.h:1613
#define f_nonzero_p(x)
Definition: rational.c:196
static ID id_convert
Definition: rational.c:33
#define f_numerator(x)
Definition: rational.c:1777
#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:1509
void rb_copy_generic_ivar(VALUE, VALUE)
Definition: variable.c:1049
static VALUE integer_to_r(VALUE self)
Definition: rational.c:1935
#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:3961
static VALUE nurat_hash(VALUE self)
Definition: rational.c:1576
static VALUE f_zero_p(VALUE x)
Definition: rational.c:180
static VALUE nurat_rationalize(int argc, VALUE *argv, VALUE self)
Definition: rational.c:1552
#define mod(x, y)
Definition: date_strftime.c:28
static VALUE float_to_r(VALUE self)
Definition: rational.c:1998
#define NULL
Definition: _sdbm.c:103
#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:1488
static int issign(int c)
Definition: rational.c:2108
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:1574
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:47
static VALUE f_gcd_normal(VALUE x, VALUE y)
Definition: rational.c:324
static VALUE nurat_inspect(VALUE self)
Definition: rational.c:1630
VALUE rb_rational_reciprocal(VALUE x)
Definition: rational.c:1694
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:2020
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:287
VALUE rb_gcd_normal(VALUE x, VALUE y)
Definition: rational.c:356
VALUE rb_flt_rationalize(VALUE flt)
Definition: rational.c:2036
static VALUE f_eqeq_p(VALUE x, VALUE y)
Definition: rational.c:156
#define k_exact_one_p(x)
Definition: rational.c:270