Ruby: rational.c Source File

Ruby 4.0.6p0 (2026-07-14 revision 03b6d3f8898a28604fe6cb00eae3226b821168f4)

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