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