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