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