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