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