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