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