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