Ruby  3.4.0dev (2024-11-05 revision 348a53415339076afc4a02fcd09f3ae36e9c4c61)
rational.c (348a53415339076afc4a02fcd09f3ae36e9c4c61)
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_warn("in a**b, b may be too big");
1052  return rb_float_pow(nurat_to_f(self), other);
1053  }
1054  else if (RB_FLOAT_TYPE_P(other) || RB_TYPE_P(other, T_RATIONAL)) {
1055  return rb_float_pow(nurat_to_f(self), other);
1056  }
1057  else {
1058  return rb_num_coerce_bin(self, other, idPow);
1059  }
1060 }
1061 #define nurat_expt rb_rational_pow
1062 
1063 /*
1064  * call-seq:
1065  * rational <=> numeric -> -1, 0, +1, or nil
1066  *
1067  * Returns -1, 0, or +1 depending on whether +rational+ is
1068  * less than, equal to, or greater than +numeric+.
1069  *
1070  * +nil+ is returned if the two values are incomparable.
1071  *
1072  * Rational(2, 3) <=> Rational(2, 3) #=> 0
1073  * Rational(5) <=> 5 #=> 0
1074  * Rational(2, 3) <=> Rational(1, 3) #=> 1
1075  * Rational(1, 3) <=> 1 #=> -1
1076  * Rational(1, 3) <=> 0.3 #=> 1
1077  *
1078  * Rational(1, 3) <=> "0.3" #=> nil
1079  */
1080 VALUE
1081 rb_rational_cmp(VALUE self, VALUE other)
1082 {
1083  switch (TYPE(other)) {
1084  case T_FIXNUM:
1085  case T_BIGNUM:
1086  {
1087  get_dat1(self);
1088 
1089  if (dat->den == LONG2FIX(1))
1090  return rb_int_cmp(dat->num, other); /* c14n */
1091  other = f_rational_new_bang1(CLASS_OF(self), other);
1092  /* FALLTHROUGH */
1093  }
1094 
1095  case T_RATIONAL:
1096  {
1097  VALUE num1, num2;
1098 
1099  get_dat2(self, other);
1100 
1101  if (FIXNUM_P(adat->num) && FIXNUM_P(adat->den) &&
1102  FIXNUM_P(bdat->num) && FIXNUM_P(bdat->den)) {
1103  num1 = f_imul(FIX2LONG(adat->num), FIX2LONG(bdat->den));
1104  num2 = f_imul(FIX2LONG(bdat->num), FIX2LONG(adat->den));
1105  }
1106  else {
1107  num1 = rb_int_mul(adat->num, bdat->den);
1108  num2 = rb_int_mul(bdat->num, adat->den);
1109  }
1110  return rb_int_cmp(rb_int_minus(num1, num2), ZERO);
1111  }
1112 
1113  case T_FLOAT:
1114  return rb_dbl_cmp(nurat_to_double(self), RFLOAT_VALUE(other));
1115 
1116  default:
1117  return rb_num_coerce_cmp(self, other, idCmp);
1118  }
1119 }
1120 
1121 /*
1122  * call-seq:
1123  * rat == object -> true or false
1124  *
1125  * Returns +true+ if +rat+ equals +object+ numerically.
1126  *
1127  * Rational(2, 3) == Rational(2, 3) #=> true
1128  * Rational(5) == 5 #=> true
1129  * Rational(0) == 0.0 #=> true
1130  * Rational('1/3') == 0.33 #=> false
1131  * Rational('1/2') == '1/2' #=> false
1132  */
1133 static VALUE
1134 nurat_eqeq_p(VALUE self, VALUE other)
1135 {
1136  if (RB_INTEGER_TYPE_P(other)) {
1137  get_dat1(self);
1138 
1139  if (RB_INTEGER_TYPE_P(dat->num) && RB_INTEGER_TYPE_P(dat->den)) {
1140  if (INT_ZERO_P(dat->num) && INT_ZERO_P(other))
1141  return Qtrue;
1142 
1143  if (!FIXNUM_P(dat->den))
1144  return Qfalse;
1145  if (FIX2LONG(dat->den) != 1)
1146  return Qfalse;
1147  return rb_int_equal(dat->num, other);
1148  }
1149  else {
1150  const double d = nurat_to_double(self);
1151  return RBOOL(FIXNUM_ZERO_P(rb_dbl_cmp(d, NUM2DBL(other))));
1152  }
1153  }
1154  else if (RB_FLOAT_TYPE_P(other)) {
1155  const double d = nurat_to_double(self);
1156  return RBOOL(FIXNUM_ZERO_P(rb_dbl_cmp(d, RFLOAT_VALUE(other))));
1157  }
1158  else if (RB_TYPE_P(other, T_RATIONAL)) {
1159  {
1160  get_dat2(self, other);
1161 
1162  if (INT_ZERO_P(adat->num) && INT_ZERO_P(bdat->num))
1163  return Qtrue;
1164 
1165  return RBOOL(rb_int_equal(adat->num, bdat->num) &&
1166  rb_int_equal(adat->den, bdat->den));
1167  }
1168  }
1169  else {
1170  return rb_equal(other, self);
1171  }
1172 }
1173 
1174 /* :nodoc: */
1175 static VALUE
1176 nurat_coerce(VALUE self, VALUE other)
1177 {
1178  if (RB_INTEGER_TYPE_P(other)) {
1179  return rb_assoc_new(f_rational_new_bang1(CLASS_OF(self), other), self);
1180  }
1181  else if (RB_FLOAT_TYPE_P(other)) {
1182  return rb_assoc_new(other, nurat_to_f(self));
1183  }
1184  else if (RB_TYPE_P(other, T_RATIONAL)) {
1185  return rb_assoc_new(other, self);
1186  }
1187  else if (RB_TYPE_P(other, T_COMPLEX)) {
1188  if (!k_exact_zero_p(RCOMPLEX(other)->imag))
1189  return rb_assoc_new(other, rb_Complex(self, INT2FIX(0)));
1190  other = RCOMPLEX(other)->real;
1191  if (RB_FLOAT_TYPE_P(other)) {
1192  other = float_to_r(other);
1193  RBASIC_SET_CLASS(other, CLASS_OF(self));
1194  }
1195  else {
1196  other = f_rational_new_bang1(CLASS_OF(self), other);
1197  }
1198  return rb_assoc_new(other, self);
1199  }
1200 
1201  rb_raise(rb_eTypeError, "%s can't be coerced into %s",
1202  rb_obj_classname(other), rb_obj_classname(self));
1203  return Qnil;
1204 }
1205 
1206 /*
1207  * call-seq:
1208  * rat.positive? -> true or false
1209  *
1210  * Returns +true+ if +rat+ is greater than 0.
1211  */
1212 static VALUE
1213 nurat_positive_p(VALUE self)
1214 {
1215  get_dat1(self);
1216  return RBOOL(INT_POSITIVE_P(dat->num));
1217 }
1218 
1219 /*
1220  * call-seq:
1221  * rat.negative? -> true or false
1222  *
1223  * Returns +true+ if +rat+ is less than 0.
1224  */
1225 static VALUE
1226 nurat_negative_p(VALUE self)
1227 {
1228  get_dat1(self);
1229  return RBOOL(INT_NEGATIVE_P(dat->num));
1230 }
1231 
1232 /*
1233  * call-seq:
1234  * rat.abs -> rational
1235  * rat.magnitude -> rational
1236  *
1237  * Returns the absolute value of +rat+.
1238  *
1239  * (1/2r).abs #=> (1/2)
1240  * (-1/2r).abs #=> (1/2)
1241  *
1242  */
1243 
1244 VALUE
1245 rb_rational_abs(VALUE self)
1246 {
1247  get_dat1(self);
1248  if (INT_NEGATIVE_P(dat->num)) {
1249  VALUE num = rb_int_abs(dat->num);
1250  return nurat_s_canonicalize_internal_no_reduce(CLASS_OF(self), num, dat->den);
1251  }
1252  return self;
1253 }
1254 
1255 static VALUE
1256 nurat_floor(VALUE self)
1257 {
1258  get_dat1(self);
1259  return rb_int_idiv(dat->num, dat->den);
1260 }
1261 
1262 static VALUE
1263 nurat_ceil(VALUE self)
1264 {
1265  get_dat1(self);
1266  return rb_int_uminus(rb_int_idiv(rb_int_uminus(dat->num), dat->den));
1267 }
1268 
1269 /*
1270  * call-seq:
1271  * rat.to_i -> integer
1272  *
1273  * Returns the truncated value as an integer.
1274  *
1275  * Equivalent to Rational#truncate.
1276  *
1277  * Rational(2, 3).to_i #=> 0
1278  * Rational(3).to_i #=> 3
1279  * Rational(300.6).to_i #=> 300
1280  * Rational(98, 71).to_i #=> 1
1281  * Rational(-31, 2).to_i #=> -15
1282  */
1283 static VALUE
1284 nurat_truncate(VALUE self)
1285 {
1286  get_dat1(self);
1287  if (INT_NEGATIVE_P(dat->num))
1288  return rb_int_uminus(rb_int_idiv(rb_int_uminus(dat->num), dat->den));
1289  return rb_int_idiv(dat->num, dat->den);
1290 }
1291 
1292 static VALUE
1293 nurat_round_half_up(VALUE self)
1294 {
1295  VALUE num, den, neg;
1296 
1297  get_dat1(self);
1298 
1299  num = dat->num;
1300  den = dat->den;
1301  neg = INT_NEGATIVE_P(num);
1302 
1303  if (neg)
1304  num = rb_int_uminus(num);
1305 
1306  num = rb_int_plus(rb_int_mul(num, TWO), den);
1307  den = rb_int_mul(den, TWO);
1308  num = rb_int_idiv(num, den);
1309 
1310  if (neg)
1311  num = rb_int_uminus(num);
1312 
1313  return num;
1314 }
1315 
1316 static VALUE
1317 nurat_round_half_down(VALUE self)
1318 {
1319  VALUE num, den, neg;
1320 
1321  get_dat1(self);
1322 
1323  num = dat->num;
1324  den = dat->den;
1325  neg = INT_NEGATIVE_P(num);
1326 
1327  if (neg)
1328  num = rb_int_uminus(num);
1329 
1330  num = rb_int_plus(rb_int_mul(num, TWO), den);
1331  num = rb_int_minus(num, ONE);
1332  den = rb_int_mul(den, TWO);
1333  num = rb_int_idiv(num, den);
1334 
1335  if (neg)
1336  num = rb_int_uminus(num);
1337 
1338  return num;
1339 }
1340 
1341 static VALUE
1342 nurat_round_half_even(VALUE self)
1343 {
1344  VALUE num, den, neg, qr;
1345 
1346  get_dat1(self);
1347 
1348  num = dat->num;
1349  den = dat->den;
1350  neg = INT_NEGATIVE_P(num);
1351 
1352  if (neg)
1353  num = rb_int_uminus(num);
1354 
1355  num = rb_int_plus(rb_int_mul(num, TWO), den);
1356  den = rb_int_mul(den, TWO);
1357  qr = rb_int_divmod(num, den);
1358  num = RARRAY_AREF(qr, 0);
1359  if (INT_ZERO_P(RARRAY_AREF(qr, 1)))
1360  num = rb_int_and(num, LONG2FIX(((int)~1)));
1361 
1362  if (neg)
1363  num = rb_int_uminus(num);
1364 
1365  return num;
1366 }
1367 
1368 static VALUE
1369 f_round_common(int argc, VALUE *argv, VALUE self, VALUE (*func)(VALUE))
1370 {
1371  VALUE n, b, s;
1372 
1373  if (rb_check_arity(argc, 0, 1) == 0)
1374  return (*func)(self);
1375 
1376  n = argv[0];
1377 
1378  if (!k_integer_p(n))
1379  rb_raise(rb_eTypeError, "not an integer");
1380 
1381  b = f_expt10(n);
1382  s = rb_rational_mul(self, b);
1383 
1384  if (k_float_p(s)) {
1385  if (INT_NEGATIVE_P(n))
1386  return ZERO;
1387  return self;
1388  }
1389 
1390  if (!k_rational_p(s)) {
1391  s = f_rational_new_bang1(CLASS_OF(self), s);
1392  }
1393 
1394  s = (*func)(s);
1395 
1396  s = rb_rational_div(f_rational_new_bang1(CLASS_OF(self), s), b);
1397 
1398  if (RB_TYPE_P(s, T_RATIONAL) && FIX2INT(rb_int_cmp(n, ONE)) < 0)
1399  s = nurat_truncate(s);
1400 
1401  return s;
1402 }
1403 
1404 VALUE
1405 rb_rational_floor(VALUE self, int ndigits)
1406 {
1407  if (ndigits == 0) {
1408  return nurat_floor(self);
1409  }
1410  else {
1411  VALUE n = INT2NUM(ndigits);
1412  return f_round_common(1, &n, self, nurat_floor);
1413  }
1414 }
1415 
1416 /*
1417  * call-seq:
1418  * rat.floor([ndigits]) -> integer or rational
1419  *
1420  * Returns the largest number less than or equal to +rat+ with
1421  * a precision of +ndigits+ decimal digits (default: 0).
1422  *
1423  * When the precision is negative, the returned value is an integer
1424  * with at least <code>ndigits.abs</code> trailing zeros.
1425  *
1426  * Returns a rational when +ndigits+ is positive,
1427  * otherwise returns an integer.
1428  *
1429  * Rational(3).floor #=> 3
1430  * Rational(2, 3).floor #=> 0
1431  * Rational(-3, 2).floor #=> -2
1432  *
1433  * # decimal - 1 2 3 . 4 5 6
1434  * # ^ ^ ^ ^ ^ ^
1435  * # precision -3 -2 -1 0 +1 +2
1436  *
1437  * Rational('-123.456').floor(+1).to_f #=> -123.5
1438  * Rational('-123.456').floor(-1) #=> -130
1439  */
1440 static VALUE
1441 nurat_floor_n(int argc, VALUE *argv, VALUE self)
1442 {
1443  return f_round_common(argc, argv, self, nurat_floor);
1444 }
1445 
1446 /*
1447  * call-seq:
1448  * rat.ceil([ndigits]) -> integer or rational
1449  *
1450  * Returns the smallest number greater than or equal to +rat+ with
1451  * a precision of +ndigits+ decimal digits (default: 0).
1452  *
1453  * When the precision is negative, the returned value is an integer
1454  * with at least <code>ndigits.abs</code> trailing zeros.
1455  *
1456  * Returns a rational when +ndigits+ is positive,
1457  * otherwise returns an integer.
1458  *
1459  * Rational(3).ceil #=> 3
1460  * Rational(2, 3).ceil #=> 1
1461  * Rational(-3, 2).ceil #=> -1
1462  *
1463  * # decimal - 1 2 3 . 4 5 6
1464  * # ^ ^ ^ ^ ^ ^
1465  * # precision -3 -2 -1 0 +1 +2
1466  *
1467  * Rational('-123.456').ceil(+1).to_f #=> -123.4
1468  * Rational('-123.456').ceil(-1) #=> -120
1469  */
1470 static VALUE
1471 nurat_ceil_n(int argc, VALUE *argv, VALUE self)
1472 {
1473  return f_round_common(argc, argv, self, nurat_ceil);
1474 }
1475 
1476 /*
1477  * call-seq:
1478  * rat.truncate([ndigits]) -> integer or rational
1479  *
1480  * Returns +rat+ truncated (toward zero) to
1481  * a precision of +ndigits+ decimal digits (default: 0).
1482  *
1483  * When the precision is negative, the returned value is an integer
1484  * with at least <code>ndigits.abs</code> trailing zeros.
1485  *
1486  * Returns a rational when +ndigits+ is positive,
1487  * otherwise returns an integer.
1488  *
1489  * Rational(3).truncate #=> 3
1490  * Rational(2, 3).truncate #=> 0
1491  * Rational(-3, 2).truncate #=> -1
1492  *
1493  * # decimal - 1 2 3 . 4 5 6
1494  * # ^ ^ ^ ^ ^ ^
1495  * # precision -3 -2 -1 0 +1 +2
1496  *
1497  * Rational('-123.456').truncate(+1).to_f #=> -123.4
1498  * Rational('-123.456').truncate(-1) #=> -120
1499  */
1500 static VALUE
1501 nurat_truncate_n(int argc, VALUE *argv, VALUE self)
1502 {
1503  return f_round_common(argc, argv, self, nurat_truncate);
1504 }
1505 
1506 /*
1507  * call-seq:
1508  * rat.round([ndigits] [, half: mode]) -> integer or rational
1509  *
1510  * Returns +rat+ rounded to the nearest value with
1511  * a precision of +ndigits+ decimal digits (default: 0).
1512  *
1513  * When the precision is negative, the returned value is an integer
1514  * with at least <code>ndigits.abs</code> trailing zeros.
1515  *
1516  * Returns a rational when +ndigits+ is positive,
1517  * otherwise returns an integer.
1518  *
1519  * Rational(3).round #=> 3
1520  * Rational(2, 3).round #=> 1
1521  * Rational(-3, 2).round #=> -2
1522  *
1523  * # decimal - 1 2 3 . 4 5 6
1524  * # ^ ^ ^ ^ ^ ^
1525  * # precision -3 -2 -1 0 +1 +2
1526  *
1527  * Rational('-123.456').round(+1).to_f #=> -123.5
1528  * Rational('-123.456').round(-1) #=> -120
1529  *
1530  * The optional +half+ keyword argument is available
1531  * similar to Float#round.
1532  *
1533  * Rational(25, 100).round(1, half: :up) #=> (3/10)
1534  * Rational(25, 100).round(1, half: :down) #=> (1/5)
1535  * Rational(25, 100).round(1, half: :even) #=> (1/5)
1536  * Rational(35, 100).round(1, half: :up) #=> (2/5)
1537  * Rational(35, 100).round(1, half: :down) #=> (3/10)
1538  * Rational(35, 100).round(1, half: :even) #=> (2/5)
1539  * Rational(-25, 100).round(1, half: :up) #=> (-3/10)
1540  * Rational(-25, 100).round(1, half: :down) #=> (-1/5)
1541  * Rational(-25, 100).round(1, half: :even) #=> (-1/5)
1542  */
1543 static VALUE
1544 nurat_round_n(int argc, VALUE *argv, VALUE self)
1545 {
1546  VALUE opt;
1547  enum ruby_num_rounding_mode mode = (
1548  argc = rb_scan_args(argc, argv, "*:", NULL, &opt),
1549  rb_num_get_rounding_option(opt));
1550  VALUE (*round_func)(VALUE) = ROUND_FUNC(mode, nurat_round);
1551  return f_round_common(argc, argv, self, round_func);
1552 }
1553 
1554 VALUE
1555 rb_flo_round_by_rational(int argc, VALUE *argv, VALUE num)
1556 {
1557  return nurat_to_f(nurat_round_n(argc, argv, float_to_r(num)));
1558 }
1559 
1560 static double
1561 nurat_to_double(VALUE self)
1562 {
1563  get_dat1(self);
1564  if (!RB_INTEGER_TYPE_P(dat->num) || !RB_INTEGER_TYPE_P(dat->den)) {
1565  return NUM2DBL(dat->num) / NUM2DBL(dat->den);
1566  }
1567  return rb_int_fdiv_double(dat->num, dat->den);
1568 }
1569 
1570 /*
1571  * call-seq:
1572  * rat.to_f -> float
1573  *
1574  * Returns the value as a Float.
1575  *
1576  * Rational(2).to_f #=> 2.0
1577  * Rational(9, 4).to_f #=> 2.25
1578  * Rational(-3, 4).to_f #=> -0.75
1579  * Rational(20, 3).to_f #=> 6.666666666666667
1580  */
1581 static VALUE
1582 nurat_to_f(VALUE self)
1583 {
1584  return DBL2NUM(nurat_to_double(self));
1585 }
1586 
1587 /*
1588  * call-seq:
1589  * rat.to_r -> self
1590  *
1591  * Returns self.
1592  *
1593  * Rational(2).to_r #=> (2/1)
1594  * Rational(-8, 6).to_r #=> (-4/3)
1595  */
1596 static VALUE
1597 nurat_to_r(VALUE self)
1598 {
1599  return self;
1600 }
1601 
1602 #define id_ceil rb_intern("ceil")
1603 static VALUE
1604 f_ceil(VALUE x)
1605 {
1606  if (RB_INTEGER_TYPE_P(x))
1607  return x;
1608  if (RB_FLOAT_TYPE_P(x))
1609  return rb_float_ceil(x, 0);
1610 
1611  return rb_funcall(x, id_ceil, 0);
1612 }
1613 
1614 #define id_quo idQuo
1615 static VALUE
1616 f_quo(VALUE x, VALUE y)
1617 {
1618  if (RB_INTEGER_TYPE_P(x))
1619  return rb_int_div(x, y);
1620  if (RB_FLOAT_TYPE_P(x))
1621  return DBL2NUM(RFLOAT_VALUE(x) / RFLOAT_VALUE(y));
1622 
1623  return rb_funcallv(x, id_quo, 1, &y);
1624 }
1625 
1626 #define f_reciprocal(x) f_quo(ONE, (x))
1627 
1628 /*
1629  The algorithm here is the method described in CLISP. Bruno Haible has
1630  graciously given permission to use this algorithm. He says, "You can use
1631  it, if you present the following explanation of the algorithm."
1632 
1633  Algorithm (recursively presented):
1634  If x is a rational number, return x.
1635  If x = 0.0, return 0.
1636  If x < 0.0, return (- (rationalize (- x))).
1637  If x > 0.0:
1638  Call (integer-decode-float x). It returns a m,e,s=1 (mantissa,
1639  exponent, sign).
1640  If m = 0 or e >= 0: return x = m*2^e.
1641  Search a rational number between a = (m-1/2)*2^e and b = (m+1/2)*2^e
1642  with smallest possible numerator and denominator.
1643  Note 1: If m is a power of 2, we ought to take a = (m-1/4)*2^e.
1644  But in this case the result will be x itself anyway, regardless of
1645  the choice of a. Therefore we can simply ignore this case.
1646  Note 2: At first, we need to consider the closed interval [a,b].
1647  but since a and b have the denominator 2^(|e|+1) whereas x itself
1648  has a denominator <= 2^|e|, we can restrict the search to the open
1649  interval (a,b).
1650  So, for given a and b (0 < a < b) we are searching a rational number
1651  y with a <= y <= b.
1652  Recursive algorithm fraction_between(a,b):
1653  c := (ceiling a)
1654  if c < b
1655  then return c ; because a <= c < b, c integer
1656  else
1657  ; a is not integer (otherwise we would have had c = a < b)
1658  k := c-1 ; k = floor(a), k < a < b <= k+1
1659  return y = k + 1/fraction_between(1/(b-k), 1/(a-k))
1660  ; note 1 <= 1/(b-k) < 1/(a-k)
1661 
1662  You can see that we are actually computing a continued fraction expansion.
1663 
1664  Algorithm (iterative):
1665  If x is rational, return x.
1666  Call (integer-decode-float x). It returns a m,e,s (mantissa,
1667  exponent, sign).
1668  If m = 0 or e >= 0, return m*2^e*s. (This includes the case x = 0.0.)
1669  Create rational numbers a := (2*m-1)*2^(e-1) and b := (2*m+1)*2^(e-1)
1670  (positive and already in lowest terms because the denominator is a
1671  power of two and the numerator is odd).
1672  Start a continued fraction expansion
1673  p[-1] := 0, p[0] := 1, q[-1] := 1, q[0] := 0, i := 0.
1674  Loop
1675  c := (ceiling a)
1676  if c >= b
1677  then k := c-1, partial_quotient(k), (a,b) := (1/(b-k),1/(a-k)),
1678  goto Loop
1679  finally partial_quotient(c).
1680  Here partial_quotient(c) denotes the iteration
1681  i := i+1, p[i] := c*p[i-1]+p[i-2], q[i] := c*q[i-1]+q[i-2].
1682  At the end, return s * (p[i]/q[i]).
1683  This rational number is already in lowest terms because
1684  p[i]*q[i-1]-p[i-1]*q[i] = (-1)^i.
1685 */
1686 
1687 static void
1688 nurat_rationalize_internal(VALUE a, VALUE b, VALUE *p, VALUE *q)
1689 {
1690  VALUE c, k, t, p0, p1, p2, q0, q1, q2;
1691 
1692  p0 = ZERO;
1693  p1 = ONE;
1694  q0 = ONE;
1695  q1 = ZERO;
1696 
1697  while (1) {
1698  c = f_ceil(a);
1699  if (f_lt_p(c, b))
1700  break;
1701  k = f_sub(c, ONE);
1702  p2 = f_add(f_mul(k, p1), p0);
1703  q2 = f_add(f_mul(k, q1), q0);
1704  t = f_reciprocal(f_sub(b, k));
1705  b = f_reciprocal(f_sub(a, k));
1706  a = t;
1707  p0 = p1;
1708  q0 = q1;
1709  p1 = p2;
1710  q1 = q2;
1711  }
1712  *p = f_add(f_mul(c, p1), p0);
1713  *q = f_add(f_mul(c, q1), q0);
1714 }
1715 
1716 /*
1717  * call-seq:
1718  * rat.rationalize -> self
1719  * rat.rationalize(eps) -> rational
1720  *
1721  * Returns a simpler approximation of the value if the optional
1722  * argument +eps+ is given (rat-|eps| <= result <= rat+|eps|),
1723  * self otherwise.
1724  *
1725  * r = Rational(5033165, 16777216)
1726  * r.rationalize #=> (5033165/16777216)
1727  * r.rationalize(Rational('0.01')) #=> (3/10)
1728  * r.rationalize(Rational('0.1')) #=> (1/3)
1729  */
1730 static VALUE
1731 nurat_rationalize(int argc, VALUE *argv, VALUE self)
1732 {
1733  VALUE e, a, b, p, q;
1734  VALUE rat = self;
1735  get_dat1(self);
1736 
1737  if (rb_check_arity(argc, 0, 1) == 0)
1738  return self;
1739 
1740  e = f_abs(argv[0]);
1741 
1742  if (INT_NEGATIVE_P(dat->num)) {
1743  rat = f_rational_new2(RBASIC_CLASS(self), rb_int_uminus(dat->num), dat->den);
1744  }
1745 
1746  a = FIXNUM_ZERO_P(e) ? rat : rb_rational_minus(rat, e);
1747  b = FIXNUM_ZERO_P(e) ? rat : rb_rational_plus(rat, e);
1748 
1749  if (f_eqeq_p(a, b))
1750  return self;
1751 
1752  nurat_rationalize_internal(a, b, &p, &q);
1753  if (rat != self) {
1754  RATIONAL_SET_NUM(rat, rb_int_uminus(p));
1755  RATIONAL_SET_DEN(rat, q);
1756  return rat;
1757  }
1758  return f_rational_new2(CLASS_OF(self), p, q);
1759 }
1760 
1761 /* :nodoc: */
1762 st_index_t
1763 rb_rational_hash(VALUE self)
1764 {
1765  st_index_t v, h[2];
1766  VALUE n;
1767 
1768  get_dat1(self);
1769  n = rb_hash(dat->num);
1770  h[0] = NUM2LONG(n);
1771  n = rb_hash(dat->den);
1772  h[1] = NUM2LONG(n);
1773  v = rb_memhash(h, sizeof(h));
1774  return v;
1775 }
1776 
1777 static VALUE
1778 nurat_hash(VALUE self)
1779 {
1780  return ST2FIX(rb_rational_hash(self));
1781 }
1782 
1783 
1784 static VALUE
1785 f_format(VALUE self, VALUE (*func)(VALUE))
1786 {
1787  VALUE s;
1788  get_dat1(self);
1789 
1790  s = (*func)(dat->num);
1791  rb_str_cat2(s, "/");
1792  rb_str_concat(s, (*func)(dat->den));
1793 
1794  return s;
1795 }
1796 
1797 /*
1798  * call-seq:
1799  * rat.to_s -> string
1800  *
1801  * Returns the value as a string.
1802  *
1803  * Rational(2).to_s #=> "2/1"
1804  * Rational(-8, 6).to_s #=> "-4/3"
1805  * Rational('1/2').to_s #=> "1/2"
1806  */
1807 static VALUE
1808 nurat_to_s(VALUE self)
1809 {
1810  return f_format(self, f_to_s);
1811 }
1812 
1813 /*
1814  * call-seq:
1815  * rat.inspect -> string
1816  *
1817  * Returns the value as a string for inspection.
1818  *
1819  * Rational(2).inspect #=> "(2/1)"
1820  * Rational(-8, 6).inspect #=> "(-4/3)"
1821  * Rational('1/2').inspect #=> "(1/2)"
1822  */
1823 static VALUE
1824 nurat_inspect(VALUE self)
1825 {
1826  VALUE s;
1827 
1828  s = rb_usascii_str_new2("(");
1829  rb_str_concat(s, f_format(self, f_inspect));
1830  rb_str_cat2(s, ")");
1831 
1832  return s;
1833 }
1834 
1835 /* :nodoc: */
1836 static VALUE
1837 nurat_dumper(VALUE self)
1838 {
1839  return self;
1840 }
1841 
1842 /* :nodoc: */
1843 static VALUE
1844 nurat_loader(VALUE self, VALUE a)
1845 {
1846  VALUE num, den;
1847 
1848  get_dat1(self);
1849  num = rb_ivar_get(a, id_i_num);
1850  den = rb_ivar_get(a, id_i_den);
1851  nurat_int_check(num);
1852  nurat_int_check(den);
1853  nurat_canonicalize(&num, &den);
1854  RATIONAL_SET_NUM((VALUE)dat, num);
1855  RATIONAL_SET_DEN((VALUE)dat, den);
1856  OBJ_FREEZE(self);
1857 
1858  return self;
1859 }
1860 
1861 /* :nodoc: */
1862 static VALUE
1863 nurat_marshal_dump(VALUE self)
1864 {
1865  VALUE a;
1866  get_dat1(self);
1867 
1868  a = rb_assoc_new(dat->num, dat->den);
1869  rb_copy_generic_ivar(a, self);
1870  return a;
1871 }
1872 
1873 /* :nodoc: */
1874 static VALUE
1875 nurat_marshal_load(VALUE self, VALUE a)
1876 {
1877  VALUE num, den;
1878 
1879  rb_check_frozen(self);
1880 
1881  Check_Type(a, T_ARRAY);
1882  if (RARRAY_LEN(a) != 2)
1883  rb_raise(rb_eArgError, "marshaled rational must have an array whose length is 2 but %ld", RARRAY_LEN(a));
1884 
1885  num = RARRAY_AREF(a, 0);
1886  den = RARRAY_AREF(a, 1);
1887  nurat_int_check(num);
1888  nurat_int_check(den);
1889  nurat_canonicalize(&num, &den);
1890  rb_ivar_set(self, id_i_num, num);
1891  rb_ivar_set(self, id_i_den, den);
1892 
1893  return self;
1894 }
1895 
1896 VALUE
1897 rb_rational_reciprocal(VALUE x)
1898 {
1899  get_dat1(x);
1900  return nurat_convert(CLASS_OF(x), dat->den, dat->num, FALSE);
1901 }
1902 
1903 /*
1904  * call-seq:
1905  * int.gcd(other_int) -> integer
1906  *
1907  * Returns the greatest common divisor of the two integers.
1908  * The result is always positive. 0.gcd(x) and x.gcd(0) return x.abs.
1909  *
1910  * 36.gcd(60) #=> 12
1911  * 2.gcd(2) #=> 2
1912  * 3.gcd(-7) #=> 1
1913  * ((1<<31)-1).gcd((1<<61)-1) #=> 1
1914  */
1915 VALUE
1916 rb_gcd(VALUE self, VALUE other)
1917 {
1918  other = nurat_int_value(other);
1919  return f_gcd(self, other);
1920 }
1921 
1922 /*
1923  * call-seq:
1924  * int.lcm(other_int) -> integer
1925  *
1926  * Returns the least common multiple of the two integers.
1927  * The result is always positive. 0.lcm(x) and x.lcm(0) return zero.
1928  *
1929  * 36.lcm(60) #=> 180
1930  * 2.lcm(2) #=> 2
1931  * 3.lcm(-7) #=> 21
1932  * ((1<<31)-1).lcm((1<<61)-1) #=> 4951760154835678088235319297
1933  */
1934 VALUE
1935 rb_lcm(VALUE self, VALUE other)
1936 {
1937  other = nurat_int_value(other);
1938  return f_lcm(self, other);
1939 }
1940 
1941 /*
1942  * call-seq:
1943  * int.gcdlcm(other_int) -> array
1944  *
1945  * Returns an array with the greatest common divisor and
1946  * the least common multiple of the two integers, [gcd, lcm].
1947  *
1948  * 36.gcdlcm(60) #=> [12, 180]
1949  * 2.gcdlcm(2) #=> [2, 2]
1950  * 3.gcdlcm(-7) #=> [1, 21]
1951  * ((1<<31)-1).gcdlcm((1<<61)-1) #=> [1, 4951760154835678088235319297]
1952  */
1953 VALUE
1954 rb_gcdlcm(VALUE self, VALUE other)
1955 {
1956  other = nurat_int_value(other);
1957  return rb_assoc_new(f_gcd(self, other), f_lcm(self, other));
1958 }
1959 
1960 VALUE
1962 {
1963  if (! RB_INTEGER_TYPE_P(x))
1964  x = rb_to_int(x);
1965  if (! RB_INTEGER_TYPE_P(y))
1966  y = rb_to_int(y);
1967  if (INT_NEGATIVE_P(y)) {
1968  x = rb_int_uminus(x);
1969  y = rb_int_uminus(y);
1970  }
1971  return nurat_s_new_internal(rb_cRational, x, y);
1972 }
1973 
1974 VALUE
1976 {
1977  return nurat_s_canonicalize_internal(rb_cRational, x, y);
1978 }
1979 
1980 VALUE
1982 {
1983  VALUE a[2];
1984  a[0] = x;
1985  a[1] = y;
1986  return nurat_s_convert(2, a, rb_cRational);
1987 }
1988 
1989 VALUE
1991 {
1992  return nurat_numerator(rat);
1993 }
1994 
1995 VALUE
1997 {
1998  return nurat_denominator(rat);
1999 }
2000 
2001 #define id_numerator rb_intern("numerator")
2002 #define f_numerator(x) rb_funcall((x), id_numerator, 0)
2003 
2004 #define id_denominator rb_intern("denominator")
2005 #define f_denominator(x) rb_funcall((x), id_denominator, 0)
2006 
2007 #define id_to_r idTo_r
2008 #define f_to_r(x) rb_funcall((x), id_to_r, 0)
2009 
2010 /*
2011  * call-seq:
2012  * num.numerator -> integer
2013  *
2014  * Returns the numerator.
2015  */
2016 static VALUE
2017 numeric_numerator(VALUE self)
2018 {
2019  return f_numerator(f_to_r(self));
2020 }
2021 
2022 /*
2023  * call-seq:
2024  * num.denominator -> integer
2025  *
2026  * Returns the denominator (always positive).
2027  */
2028 static VALUE
2029 numeric_denominator(VALUE self)
2030 {
2031  return f_denominator(f_to_r(self));
2032 }
2033 
2034 
2035 /*
2036  * call-seq:
2037  * num.quo(int_or_rat) -> rat
2038  * num.quo(flo) -> flo
2039  *
2040  * Returns the most exact division (rational for integers, float for floats).
2041  */
2042 
2043 VALUE
2044 rb_numeric_quo(VALUE x, VALUE y)
2045 {
2046  if (RB_TYPE_P(x, T_COMPLEX)) {
2047  return rb_complex_div(x, y);
2048  }
2049 
2050  if (RB_FLOAT_TYPE_P(y)) {
2051  return rb_funcallv(x, idFdiv, 1, &y);
2052  }
2053 
2054  x = rb_convert_type(x, T_RATIONAL, "Rational", "to_r");
2055  return rb_rational_div(x, y);
2056 }
2057 
2058 VALUE
2059 rb_rational_canonicalize(VALUE x)
2060 {
2061  if (RB_TYPE_P(x, T_RATIONAL)) {
2062  get_dat1(x);
2063  if (f_one_p(dat->den)) return dat->num;
2064  }
2065  return x;
2066 }
2067 
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
2081 rb_float_numerator(VALUE self)
2082 {
2083  double d = RFLOAT_VALUE(self);
2084  VALUE r;
2085  if (!isfinite(d))
2086  return self;
2087  r = float_to_r(self);
2088  return nurat_numerator(r);
2089 }
2090 
2091 /*
2092  * call-seq:
2093  * flo.denominator -> integer
2094  *
2095  * Returns the denominator (always positive). The result is machine
2096  * dependent.
2097  *
2098  * See also Float#numerator.
2099  */
2100 VALUE
2101 rb_float_denominator(VALUE self)
2102 {
2103  double d = RFLOAT_VALUE(self);
2104  VALUE r;
2105  if (!isfinite(d))
2106  return INT2FIX(1);
2107  r = float_to_r(self);
2108  return nurat_denominator(r);
2109 }
2110 
2111 /*
2112  * call-seq:
2113  * to_r -> (0/1)
2114  *
2115  * Returns zero as a Rational:
2116  *
2117  * nil.to_r # => (0/1)
2118  *
2119  */
2120 static VALUE
2121 nilclass_to_r(VALUE self)
2122 {
2123  return rb_rational_new1(INT2FIX(0));
2124 }
2125 
2126 /*
2127  * call-seq:
2128  * rationalize(eps = nil) -> (0/1)
2129  *
2130  * Returns zero as a Rational:
2131  *
2132  * nil.rationalize # => (0/1)
2133  *
2134  * Argument +eps+ is ignored.
2135  *
2136  */
2137 static VALUE
2138 nilclass_rationalize(int argc, VALUE *argv, VALUE self)
2139 {
2140  rb_check_arity(argc, 0, 1);
2141  return nilclass_to_r(self);
2142 }
2143 
2144 /*
2145  * call-seq:
2146  * int.to_r -> rational
2147  *
2148  * Returns the value as a rational.
2149  *
2150  * 1.to_r #=> (1/1)
2151  * (1<<64).to_r #=> (18446744073709551616/1)
2152  */
2153 static VALUE
2154 integer_to_r(VALUE self)
2155 {
2156  return rb_rational_new1(self);
2157 }
2158 
2159 /*
2160  * call-seq:
2161  * int.rationalize([eps]) -> rational
2162  *
2163  * Returns the value as a rational. The optional argument +eps+ is
2164  * always ignored.
2165  */
2166 static VALUE
2167 integer_rationalize(int argc, VALUE *argv, VALUE self)
2168 {
2169  rb_check_arity(argc, 0, 1);
2170  return integer_to_r(self);
2171 }
2172 
2173 static void
2174 float_decode_internal(VALUE self, VALUE *rf, int *n)
2175 {
2176  double f;
2177 
2178  f = frexp(RFLOAT_VALUE(self), n);
2179  f = ldexp(f, DBL_MANT_DIG);
2180  *n -= DBL_MANT_DIG;
2181  *rf = rb_dbl2big(f);
2182 }
2183 
2184 /*
2185  * call-seq:
2186  * flt.to_r -> rational
2187  *
2188  * Returns the value as a rational.
2189  *
2190  * 2.0.to_r #=> (2/1)
2191  * 2.5.to_r #=> (5/2)
2192  * -0.75.to_r #=> (-3/4)
2193  * 0.0.to_r #=> (0/1)
2194  * 0.3.to_r #=> (5404319552844595/18014398509481984)
2195  *
2196  * NOTE: 0.3.to_r isn't the same as "0.3".to_r. The latter is
2197  * equivalent to "3/10".to_r, but the former isn't so.
2198  *
2199  * 0.3.to_r == 3/10r #=> false
2200  * "0.3".to_r == 3/10r #=> true
2201  *
2202  * See also Float#rationalize.
2203  */
2204 static VALUE
2205 float_to_r(VALUE self)
2206 {
2207  VALUE f;
2208  int n;
2209 
2210  float_decode_internal(self, &f, &n);
2211 #if FLT_RADIX == 2
2212  if (n == 0)
2213  return rb_rational_new1(f);
2214  if (n > 0)
2215  return rb_rational_new1(rb_int_lshift(f, INT2FIX(n)));
2216  n = -n;
2217  return rb_rational_new2(f, rb_int_lshift(ONE, INT2FIX(n)));
2218 #else
2219  f = rb_int_mul(f, rb_int_pow(INT2FIX(FLT_RADIX), n));
2220  if (RB_TYPE_P(f, T_RATIONAL))
2221  return f;
2222  return rb_rational_new1(f);
2223 #endif
2224 }
2225 
2226 VALUE
2228 {
2229  VALUE e, a, b, p, q;
2230 
2231  e = f_abs(prec);
2232  a = f_sub(flt, e);
2233  b = f_add(flt, e);
2234 
2235  if (f_eqeq_p(a, b))
2236  return float_to_r(flt);
2237 
2238  nurat_rationalize_internal(a, b, &p, &q);
2239  return rb_rational_new2(p, q);
2240 }
2241 
2242 VALUE
2244 {
2245  VALUE a, b, f, p, q, den;
2246  int n;
2247 
2248  float_decode_internal(flt, &f, &n);
2249  if (INT_ZERO_P(f) || n >= 0)
2250  return rb_rational_new1(rb_int_lshift(f, INT2FIX(n)));
2251 
2252  {
2253  VALUE radix_times_f;
2254 
2255  radix_times_f = rb_int_mul(INT2FIX(FLT_RADIX), f);
2256 #if FLT_RADIX == 2 && 0
2257  den = rb_int_lshift(ONE, INT2FIX(1-n));
2258 #else
2259  den = rb_int_positive_pow(FLT_RADIX, 1-n);
2260 #endif
2261 
2262  a = rb_int_minus(radix_times_f, INT2FIX(FLT_RADIX - 1));
2263  b = rb_int_plus(radix_times_f, INT2FIX(FLT_RADIX - 1));
2264  }
2265 
2266  if (f_eqeq_p(a, b))
2267  return float_to_r(flt);
2268 
2269  a = rb_rational_new2(a, den);
2270  b = rb_rational_new2(b, den);
2271  nurat_rationalize_internal(a, b, &p, &q);
2272  return rb_rational_new2(p, q);
2273 }
2274 
2275 /*
2276  * call-seq:
2277  * flt.rationalize([eps]) -> rational
2278  *
2279  * Returns a simpler approximation of the value (flt-|eps| <= result
2280  * <= flt+|eps|). If the optional argument +eps+ is not given,
2281  * it will be chosen automatically.
2282  *
2283  * 0.3.rationalize #=> (3/10)
2284  * 1.333.rationalize #=> (1333/1000)
2285  * 1.333.rationalize(0.01) #=> (4/3)
2286  *
2287  * See also Float#to_r.
2288  */
2289 static VALUE
2290 float_rationalize(int argc, VALUE *argv, VALUE self)
2291 {
2292  double d = RFLOAT_VALUE(self);
2293  VALUE rat;
2294  int neg = d < 0.0;
2295  if (neg) self = DBL2NUM(-d);
2296 
2297  if (rb_check_arity(argc, 0, 1)) {
2298  rat = rb_flt_rationalize_with_prec(self, argv[0]);
2299  }
2300  else {
2301  rat = rb_flt_rationalize(self);
2302  }
2303  if (neg) RATIONAL_SET_NUM(rat, rb_int_uminus(RRATIONAL(rat)->num));
2304  return rat;
2305 }
2306 
2307 inline static int
2308 issign(int c)
2309 {
2310  return (c == '-' || c == '+');
2311 }
2312 
2313 static int
2314 read_sign(const char **s, const char *const e)
2315 {
2316  int sign = '?';
2317 
2318  if (*s < e && issign(**s)) {
2319  sign = **s;
2320  (*s)++;
2321  }
2322  return sign;
2323 }
2324 
2325 inline static int
2326 islettere(int c)
2327 {
2328  return (c == 'e' || c == 'E');
2329 }
2330 
2331 static VALUE
2332 negate_num(VALUE num)
2333 {
2334  if (FIXNUM_P(num)) {
2335  return rb_int_uminus(num);
2336  }
2337  else {
2338  BIGNUM_NEGATE(num);
2339  return rb_big_norm(num);
2340  }
2341 }
2342 
2343 static int
2344 read_num(const char **s, const char *const end, VALUE *num, VALUE *nexp)
2345 {
2346  VALUE fp = ONE, exp, fn = ZERO, n = ZERO;
2347  int expsign = 0, ok = 0;
2348  char *e;
2349 
2350  *nexp = ZERO;
2351  *num = ZERO;
2352  if (*s < end && **s != '.') {
2353  n = rb_int_parse_cstr(*s, end-*s, &e, NULL,
2354  10, RB_INT_PARSE_UNDERSCORE);
2355  if (NIL_P(n))
2356  return 0;
2357  *s = e;
2358  *num = n;
2359  ok = 1;
2360  }
2361 
2362  if (*s < end && **s == '.') {
2363  size_t count = 0;
2364 
2365  (*s)++;
2366  fp = rb_int_parse_cstr(*s, end-*s, &e, &count,
2367  10, RB_INT_PARSE_UNDERSCORE);
2368  if (NIL_P(fp))
2369  return 1;
2370  *s = e;
2371  {
2372  VALUE l = f_expt10(*nexp = SIZET2NUM(count));
2373  n = n == ZERO ? fp : rb_int_plus(rb_int_mul(*num, l), fp);
2374  *num = n;
2375  fn = SIZET2NUM(count);
2376  }
2377  ok = 1;
2378  }
2379 
2380  if (ok && *s + 1 < end && islettere(**s)) {
2381  (*s)++;
2382  expsign = read_sign(s, end);
2383  exp = rb_int_parse_cstr(*s, end-*s, &e, NULL,
2384  10, RB_INT_PARSE_UNDERSCORE);
2385  if (NIL_P(exp))
2386  return 1;
2387  *s = e;
2388  if (exp != ZERO) {
2389  if (expsign == '-') {
2390  if (fn != ZERO) exp = rb_int_plus(exp, fn);
2391  }
2392  else {
2393  if (fn != ZERO) exp = rb_int_minus(exp, fn);
2394  exp = negate_num(exp);
2395  }
2396  *nexp = exp;
2397  }
2398  }
2399 
2400  return ok;
2401 }
2402 
2403 inline static const char *
2404 skip_ws(const char *s, const char *e)
2405 {
2406  while (s < e && isspace((unsigned char)*s))
2407  ++s;
2408  return s;
2409 }
2410 
2411 static VALUE
2412 parse_rat(const char *s, const char *const e, int strict, int raise)
2413 {
2414  int sign;
2415  VALUE num, den, nexp, dexp;
2416 
2417  s = skip_ws(s, e);
2418  sign = read_sign(&s, e);
2419 
2420  if (!read_num(&s, e, &num, &nexp)) {
2421  if (strict) return Qnil;
2422  return nurat_s_alloc(rb_cRational);
2423  }
2424  den = ONE;
2425  if (s < e && *s == '/') {
2426  s++;
2427  if (!read_num(&s, e, &den, &dexp)) {
2428  if (strict) return Qnil;
2429  den = ONE;
2430  }
2431  else if (den == ZERO) {
2432  if (!raise) return Qnil;
2433  rb_num_zerodiv();
2434  }
2435  else if (strict && skip_ws(s, e) != e) {
2436  return Qnil;
2437  }
2438  else {
2439  nexp = rb_int_minus(nexp, dexp);
2440  nurat_reduce(&num, &den);
2441  }
2442  }
2443  else if (strict && skip_ws(s, e) != e) {
2444  return Qnil;
2445  }
2446 
2447  if (nexp != ZERO) {
2448  if (INT_NEGATIVE_P(nexp)) {
2449  VALUE mul;
2450  if (FIXNUM_P(nexp)) {
2451  mul = f_expt10(LONG2NUM(-FIX2LONG(nexp)));
2452  if (! RB_FLOAT_TYPE_P(mul)) {
2453  num = rb_int_mul(num, mul);
2454  goto reduce;
2455  }
2456  }
2457  return sign == '-' ? DBL2NUM(-HUGE_VAL) : DBL2NUM(HUGE_VAL);
2458  }
2459  else {
2460  VALUE div;
2461  if (FIXNUM_P(nexp)) {
2462  div = f_expt10(nexp);
2463  if (! RB_FLOAT_TYPE_P(div)) {
2464  den = rb_int_mul(den, div);
2465  goto reduce;
2466  }
2467  }
2468  return sign == '-' ? DBL2NUM(-0.0) : DBL2NUM(+0.0);
2469  }
2470  reduce:
2471  nurat_reduce(&num, &den);
2472  }
2473 
2474  if (sign == '-') {
2475  num = negate_num(num);
2476  }
2477 
2478  return rb_rational_raw(num, den);
2479 }
2480 
2481 static VALUE
2482 string_to_r_strict(VALUE self, int raise)
2483 {
2484  VALUE num;
2485 
2486  rb_must_asciicompat(self);
2487 
2488  num = parse_rat(RSTRING_PTR(self), RSTRING_END(self), 1, raise);
2489  if (NIL_P(num)) {
2490  if (!raise) return Qnil;
2491  rb_raise(rb_eArgError, "invalid value for convert(): %+"PRIsVALUE,
2492  self);
2493  }
2494 
2495  if (RB_FLOAT_TYPE_P(num) && !FLOAT_ZERO_P(num)) {
2496  if (!raise) return Qnil;
2497  rb_raise(rb_eFloatDomainError, "Infinity");
2498  }
2499  return num;
2500 }
2501 
2502 /*
2503  * call-seq:
2504  * str.to_r -> rational
2505  *
2506  * Returns the result of interpreting leading characters in +str+
2507  * as a rational. Leading whitespace and extraneous characters
2508  * past the end of a valid number are ignored.
2509  * Digit sequences can be separated by an underscore.
2510  * If there is not a valid number at the start of +str+,
2511  * zero is returned. This method never raises an exception.
2512  *
2513  * ' 2 '.to_r #=> (2/1)
2514  * '300/2'.to_r #=> (150/1)
2515  * '-9.2'.to_r #=> (-46/5)
2516  * '-9.2e2'.to_r #=> (-920/1)
2517  * '1_234_567'.to_r #=> (1234567/1)
2518  * '21 June 09'.to_r #=> (21/1)
2519  * '21/06/09'.to_r #=> (7/2)
2520  * 'BWV 1079'.to_r #=> (0/1)
2521  *
2522  * NOTE: "0.3".to_r isn't the same as 0.3.to_r. The former is
2523  * equivalent to "3/10".to_r, but the latter isn't so.
2524  *
2525  * "0.3".to_r == 3/10r #=> true
2526  * 0.3.to_r == 3/10r #=> false
2527  *
2528  * See also Kernel#Rational.
2529  */
2530 static VALUE
2531 string_to_r(VALUE self)
2532 {
2533  VALUE num;
2534 
2535  rb_must_asciicompat(self);
2536 
2537  num = parse_rat(RSTRING_PTR(self), RSTRING_END(self), 0, TRUE);
2538 
2539  if (RB_FLOAT_TYPE_P(num) && !FLOAT_ZERO_P(num))
2540  rb_raise(rb_eFloatDomainError, "Infinity");
2541  return num;
2542 }
2543 
2544 VALUE
2545 rb_cstr_to_rat(const char *s, int strict) /* for complex's internal */
2546 {
2547  VALUE num;
2548 
2549  num = parse_rat(s, s + strlen(s), strict, TRUE);
2550 
2551  if (RB_FLOAT_TYPE_P(num) && !FLOAT_ZERO_P(num))
2552  rb_raise(rb_eFloatDomainError, "Infinity");
2553  return num;
2554 }
2555 
2556 static VALUE
2557 to_rational(VALUE val)
2558 {
2559  return rb_convert_type_with_id(val, T_RATIONAL, "Rational", idTo_r);
2560 }
2561 
2562 static VALUE
2563 nurat_convert(VALUE klass, VALUE numv, VALUE denv, int raise)
2564 {
2565  VALUE a1 = numv, a2 = denv;
2566  int state;
2567 
2568  RUBY_ASSERT(!UNDEF_P(a1));
2569 
2570  if (NIL_P(a1) || NIL_P(a2)) {
2571  if (!raise) return Qnil;
2572  rb_raise(rb_eTypeError, "can't convert nil into Rational");
2573  }
2574 
2575  if (RB_TYPE_P(a1, T_COMPLEX)) {
2576  if (k_exact_zero_p(RCOMPLEX(a1)->imag))
2577  a1 = RCOMPLEX(a1)->real;
2578  }
2579 
2580  if (RB_TYPE_P(a2, T_COMPLEX)) {
2581  if (k_exact_zero_p(RCOMPLEX(a2)->imag))
2582  a2 = RCOMPLEX(a2)->real;
2583  }
2584 
2585  if (RB_INTEGER_TYPE_P(a1)) {
2586  // nothing to do
2587  }
2588  else if (RB_FLOAT_TYPE_P(a1)) {
2589  a1 = float_to_r(a1);
2590  }
2591  else if (RB_TYPE_P(a1, T_RATIONAL)) {
2592  // nothing to do
2593  }
2594  else if (RB_TYPE_P(a1, T_STRING)) {
2595  a1 = string_to_r_strict(a1, raise);
2596  if (!raise && NIL_P(a1)) return Qnil;
2597  }
2598  else if (!rb_respond_to(a1, idTo_r)) {
2599  VALUE tmp = rb_protect(rb_check_to_int, a1, NULL);
2601  if (!NIL_P(tmp)) {
2602  a1 = tmp;
2603  }
2604  }
2605 
2606  if (RB_INTEGER_TYPE_P(a2)) {
2607  // nothing to do
2608  }
2609  else if (RB_FLOAT_TYPE_P(a2)) {
2610  a2 = float_to_r(a2);
2611  }
2612  else if (RB_TYPE_P(a2, T_RATIONAL)) {
2613  // nothing to do
2614  }
2615  else if (RB_TYPE_P(a2, T_STRING)) {
2616  a2 = string_to_r_strict(a2, raise);
2617  if (!raise && NIL_P(a2)) return Qnil;
2618  }
2619  else if (!UNDEF_P(a2) && !rb_respond_to(a2, idTo_r)) {
2620  VALUE tmp = rb_protect(rb_check_to_int, a2, NULL);
2622  if (!NIL_P(tmp)) {
2623  a2 = tmp;
2624  }
2625  }
2626 
2627  if (RB_TYPE_P(a1, T_RATIONAL)) {
2628  if (UNDEF_P(a2) || (k_exact_one_p(a2)))
2629  return a1;
2630  }
2631 
2632  if (UNDEF_P(a2)) {
2633  if (!RB_INTEGER_TYPE_P(a1)) {
2634  if (!raise) {
2635  VALUE result = rb_protect(to_rational, a1, NULL);
2637  return result;
2638  }
2639  return to_rational(a1);
2640  }
2641  }
2642  else {
2643  if (!k_numeric_p(a1)) {
2644  if (!raise) {
2645  a1 = rb_protect(to_rational, a1, &state);
2646  if (state) {
2648  return Qnil;
2649  }
2650  }
2651  else {
2652  a1 = rb_check_convert_type_with_id(a1, T_RATIONAL, "Rational", idTo_r);
2653  }
2654  }
2655  if (!k_numeric_p(a2)) {
2656  if (!raise) {
2657  a2 = rb_protect(to_rational, a2, &state);
2658  if (state) {
2660  return Qnil;
2661  }
2662  }
2663  else {
2664  a2 = rb_check_convert_type_with_id(a2, T_RATIONAL, "Rational", idTo_r);
2665  }
2666  }
2667  if ((k_numeric_p(a1) && k_numeric_p(a2)) &&
2668  (!f_integer_p(a1) || !f_integer_p(a2))) {
2669  VALUE tmp = rb_protect(to_rational, a1, &state);
2670  if (!state) {
2671  a1 = tmp;
2672  }
2673  else {
2675  }
2676  return f_div(a1, a2);
2677  }
2678  }
2679 
2680  a1 = nurat_int_value(a1);
2681 
2682  if (UNDEF_P(a2)) {
2683  a2 = ONE;
2684  }
2685  else if (!k_integer_p(a2) && !raise) {
2686  return Qnil;
2687  }
2688  else {
2689  a2 = nurat_int_value(a2);
2690  }
2691 
2692 
2693  return nurat_s_canonicalize_internal(klass, a1, a2);
2694 }
2695 
2696 static VALUE
2697 nurat_s_convert(int argc, VALUE *argv, VALUE klass)
2698 {
2699  VALUE a1, a2;
2700 
2701  if (rb_scan_args(argc, argv, "11", &a1, &a2) == 1) {
2702  a2 = Qundef;
2703  }
2704 
2705  return nurat_convert(klass, a1, a2, TRUE);
2706 }
2707 
2708 /*
2709  * A rational number can be represented as a pair of integer numbers:
2710  * a/b (b>0), where a is the numerator and b is the denominator.
2711  * Integer a equals rational a/1 mathematically.
2712  *
2713  * You can create a \Rational object explicitly with:
2714  *
2715  * - A {rational literal}[rdoc-ref:syntax/literals.rdoc@Rational+Literals].
2716  *
2717  * You can convert certain objects to Rationals with:
2718  *
2719  * - \Method #Rational.
2720  *
2721  * Examples
2722  *
2723  * Rational(1) #=> (1/1)
2724  * Rational(2, 3) #=> (2/3)
2725  * Rational(4, -6) #=> (-2/3) # Reduced.
2726  * 3.to_r #=> (3/1)
2727  * 2/3r #=> (2/3)
2728  *
2729  * You can also create rational objects from floating-point numbers or
2730  * strings.
2731  *
2732  * Rational(0.3) #=> (5404319552844595/18014398509481984)
2733  * Rational('0.3') #=> (3/10)
2734  * Rational('2/3') #=> (2/3)
2735  *
2736  * 0.3.to_r #=> (5404319552844595/18014398509481984)
2737  * '0.3'.to_r #=> (3/10)
2738  * '2/3'.to_r #=> (2/3)
2739  * 0.3.rationalize #=> (3/10)
2740  *
2741  * A rational object is an exact number, which helps you to write
2742  * programs without any rounding errors.
2743  *
2744  * 10.times.inject(0) {|t| t + 0.1 } #=> 0.9999999999999999
2745  * 10.times.inject(0) {|t| t + Rational('0.1') } #=> (1/1)
2746  *
2747  * However, when an expression includes an inexact component (numerical value
2748  * or operation), it will produce an inexact result.
2749  *
2750  * Rational(10) / 3 #=> (10/3)
2751  * Rational(10) / 3.0 #=> 3.3333333333333335
2752  *
2753  * Rational(-8) ** Rational(1, 3)
2754  * #=> (1.0000000000000002+1.7320508075688772i)
2755  */
2756 void
2757 Init_Rational(void)
2758 {
2759  VALUE compat;
2760  id_abs = rb_intern_const("abs");
2761  id_integer_p = rb_intern_const("integer?");
2762  id_i_num = rb_intern_const("@numerator");
2763  id_i_den = rb_intern_const("@denominator");
2764 
2765  rb_cRational = rb_define_class("Rational", rb_cNumeric);
2766 
2767  rb_define_alloc_func(rb_cRational, nurat_s_alloc);
2768  rb_undef_method(CLASS_OF(rb_cRational), "allocate");
2769 
2771 
2772  rb_define_global_function("Rational", nurat_f_rational, -1);
2773 
2774  rb_define_method(rb_cRational, "numerator", nurat_numerator, 0);
2775  rb_define_method(rb_cRational, "denominator", nurat_denominator, 0);
2776 
2777  rb_define_method(rb_cRational, "-@", rb_rational_uminus, 0);
2778  rb_define_method(rb_cRational, "+", rb_rational_plus, 1);
2779  rb_define_method(rb_cRational, "-", rb_rational_minus, 1);
2780  rb_define_method(rb_cRational, "*", rb_rational_mul, 1);
2781  rb_define_method(rb_cRational, "/", rb_rational_div, 1);
2782  rb_define_method(rb_cRational, "quo", rb_rational_div, 1);
2783  rb_define_method(rb_cRational, "fdiv", nurat_fdiv, 1);
2784  rb_define_method(rb_cRational, "**", nurat_expt, 1);
2785 
2786  rb_define_method(rb_cRational, "<=>", rb_rational_cmp, 1);
2787  rb_define_method(rb_cRational, "==", nurat_eqeq_p, 1);
2788  rb_define_method(rb_cRational, "coerce", nurat_coerce, 1);
2789 
2790  rb_define_method(rb_cRational, "positive?", nurat_positive_p, 0);
2791  rb_define_method(rb_cRational, "negative?", nurat_negative_p, 0);
2792  rb_define_method(rb_cRational, "abs", rb_rational_abs, 0);
2793  rb_define_method(rb_cRational, "magnitude", rb_rational_abs, 0);
2794 
2795  rb_define_method(rb_cRational, "floor", nurat_floor_n, -1);
2796  rb_define_method(rb_cRational, "ceil", nurat_ceil_n, -1);
2797  rb_define_method(rb_cRational, "truncate", nurat_truncate_n, -1);
2798  rb_define_method(rb_cRational, "round", nurat_round_n, -1);
2799 
2800  rb_define_method(rb_cRational, "to_i", nurat_truncate, 0);
2801  rb_define_method(rb_cRational, "to_f", nurat_to_f, 0);
2802  rb_define_method(rb_cRational, "to_r", nurat_to_r, 0);
2803  rb_define_method(rb_cRational, "rationalize", nurat_rationalize, -1);
2804 
2805  rb_define_method(rb_cRational, "hash", nurat_hash, 0);
2806 
2807  rb_define_method(rb_cRational, "to_s", nurat_to_s, 0);
2808  rb_define_method(rb_cRational, "inspect", nurat_inspect, 0);
2809 
2810  rb_define_private_method(rb_cRational, "marshal_dump", nurat_marshal_dump, 0);
2811  /* :nodoc: */
2812  compat = rb_define_class_under(rb_cRational, "compatible", rb_cObject);
2813  rb_define_private_method(compat, "marshal_load", nurat_marshal_load, 1);
2814  rb_marshal_define_compat(rb_cRational, compat, nurat_dumper, nurat_loader);
2815 
2816  rb_define_method(rb_cInteger, "gcd", rb_gcd, 1);
2817  rb_define_method(rb_cInteger, "lcm", rb_lcm, 1);
2818  rb_define_method(rb_cInteger, "gcdlcm", rb_gcdlcm, 1);
2819 
2820  rb_define_method(rb_cNumeric, "numerator", numeric_numerator, 0);
2821  rb_define_method(rb_cNumeric, "denominator", numeric_denominator, 0);
2822  rb_define_method(rb_cNumeric, "quo", rb_numeric_quo, 1);
2823 
2824  rb_define_method(rb_cFloat, "numerator", rb_float_numerator, 0);
2825  rb_define_method(rb_cFloat, "denominator", rb_float_denominator, 0);
2826 
2827  rb_define_method(rb_cNilClass, "to_r", nilclass_to_r, 0);
2828  rb_define_method(rb_cNilClass, "rationalize", nilclass_rationalize, -1);
2829  rb_define_method(rb_cInteger, "to_r", integer_to_r, 0);
2830  rb_define_method(rb_cInteger, "rationalize", integer_rationalize, -1);
2831  rb_define_method(rb_cFloat, "to_r", float_to_r, 0);
2832  rb_define_method(rb_cFloat, "rationalize", float_rationalize, -1);
2833 
2834  rb_define_method(rb_cString, "to_r", string_to_r, 0);
2835 
2836  rb_define_private_method(CLASS_OF(rb_cRational), "convert", nurat_s_convert, -1);
2837 
2838  rb_provide("rational.so"); /* for backward compatibility */
2839 }
#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, const char *fmt,...)
Exception entry point.
Definition: error.c:3627
void rb_set_errinfo(VALUE err)
Sets the current exception ($!) to the given value.
Definition: eval.c:1941
VALUE rb_eTypeError
TypeError exception.
Definition: error.c:1403
VALUE rb_eFloatDomainError
FloatDomainError exception.
Definition: numeric.c:201
void rb_warn(const char *fmt,...)
Identical to rb_warning(), except it reports unless $VERBOSE is nil.
Definition: error.c:465
VALUE rb_eArgError
ArgumentError exception.
Definition: error.c:1404
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:3086
VALUE rb_check_to_int(VALUE val)
Identical to rb_check_to_integer(), except it uses #to_int for conversion.
Definition: object.c:3192
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:863
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:3186
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:1001
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:5961
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:714
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:1961
VALUE rb_rational_new(VALUE num, VALUE den)
Constructs a Rational, with reduction.
Definition: rational.c:1975
VALUE rb_Rational(VALUE num, VALUE den)
Converts various values into a Rational.
Definition: rational.c:1981
VALUE rb_rational_num(VALUE rat)
Queries the numerator of the passed Rational.
Definition: rational.c:1990
VALUE rb_flt_rationalize(VALUE flt)
Identical to rb_flt_rationalize_with_prec(), except it auto-detects appropriate precision depending o...
Definition: rational.c:2243
VALUE rb_flt_rationalize_with_prec(VALUE flt, VALUE prec)
Simplified approximation of a float.
Definition: rational.c:2227
#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:1996
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:2694
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:3904
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:1859
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:1350
int rb_respond_to(VALUE obj, ID mid)
Queries if the object responds to the method.
Definition: vm_method.c:2955
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:276
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:2036
#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