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