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