[ruby/win32ole] Undefine allocator of WIN32OLE_VARIABLE to get rid of warning
[ruby-80x24.org.git] / rational.c
blob7817bdbcefa77028c92361b3c8f689069fea28ad
1 /*
2 rational.c: Coded by Tadayoshi Funaba 2008-2012
4 This implementation is based on Keiju Ishitsuka's Rational library
5 which is written in ruby.
6 */
8 #include "ruby/internal/config.h"
10 #include <ctype.h>
11 #include <float.h>
12 #include <math.h>
14 #ifdef HAVE_IEEEFP_H
15 #include <ieeefp.h>
16 #endif
18 #if defined(HAVE_LIBGMP) && defined(HAVE_GMP_H)
19 #define USE_GMP
20 #include <gmp.h>
21 #endif
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"
33 #define ZERO INT2FIX(0)
34 #define ONE INT2FIX(1)
35 #define TWO INT2FIX(2)
37 #define GMP_GCD_DIGITS 1
39 #define INT_ZERO_P(x) (FIXNUM_P(x) ? FIXNUM_ZERO_P(x) : rb_bigzero_p(x))
41 VALUE rb_cRational;
43 static ID id_abs, id_integer_p,
44 id_i_num, id_i_den;
46 #define id_idiv idDiv
47 #define id_to_i idTo_i
49 #define f_inspect rb_inspect
50 #define f_to_s rb_obj_as_string
52 static VALUE nurat_to_f(VALUE self);
53 static VALUE float_to_r(VALUE self);
55 inline static VALUE
56 f_add(VALUE x, VALUE y)
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);
67 inline static VALUE
68 f_div(VALUE x, VALUE y)
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);
77 inline static int
78 f_lt_p(VALUE x, VALUE y)
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);
86 return RTEST(rb_funcall(x, '<', 1, y));
89 #ifndef NDEBUG
90 /* f_mod is used only in f_gcd defined when NDEBUG is not defined */
91 inline static VALUE
92 f_mod(VALUE x, VALUE y)
94 if (RB_INTEGER_TYPE_P(x))
95 return rb_int_modulo(x, y);
96 return rb_funcall(x, '%', 1, y);
98 #endif
100 inline static VALUE
101 f_mul(VALUE x, VALUE y)
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);
114 inline static VALUE
115 f_sub(VALUE x, VALUE y)
117 if (FIXNUM_P(y) && FIXNUM_ZERO_P(y))
118 return x;
119 return rb_funcall(x, '-', 1, y);
122 inline static VALUE
123 f_abs(VALUE x)
125 if (RB_INTEGER_TYPE_P(x))
126 return rb_int_abs(x);
127 return rb_funcall(x, id_abs, 0);
131 inline static int
132 f_integer_p(VALUE x)
134 return RB_INTEGER_TYPE_P(x);
137 inline static VALUE
138 f_to_i(VALUE x)
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);
145 inline static int
146 f_eqeq_p(VALUE x, VALUE y)
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);
155 inline static VALUE
156 f_idiv(VALUE x, VALUE y)
158 if (RB_INTEGER_TYPE_P(x))
159 return rb_int_idiv(x, y);
160 return rb_funcall(x, id_idiv, 1, y);
163 #define f_expt10(x) rb_int_pow(INT2FIX(10), x)
165 inline static int
166 f_zero_p(VALUE x)
168 if (RB_INTEGER_TYPE_P(x)) {
169 return FIXNUM_ZERO_P(x);
171 else if (RB_TYPE_P(x, T_RATIONAL)) {
172 VALUE num = RRATIONAL(x)->num;
174 return FIXNUM_ZERO_P(num);
176 return (int)rb_equal(x, ZERO);
179 #define f_nonzero_p(x) (!f_zero_p(x))
181 inline static int
182 f_one_p(VALUE x)
184 if (RB_INTEGER_TYPE_P(x)) {
185 return x == LONG2FIX(1);
187 else if (RB_TYPE_P(x, T_RATIONAL)) {
188 VALUE num = RRATIONAL(x)->num;
189 VALUE den = RRATIONAL(x)->den;
191 return num == LONG2FIX(1) && den == LONG2FIX(1);
193 return (int)rb_equal(x, ONE);
196 inline static int
197 f_minus_one_p(VALUE x)
199 if (RB_INTEGER_TYPE_P(x)) {
200 return x == LONG2FIX(-1);
202 else if (RB_BIGNUM_TYPE_P(x)) {
203 return Qfalse;
205 else if (RB_TYPE_P(x, T_RATIONAL)) {
206 VALUE num = RRATIONAL(x)->num;
207 VALUE den = RRATIONAL(x)->den;
209 return num == LONG2FIX(-1) && den == LONG2FIX(1);
211 return (int)rb_equal(x, INT2FIX(-1));
214 inline static int
215 f_kind_of_p(VALUE x, VALUE c)
217 return (int)rb_obj_is_kind_of(x, c);
220 inline static int
221 k_numeric_p(VALUE x)
223 return f_kind_of_p(x, rb_cNumeric);
226 inline static int
227 k_integer_p(VALUE x)
229 return RB_INTEGER_TYPE_P(x);
232 inline static int
233 k_float_p(VALUE x)
235 return RB_FLOAT_TYPE_P(x);
238 inline static int
239 k_rational_p(VALUE x)
241 return RB_TYPE_P(x, T_RATIONAL);
244 #define k_exact_p(x) (!k_float_p(x))
245 #define k_inexact_p(x) k_float_p(x)
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))
250 #ifdef USE_GMP
251 VALUE
252 rb_gcd_gmp(VALUE x, VALUE y)
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;
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));
266 mpz_gcd(mz, mx, my);
268 mpz_clear(mx);
269 mpz_clear(my);
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);
275 mpz_clear(mz);
277 return rb_big_norm(z);
279 #endif
281 #ifndef NDEBUG
282 #define f_gcd f_gcd_orig
283 #endif
285 inline static long
286 i_gcd(long x, long y)
288 unsigned long u, v, t;
289 int shift;
291 if (x < 0)
292 x = -x;
293 if (y < 0)
294 y = -y;
296 if (x == 0)
297 return y;
298 if (y == 0)
299 return x;
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;
308 while ((u & 1) == 0)
309 u >>= 1;
311 do {
312 while ((v & 1) == 0)
313 v >>= 1;
315 if (u > v) {
316 t = v;
317 v = u;
318 u = t;
320 v = v - u;
321 } while (v != 0);
323 return (long)(u << shift);
326 inline static VALUE
327 f_gcd_normal(VALUE x, VALUE y)
329 VALUE z;
331 if (FIXNUM_P(x) && FIXNUM_P(y))
332 return LONG2NUM(i_gcd(FIX2LONG(x), FIX2LONG(y)));
334 if (INT_NEGATIVE_P(x))
335 x = rb_int_uminus(x);
336 if (INT_NEGATIVE_P(y))
337 y = rb_int_uminus(y);
339 if (INT_ZERO_P(x))
340 return y;
341 if (INT_ZERO_P(y))
342 return x;
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)));
351 z = x;
352 x = rb_int_modulo(y, x);
353 y = z;
355 /* NOTREACHED */
358 VALUE
359 rb_gcd_normal(VALUE x, VALUE y)
361 return f_gcd_normal(x, y);
364 inline static VALUE
365 f_gcd(VALUE x, VALUE y)
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);
374 #endif
375 return f_gcd_normal(x, y);
378 #ifndef NDEBUG
379 #undef f_gcd
381 inline static VALUE
382 f_gcd(VALUE x, VALUE y)
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)));
389 return r;
391 #endif
393 inline static VALUE
394 f_lcm(VALUE x, VALUE y)
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));
401 #define get_dat1(x) \
402 struct RRational *dat = RRATIONAL(x)
404 #define get_dat2(x,y) \
405 struct RRational *adat = RRATIONAL(x), *bdat = RRATIONAL(y)
407 inline static VALUE
408 nurat_s_new_internal(VALUE klass, VALUE num, VALUE den)
410 NEWOBJ_OF(obj, struct RRational, klass, T_RATIONAL | (RGENGC_WB_PROTECTED_RATIONAL ? FL_WB_PROTECTED : 0));
412 RATIONAL_SET_NUM((VALUE)obj, num);
413 RATIONAL_SET_DEN((VALUE)obj, den);
414 OBJ_FREEZE_RAW((VALUE)obj);
416 return (VALUE)obj;
419 static VALUE
420 nurat_s_alloc(VALUE klass)
422 return nurat_s_new_internal(klass, ZERO, ONE);
425 inline static VALUE
426 f_rational_new_bang1(VALUE klass, VALUE x)
428 return nurat_s_new_internal(klass, x, ONE);
431 inline static void
432 nurat_int_check(VALUE num)
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");
440 inline static VALUE
441 nurat_int_value(VALUE num)
443 nurat_int_check(num);
444 if (!k_integer_p(num))
445 num = f_to_i(num);
446 return num;
449 static void
450 nurat_canonicalize(VALUE *num, VALUE *den)
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);
458 else if (INT_ZERO_P(*den)) {
459 rb_num_zerodiv();
463 static void
464 nurat_reduce(VALUE *x, VALUE *y)
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);
473 inline static VALUE
474 nurat_s_canonicalize_internal(VALUE klass, VALUE num, VALUE den)
476 nurat_canonicalize(&num, &den);
477 nurat_reduce(&num, &den);
479 return nurat_s_new_internal(klass, num, den);
482 inline static VALUE
483 nurat_s_canonicalize_internal_no_reduce(VALUE klass, VALUE num, VALUE den)
485 nurat_canonicalize(&num, &den);
487 return nurat_s_new_internal(klass, num, den);
490 inline static VALUE
491 f_rational_new2(VALUE klass, VALUE x, VALUE y)
493 assert(!k_rational_p(x));
494 assert(!k_rational_p(y));
495 return nurat_s_canonicalize_internal(klass, x, y);
498 inline static VALUE
499 f_rational_new_no_reduce2(VALUE klass, VALUE x, VALUE y)
501 assert(!k_rational_p(x));
502 assert(!k_rational_p(y));
503 return nurat_s_canonicalize_internal_no_reduce(klass, x, y);
506 static VALUE nurat_convert(VALUE klass, VALUE numv, VALUE denv, int raise);
507 static VALUE nurat_s_convert(int argc, VALUE *argv, VALUE klass);
510 * call-seq:
511 * Rational(x, y, exception: true) -> rational or nil
512 * Rational(arg, exception: true) -> rational or nil
514 * Returns +x/y+ or +arg+ as a Rational.
516 * Rational(2, 3) #=> (2/3)
517 * Rational(5) #=> (5/1)
518 * Rational(0.5) #=> (1/2)
519 * Rational(0.3) #=> (5404319552844595/18014398509481984)
521 * Rational("2/3") #=> (2/3)
522 * Rational("0.3") #=> (3/10)
524 * Rational("10 cents") #=> ArgumentError
525 * Rational(nil) #=> TypeError
526 * Rational(1, nil) #=> TypeError
528 * Rational("10 cents", exception: false) #=> nil
530 * Syntax of the string form:
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* ? ;
544 * See also String#to_r.
546 static VALUE
547 nurat_f_rational(int argc, VALUE *argv, VALUE klass)
549 VALUE a1, a2, opts = Qnil;
550 int raise = TRUE;
552 if (rb_scan_args(argc, argv, "11:", &a1, &a2, &opts) == 1) {
553 a2 = Qundef;
555 if (!NIL_P(opts)) {
556 raise = rb_opts_exception_p(opts, raise);
558 return nurat_convert(rb_cRational, a1, a2, raise);
562 * call-seq:
563 * rat.numerator -> integer
565 * Returns the numerator.
567 * Rational(7).numerator #=> 7
568 * Rational(7, 1).numerator #=> 7
569 * Rational(9, -4).numerator #=> -9
570 * Rational(-2, -10).numerator #=> 1
572 static VALUE
573 nurat_numerator(VALUE self)
575 get_dat1(self);
576 return dat->num;
580 * call-seq:
581 * rat.denominator -> integer
583 * Returns the denominator (always positive).
585 * Rational(7).denominator #=> 1
586 * Rational(7, 1).denominator #=> 1
587 * Rational(9, -4).denominator #=> 4
588 * Rational(-2, -10).denominator #=> 5
590 static VALUE
591 nurat_denominator(VALUE self)
593 get_dat1(self);
594 return dat->den;
598 * call-seq:
599 * -rat -> rational
601 * Negates +rat+.
603 VALUE
604 rb_rational_uminus(VALUE self)
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);
612 #ifndef NDEBUG
613 #define f_imul f_imul_orig
614 #endif
616 inline static VALUE
617 f_imul(long a, long b)
619 VALUE r;
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);
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;
635 #ifndef NDEBUG
636 #undef f_imul
638 inline static VALUE
639 f_imul(long x, long y)
641 VALUE r = f_imul_orig(x, y);
642 assert(f_eqeq_p(r, f_mul(LONG2NUM(x), LONG2NUM(y))));
643 return r;
645 #endif
647 inline static VALUE
648 f_addsub(VALUE self, VALUE anum, VALUE aden, VALUE bnum, VALUE bden, int k)
650 VALUE num, den;
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);
660 VALUE g = LONG2NUM(ig);
661 VALUE a = f_imul(an, bd / ig);
662 VALUE b = f_imul(bn, ad / ig);
663 VALUE c;
665 if (k == '+')
666 c = rb_int_plus(a, b);
667 else
668 c = rb_int_minus(a, b);
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);
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;
683 if (k == '+')
684 c = rb_int_plus(a, b);
685 else
686 c = rb_int_minus(a, b);
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);
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);
700 return f_rational_new_no_reduce2(CLASS_OF(self), num, den);
703 static double nurat_to_double(VALUE self);
705 * call-seq:
706 * rat + numeric -> numeric
708 * Performs addition.
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
716 VALUE
717 rb_rational_plus(VALUE self, VALUE other)
719 if (RB_INTEGER_TYPE_P(other)) {
721 get_dat1(self);
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);
728 else if (RB_FLOAT_TYPE_P(other)) {
729 return DBL2NUM(nurat_to_double(self) + RFLOAT_VALUE(other));
731 else if (RB_TYPE_P(other, T_RATIONAL)) {
733 get_dat2(self, other);
735 return f_addsub(self,
736 adat->num, adat->den,
737 bdat->num, bdat->den, '+');
740 else {
741 return rb_num_coerce_bin(self, other, '+');
746 * call-seq:
747 * rat - numeric -> numeric
749 * Performs subtraction.
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
757 VALUE
758 rb_rational_minus(VALUE self, VALUE other)
760 if (RB_INTEGER_TYPE_P(other)) {
762 get_dat1(self);
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);
769 else if (RB_FLOAT_TYPE_P(other)) {
770 return DBL2NUM(nurat_to_double(self) - RFLOAT_VALUE(other));
772 else if (RB_TYPE_P(other, T_RATIONAL)) {
774 get_dat2(self, other);
776 return f_addsub(self,
777 adat->num, adat->den,
778 bdat->num, bdat->den, '-');
781 else {
782 return rb_num_coerce_bin(self, other, '-');
786 inline static VALUE
787 f_muldiv(VALUE self, VALUE anum, VALUE aden, VALUE bnum, VALUE bden, int k)
789 VALUE num, den;
791 assert(RB_TYPE_P(self, T_RATIONAL));
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);
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));
807 if (k == '/') {
808 VALUE t;
810 if (INT_NEGATIVE_P(bnum)) {
811 anum = rb_int_uminus(anum);
812 bnum = rb_int_uminus(bnum);
814 t = bnum;
815 bnum = bden;
816 bden = t;
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);
828 num = f_imul(an / g1, bn / g2);
829 den = f_imul(ad / g2, bd / g1);
831 else {
832 VALUE g1 = f_gcd(anum, bden);
833 VALUE g2 = f_gcd(aden, bnum);
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));
838 return f_rational_new_no_reduce2(CLASS_OF(self), num, den);
842 * call-seq:
843 * rat * numeric -> numeric
845 * Performs multiplication.
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
853 VALUE
854 rb_rational_mul(VALUE self, VALUE other)
856 if (RB_INTEGER_TYPE_P(other)) {
858 get_dat1(self);
860 return f_muldiv(self,
861 dat->num, dat->den,
862 other, ONE, '*');
865 else if (RB_FLOAT_TYPE_P(other)) {
866 return DBL2NUM(nurat_to_double(self) * RFLOAT_VALUE(other));
868 else if (RB_TYPE_P(other, T_RATIONAL)) {
870 get_dat2(self, other);
872 return f_muldiv(self,
873 adat->num, adat->den,
874 bdat->num, bdat->den, '*');
877 else {
878 return rb_num_coerce_bin(self, other, '*');
883 * call-seq:
884 * rat / numeric -> numeric
885 * rat.quo(numeric) -> numeric
887 * Performs division.
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
895 VALUE
896 rb_rational_div(VALUE self, VALUE other)
898 if (RB_INTEGER_TYPE_P(other)) {
899 if (f_zero_p(other))
900 rb_num_zerodiv();
902 get_dat1(self);
904 return f_muldiv(self,
905 dat->num, dat->den,
906 other, ONE, '/');
909 else if (RB_FLOAT_TYPE_P(other)) {
910 VALUE v = nurat_to_f(self);
911 return rb_flo_div_flo(v, other);
913 else if (RB_TYPE_P(other, T_RATIONAL)) {
914 if (f_zero_p(other))
915 rb_num_zerodiv();
917 get_dat2(self, other);
919 if (f_one_p(self))
920 return f_rational_new_no_reduce2(CLASS_OF(self),
921 bdat->den, bdat->num);
923 return f_muldiv(self,
924 adat->num, adat->den,
925 bdat->num, bdat->den, '/');
928 else {
929 return rb_num_coerce_bin(self, other, '/');
934 * call-seq:
935 * rat.fdiv(numeric) -> float
937 * Performs division and returns the value as a Float.
939 * Rational(2, 3).fdiv(1) #=> 0.6666666666666666
940 * Rational(2, 3).fdiv(0.5) #=> 1.3333333333333333
941 * Rational(2).fdiv(3) #=> 0.6666666666666666
943 static VALUE
944 nurat_fdiv(VALUE self, VALUE other)
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);
960 * call-seq:
961 * rat ** numeric -> numeric
963 * Performs exponentiation.
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
972 VALUE
973 rb_rational_pow(VALUE self, VALUE other)
975 if (k_numeric_p(other) && k_exact_zero_p(other))
976 return f_rational_new_bang1(CLASS_OF(self), ONE);
978 if (k_rational_p(other)) {
979 get_dat1(other);
981 if (f_one_p(dat->den))
982 other = dat->num; /* c14n */
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);
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));
995 else if (INT_ZERO_P(dat->num)) {
996 if (rb_num_negative_p(other)) {
997 rb_num_zerodiv();
999 else {
1000 return f_rational_new_bang1(CLASS_OF(self), ZERO);
1006 /* General case */
1007 if (FIXNUM_P(other)) {
1009 VALUE num, den;
1011 get_dat1(self);
1013 if (INT_POSITIVE_P(other)) {
1014 num = rb_int_pow(dat->num, other);
1015 den = rb_int_pow(dat->den, other);
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));
1021 else {
1022 num = ONE;
1023 den = ONE;
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;
1030 if (RB_FLOAT_TYPE_P(den)) { /* infinity due to overflow */
1031 num = ZERO;
1032 den = ONE;
1034 return f_rational_new2(CLASS_OF(self), num, den);
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);
1041 else if (RB_FLOAT_TYPE_P(other) || RB_TYPE_P(other, T_RATIONAL)) {
1042 return rb_float_pow(nurat_to_f(self), other);
1044 else {
1045 return rb_num_coerce_bin(self, other, idPow);
1048 #define nurat_expt rb_rational_pow
1051 * call-seq:
1052 * rational <=> numeric -> -1, 0, +1, or nil
1054 * Returns -1, 0, or +1 depending on whether +rational+ is
1055 * less than, equal to, or greater than +numeric+.
1057 * +nil+ is returned if the two values are incomparable.
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
1065 * Rational(1, 3) <=> "0.3" #=> nil
1067 VALUE
1068 rb_rational_cmp(VALUE self, VALUE other)
1070 switch (TYPE(other)) {
1071 case T_FIXNUM:
1072 case T_BIGNUM:
1074 get_dat1(self);
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 */
1082 case T_RATIONAL:
1084 VALUE num1, num2;
1086 get_dat2(self, other);
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));
1093 else {
1094 num1 = rb_int_mul(adat->num, bdat->den);
1095 num2 = rb_int_mul(bdat->num, adat->den);
1097 return rb_int_cmp(rb_int_minus(num1, num2), ZERO);
1100 case T_FLOAT:
1101 return rb_dbl_cmp(nurat_to_double(self), RFLOAT_VALUE(other));
1103 default:
1104 return rb_num_coerce_cmp(self, other, idCmp);
1109 * call-seq:
1110 * rat == object -> true or false
1112 * Returns +true+ if +rat+ equals +object+ numerically.
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
1120 static VALUE
1121 nurat_eqeq_p(VALUE self, VALUE other)
1123 if (RB_INTEGER_TYPE_P(other)) {
1124 get_dat1(self);
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;
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);
1136 else {
1137 const double d = nurat_to_double(self);
1138 return RBOOL(FIXNUM_ZERO_P(rb_dbl_cmp(d, NUM2DBL(other))));
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))));
1145 else if (RB_TYPE_P(other, T_RATIONAL)) {
1147 get_dat2(self, other);
1149 if (INT_ZERO_P(adat->num) && INT_ZERO_P(bdat->num))
1150 return Qtrue;
1152 return RBOOL(rb_int_equal(adat->num, bdat->num) &&
1153 rb_int_equal(adat->den, bdat->den));
1156 else {
1157 return rb_equal(other, self);
1161 /* :nodoc: */
1162 static VALUE
1163 nurat_coerce(VALUE self, VALUE other)
1165 if (RB_INTEGER_TYPE_P(other)) {
1166 return rb_assoc_new(f_rational_new_bang1(CLASS_OF(self), other), self);
1168 else if (RB_FLOAT_TYPE_P(other)) {
1169 return rb_assoc_new(other, nurat_to_f(self));
1171 else if (RB_TYPE_P(other, T_RATIONAL)) {
1172 return rb_assoc_new(other, self);
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));
1182 else {
1183 other = f_rational_new_bang1(CLASS_OF(self), other);
1185 return rb_assoc_new(other, self);
1188 rb_raise(rb_eTypeError, "%s can't be coerced into %s",
1189 rb_obj_classname(other), rb_obj_classname(self));
1190 return Qnil;
1194 * call-seq:
1195 * rat.positive? -> true or false
1197 * Returns +true+ if +rat+ is greater than 0.
1199 static VALUE
1200 nurat_positive_p(VALUE self)
1202 get_dat1(self);
1203 return RBOOL(INT_POSITIVE_P(dat->num));
1207 * call-seq:
1208 * rat.negative? -> true or false
1210 * Returns +true+ if +rat+ is less than 0.
1212 static VALUE
1213 nurat_negative_p(VALUE self)
1215 get_dat1(self);
1216 return RBOOL(INT_NEGATIVE_P(dat->num));
1220 * call-seq:
1221 * rat.abs -> rational
1222 * rat.magnitude -> rational
1224 * Returns the absolute value of +rat+.
1226 * (1/2r).abs #=> (1/2)
1227 * (-1/2r).abs #=> (1/2)
1229 * Rational#magnitude is an alias for Rational#abs.
1232 VALUE
1233 rb_rational_abs(VALUE self)
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);
1240 return self;
1243 static VALUE
1244 nurat_floor(VALUE self)
1246 get_dat1(self);
1247 return rb_int_idiv(dat->num, dat->den);
1250 static VALUE
1251 nurat_ceil(VALUE self)
1253 get_dat1(self);
1254 return rb_int_uminus(rb_int_idiv(rb_int_uminus(dat->num), dat->den));
1258 * call-seq:
1259 * rat.to_i -> integer
1261 * Returns the truncated value as an integer.
1263 * Equivalent to Rational#truncate.
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
1271 static VALUE
1272 nurat_truncate(VALUE self)
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);
1280 static VALUE
1281 nurat_round_half_up(VALUE self)
1283 VALUE num, den, neg;
1285 get_dat1(self);
1287 num = dat->num;
1288 den = dat->den;
1289 neg = INT_NEGATIVE_P(num);
1291 if (neg)
1292 num = rb_int_uminus(num);
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);
1298 if (neg)
1299 num = rb_int_uminus(num);
1301 return num;
1304 static VALUE
1305 nurat_round_half_down(VALUE self)
1307 VALUE num, den, neg;
1309 get_dat1(self);
1311 num = dat->num;
1312 den = dat->den;
1313 neg = INT_NEGATIVE_P(num);
1315 if (neg)
1316 num = rb_int_uminus(num);
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);
1323 if (neg)
1324 num = rb_int_uminus(num);
1326 return num;
1329 static VALUE
1330 nurat_round_half_even(VALUE self)
1332 VALUE num, den, neg, qr;
1334 get_dat1(self);
1336 num = dat->num;
1337 den = dat->den;
1338 neg = INT_NEGATIVE_P(num);
1340 if (neg)
1341 num = rb_int_uminus(num);
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)));
1350 if (neg)
1351 num = rb_int_uminus(num);
1353 return num;
1356 static VALUE
1357 f_round_common(int argc, VALUE *argv, VALUE self, VALUE (*func)(VALUE))
1359 VALUE n, b, s;
1361 if (rb_check_arity(argc, 0, 1) == 0)
1362 return (*func)(self);
1364 n = argv[0];
1366 if (!k_integer_p(n))
1367 rb_raise(rb_eTypeError, "not an integer");
1369 b = f_expt10(n);
1370 s = rb_rational_mul(self, b);
1372 if (k_float_p(s)) {
1373 if (INT_NEGATIVE_P(n))
1374 return ZERO;
1375 return self;
1378 if (!k_rational_p(s)) {
1379 s = f_rational_new_bang1(CLASS_OF(self), s);
1382 s = (*func)(s);
1384 s = rb_rational_div(f_rational_new_bang1(CLASS_OF(self), s), b);
1386 if (RB_TYPE_P(s, T_RATIONAL) && FIX2INT(rb_int_cmp(n, ONE)) < 0)
1387 s = nurat_truncate(s);
1389 return s;
1392 VALUE
1393 rb_rational_floor(VALUE self, int ndigits)
1395 if (ndigits == 0) {
1396 return nurat_floor(self);
1398 else {
1399 VALUE n = INT2NUM(ndigits);
1400 return f_round_common(1, &n, self, nurat_floor);
1405 * call-seq:
1406 * rat.floor([ndigits]) -> integer or rational
1408 * Returns the largest number less than or equal to +rat+ with
1409 * a precision of +ndigits+ decimal digits (default: 0).
1411 * When the precision is negative, the returned value is an integer
1412 * with at least <code>ndigits.abs</code> trailing zeros.
1414 * Returns a rational when +ndigits+ is positive,
1415 * otherwise returns an integer.
1417 * Rational(3).floor #=> 3
1418 * Rational(2, 3).floor #=> 0
1419 * Rational(-3, 2).floor #=> -2
1421 * # decimal - 1 2 3 . 4 5 6
1422 * # ^ ^ ^ ^ ^ ^
1423 * # precision -3 -2 -1 0 +1 +2
1425 * Rational('-123.456').floor(+1).to_f #=> -123.5
1426 * Rational('-123.456').floor(-1) #=> -130
1428 static VALUE
1429 nurat_floor_n(int argc, VALUE *argv, VALUE self)
1431 return f_round_common(argc, argv, self, nurat_floor);
1435 * call-seq:
1436 * rat.ceil([ndigits]) -> integer or rational
1438 * Returns the smallest number greater than or equal to +rat+ with
1439 * a precision of +ndigits+ decimal digits (default: 0).
1441 * When the precision is negative, the returned value is an integer
1442 * with at least <code>ndigits.abs</code> trailing zeros.
1444 * Returns a rational when +ndigits+ is positive,
1445 * otherwise returns an integer.
1447 * Rational(3).ceil #=> 3
1448 * Rational(2, 3).ceil #=> 1
1449 * Rational(-3, 2).ceil #=> -1
1451 * # decimal - 1 2 3 . 4 5 6
1452 * # ^ ^ ^ ^ ^ ^
1453 * # precision -3 -2 -1 0 +1 +2
1455 * Rational('-123.456').ceil(+1).to_f #=> -123.4
1456 * Rational('-123.456').ceil(-1) #=> -120
1458 static VALUE
1459 nurat_ceil_n(int argc, VALUE *argv, VALUE self)
1461 return f_round_common(argc, argv, self, nurat_ceil);
1465 * call-seq:
1466 * rat.truncate([ndigits]) -> integer or rational
1468 * Returns +rat+ truncated (toward zero) to
1469 * a precision of +ndigits+ decimal digits (default: 0).
1471 * When the precision is negative, the returned value is an integer
1472 * with at least <code>ndigits.abs</code> trailing zeros.
1474 * Returns a rational when +ndigits+ is positive,
1475 * otherwise returns an integer.
1477 * Rational(3).truncate #=> 3
1478 * Rational(2, 3).truncate #=> 0
1479 * Rational(-3, 2).truncate #=> -1
1481 * # decimal - 1 2 3 . 4 5 6
1482 * # ^ ^ ^ ^ ^ ^
1483 * # precision -3 -2 -1 0 +1 +2
1485 * Rational('-123.456').truncate(+1).to_f #=> -123.4
1486 * Rational('-123.456').truncate(-1) #=> -120
1488 static VALUE
1489 nurat_truncate_n(int argc, VALUE *argv, VALUE self)
1491 return f_round_common(argc, argv, self, nurat_truncate);
1495 * call-seq:
1496 * rat.round([ndigits] [, half: mode]) -> integer or rational
1498 * Returns +rat+ rounded to the nearest value with
1499 * a precision of +ndigits+ decimal digits (default: 0).
1501 * When the precision is negative, the returned value is an integer
1502 * with at least <code>ndigits.abs</code> trailing zeros.
1504 * Returns a rational when +ndigits+ is positive,
1505 * otherwise returns an integer.
1507 * Rational(3).round #=> 3
1508 * Rational(2, 3).round #=> 1
1509 * Rational(-3, 2).round #=> -2
1511 * # decimal - 1 2 3 . 4 5 6
1512 * # ^ ^ ^ ^ ^ ^
1513 * # precision -3 -2 -1 0 +1 +2
1515 * Rational('-123.456').round(+1).to_f #=> -123.5
1516 * Rational('-123.456').round(-1) #=> -120
1518 * The optional +half+ keyword argument is available
1519 * similar to Float#round.
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)
1531 static VALUE
1532 nurat_round_n(int argc, VALUE *argv, VALUE self)
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);
1542 VALUE
1543 rb_flo_round_by_rational(int argc, VALUE *argv, VALUE num)
1545 return nurat_to_f(nurat_round_n(argc, argv, float_to_r(num)));
1548 static double
1549 nurat_to_double(VALUE self)
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);
1555 return rb_int_fdiv_double(dat->num, dat->den);
1559 * call-seq:
1560 * rat.to_f -> float
1562 * Returns the value as a Float.
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
1569 static VALUE
1570 nurat_to_f(VALUE self)
1572 return DBL2NUM(nurat_to_double(self));
1576 * call-seq:
1577 * rat.to_r -> self
1579 * Returns self.
1581 * Rational(2).to_r #=> (2/1)
1582 * Rational(-8, 6).to_r #=> (-4/3)
1584 static VALUE
1585 nurat_to_r(VALUE self)
1587 return self;
1590 #define id_ceil rb_intern("ceil")
1591 static VALUE
1592 f_ceil(VALUE x)
1594 if (RB_INTEGER_TYPE_P(x))
1595 return x;
1596 if (RB_FLOAT_TYPE_P(x))
1597 return rb_float_ceil(x, 0);
1599 return rb_funcall(x, id_ceil, 0);
1602 #define id_quo idQuo
1603 static VALUE
1604 f_quo(VALUE x, VALUE y)
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));
1611 return rb_funcallv(x, id_quo, 1, &y);
1614 #define f_reciprocal(x) f_quo(ONE, (x))
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."
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)
1650 You can see that we are actually computing a continued fraction expansion.
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.
1675 static void
1676 nurat_rationalize_internal(VALUE a, VALUE b, VALUE *p, VALUE *q)
1678 VALUE c, k, t, p0, p1, p2, q0, q1, q2;
1680 p0 = ZERO;
1681 p1 = ONE;
1682 q0 = ONE;
1683 q1 = ZERO;
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;
1700 *p = f_add(f_mul(c, p1), p0);
1701 *q = f_add(f_mul(c, q1), q0);
1705 * call-seq:
1706 * rat.rationalize -> self
1707 * rat.rationalize(eps) -> rational
1709 * Returns a simpler approximation of the value if the optional
1710 * argument +eps+ is given (rat-|eps| <= result <= rat+|eps|),
1711 * self otherwise.
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)
1718 static VALUE
1719 nurat_rationalize(int argc, VALUE *argv, VALUE self)
1721 VALUE e, a, b, p, q;
1722 VALUE rat = self;
1723 get_dat1(self);
1725 if (rb_check_arity(argc, 0, 1) == 0)
1726 return self;
1728 e = f_abs(argv[0]);
1730 if (INT_NEGATIVE_P(dat->num)) {
1731 rat = f_rational_new2(RBASIC_CLASS(self), rb_int_uminus(dat->num), dat->den);
1734 a = FIXNUM_ZERO_P(e) ? rat : rb_rational_minus(rat, e);
1735 b = FIXNUM_ZERO_P(e) ? rat : rb_rational_plus(rat, e);
1737 if (f_eqeq_p(a, b))
1738 return self;
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;
1746 return f_rational_new2(CLASS_OF(self), p, q);
1749 /* :nodoc: */
1750 st_index_t
1751 rb_rational_hash(VALUE self)
1753 st_index_t v, h[2];
1754 VALUE n;
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;
1765 static VALUE
1766 nurat_hash(VALUE self)
1768 return ST2FIX(rb_rational_hash(self));
1772 static VALUE
1773 f_format(VALUE self, VALUE (*func)(VALUE))
1775 VALUE s;
1776 get_dat1(self);
1778 s = (*func)(dat->num);
1779 rb_str_cat2(s, "/");
1780 rb_str_concat(s, (*func)(dat->den));
1782 return s;
1786 * call-seq:
1787 * rat.to_s -> string
1789 * Returns the value as a string.
1791 * Rational(2).to_s #=> "2/1"
1792 * Rational(-8, 6).to_s #=> "-4/3"
1793 * Rational('1/2').to_s #=> "1/2"
1795 static VALUE
1796 nurat_to_s(VALUE self)
1798 return f_format(self, f_to_s);
1802 * call-seq:
1803 * rat.inspect -> string
1805 * Returns the value as a string for inspection.
1807 * Rational(2).inspect #=> "(2/1)"
1808 * Rational(-8, 6).inspect #=> "(-4/3)"
1809 * Rational('1/2').inspect #=> "(1/2)"
1811 static VALUE
1812 nurat_inspect(VALUE self)
1814 VALUE s;
1816 s = rb_usascii_str_new2("(");
1817 rb_str_concat(s, f_format(self, f_inspect));
1818 rb_str_cat2(s, ")");
1820 return s;
1823 /* :nodoc: */
1824 static VALUE
1825 nurat_dumper(VALUE self)
1827 return self;
1830 /* :nodoc: */
1831 static VALUE
1832 nurat_loader(VALUE self, VALUE a)
1834 VALUE num, den;
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);
1846 return self;
1849 /* :nodoc: */
1850 static VALUE
1851 nurat_marshal_dump(VALUE self)
1853 VALUE a;
1854 get_dat1(self);
1856 a = rb_assoc_new(dat->num, dat->den);
1857 rb_copy_generic_ivar(a, self);
1858 return a;
1861 /* :nodoc: */
1862 static VALUE
1863 nurat_marshal_load(VALUE self, VALUE a)
1865 VALUE num, den;
1867 rb_check_frozen(self);
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));
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);
1881 return self;
1884 VALUE
1885 rb_rational_reciprocal(VALUE x)
1887 get_dat1(x);
1888 return nurat_convert(CLASS_OF(x), dat->den, dat->num, FALSE);
1892 * call-seq:
1893 * int.gcd(other_int) -> integer
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.
1898 * 36.gcd(60) #=> 12
1899 * 2.gcd(2) #=> 2
1900 * 3.gcd(-7) #=> 1
1901 * ((1<<31)-1).gcd((1<<61)-1) #=> 1
1903 VALUE
1904 rb_gcd(VALUE self, VALUE other)
1906 other = nurat_int_value(other);
1907 return f_gcd(self, other);
1911 * call-seq:
1912 * int.lcm(other_int) -> integer
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.
1917 * 36.lcm(60) #=> 180
1918 * 2.lcm(2) #=> 2
1919 * 3.lcm(-7) #=> 21
1920 * ((1<<31)-1).lcm((1<<61)-1) #=> 4951760154835678088235319297
1922 VALUE
1923 rb_lcm(VALUE self, VALUE other)
1925 other = nurat_int_value(other);
1926 return f_lcm(self, other);
1930 * call-seq:
1931 * int.gcdlcm(other_int) -> array
1933 * Returns an array with the greatest common divisor and
1934 * the least common multiple of the two integers, [gcd, lcm].
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]
1941 VALUE
1942 rb_gcdlcm(VALUE self, VALUE other)
1944 other = nurat_int_value(other);
1945 return rb_assoc_new(f_gcd(self, other), f_lcm(self, other));
1948 VALUE
1949 rb_rational_raw(VALUE x, VALUE y)
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);
1959 return nurat_s_new_internal(rb_cRational, x, y);
1962 VALUE
1963 rb_rational_new(VALUE x, VALUE y)
1965 return nurat_s_canonicalize_internal(rb_cRational, x, y);
1968 VALUE
1969 rb_Rational(VALUE x, VALUE y)
1971 VALUE a[2];
1972 a[0] = x;
1973 a[1] = y;
1974 return nurat_s_convert(2, a, rb_cRational);
1977 VALUE
1978 rb_rational_num(VALUE rat)
1980 return nurat_numerator(rat);
1983 VALUE
1984 rb_rational_den(VALUE rat)
1986 return nurat_denominator(rat);
1989 #define id_numerator rb_intern("numerator")
1990 #define f_numerator(x) rb_funcall((x), id_numerator, 0)
1992 #define id_denominator rb_intern("denominator")
1993 #define f_denominator(x) rb_funcall((x), id_denominator, 0)
1995 #define id_to_r idTo_r
1996 #define f_to_r(x) rb_funcall((x), id_to_r, 0)
1999 * call-seq:
2000 * num.numerator -> integer
2002 * Returns the numerator.
2004 static VALUE
2005 numeric_numerator(VALUE self)
2007 return f_numerator(f_to_r(self));
2011 * call-seq:
2012 * num.denominator -> integer
2014 * Returns the denominator (always positive).
2016 static VALUE
2017 numeric_denominator(VALUE self)
2019 return f_denominator(f_to_r(self));
2024 * call-seq:
2025 * num.quo(int_or_rat) -> rat
2026 * num.quo(flo) -> flo
2028 * Returns the most exact division (rational for integers, float for floats).
2031 VALUE
2032 rb_numeric_quo(VALUE x, VALUE y)
2034 if (RB_TYPE_P(x, T_COMPLEX)) {
2035 return rb_complex_div(x, y);
2038 if (RB_FLOAT_TYPE_P(y)) {
2039 return rb_funcallv(x, idFdiv, 1, &y);
2042 x = rb_convert_type(x, T_RATIONAL, "Rational", "to_r");
2043 return rb_rational_div(x, y);
2046 VALUE
2047 rb_rational_canonicalize(VALUE x)
2049 if (RB_TYPE_P(x, T_RATIONAL)) {
2050 get_dat1(x);
2051 if (f_one_p(dat->den)) return dat->num;
2053 return x;
2057 * call-seq:
2058 * int.numerator -> self
2060 * Returns self.
2062 static VALUE
2063 integer_numerator(VALUE self)
2065 return self;
2069 * call-seq:
2070 * int.denominator -> 1
2072 * Returns 1.
2074 static VALUE
2075 integer_denominator(VALUE self)
2077 return INT2FIX(1);
2081 * call-seq:
2082 * flo.numerator -> integer
2084 * Returns the numerator. The result is machine dependent.
2086 * n = 0.3.numerator #=> 5404319552844595
2087 * d = 0.3.denominator #=> 18014398509481984
2088 * n.fdiv(d) #=> 0.3
2090 * See also Float#denominator.
2092 VALUE
2093 rb_float_numerator(VALUE self)
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);
2104 * call-seq:
2105 * flo.denominator -> integer
2107 * Returns the denominator (always positive). The result is machine
2108 * dependent.
2110 * See also Float#numerator.
2112 VALUE
2113 rb_float_denominator(VALUE self)
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);
2124 * call-seq:
2125 * nil.to_r -> (0/1)
2127 * Returns zero as a rational.
2129 static VALUE
2130 nilclass_to_r(VALUE self)
2132 return rb_rational_new1(INT2FIX(0));
2136 * call-seq:
2137 * nil.rationalize([eps]) -> (0/1)
2139 * Returns zero as a rational. The optional argument +eps+ is always
2140 * ignored.
2142 static VALUE
2143 nilclass_rationalize(int argc, VALUE *argv, VALUE self)
2145 rb_check_arity(argc, 0, 1);
2146 return nilclass_to_r(self);
2150 * call-seq:
2151 * int.to_r -> rational
2153 * Returns the value as a rational.
2155 * 1.to_r #=> (1/1)
2156 * (1<<64).to_r #=> (18446744073709551616/1)
2158 static VALUE
2159 integer_to_r(VALUE self)
2161 return rb_rational_new1(self);
2165 * call-seq:
2166 * int.rationalize([eps]) -> rational
2168 * Returns the value as a rational. The optional argument +eps+ is
2169 * always ignored.
2171 static VALUE
2172 integer_rationalize(int argc, VALUE *argv, VALUE self)
2174 rb_check_arity(argc, 0, 1);
2175 return integer_to_r(self);
2178 static void
2179 float_decode_internal(VALUE self, VALUE *rf, int *n)
2181 double f;
2183 f = frexp(RFLOAT_VALUE(self), n);
2184 f = ldexp(f, DBL_MANT_DIG);
2185 *n -= DBL_MANT_DIG;
2186 *rf = rb_dbl2big(f);
2190 * call-seq:
2191 * flt.to_r -> rational
2193 * Returns the value as a rational.
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)
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.
2204 * 0.3.to_r == 3/10r #=> false
2205 * "0.3".to_r == 3/10r #=> true
2207 * See also Float#rationalize.
2209 static VALUE
2210 float_to_r(VALUE self)
2212 VALUE f;
2213 int n;
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
2231 VALUE
2232 rb_flt_rationalize_with_prec(VALUE flt, VALUE prec)
2234 VALUE e, a, b, p, q;
2236 e = f_abs(prec);
2237 a = f_sub(flt, e);
2238 b = f_add(flt, e);
2240 if (f_eqeq_p(a, b))
2241 return float_to_r(flt);
2243 nurat_rationalize_internal(a, b, &p, &q);
2244 return rb_rational_new2(p, q);
2247 VALUE
2248 rb_flt_rationalize(VALUE flt)
2250 VALUE a, b, f, p, q, den;
2251 int n;
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)));
2258 VALUE radix_times_f;
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
2267 a = rb_int_minus(radix_times_f, INT2FIX(FLT_RADIX - 1));
2268 b = rb_int_plus(radix_times_f, INT2FIX(FLT_RADIX - 1));
2271 if (f_eqeq_p(a, b))
2272 return float_to_r(flt);
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);
2281 * call-seq:
2282 * flt.rationalize([eps]) -> rational
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.
2288 * 0.3.rationalize #=> (3/10)
2289 * 1.333.rationalize #=> (1333/1000)
2290 * 1.333.rationalize(0.01) #=> (4/3)
2292 * See also Float#to_r.
2294 static VALUE
2295 float_rationalize(int argc, VALUE *argv, VALUE self)
2297 double d = RFLOAT_VALUE(self);
2298 VALUE rat;
2299 int neg = d < 0.0;
2300 if (neg) self = DBL2NUM(-d);
2302 if (rb_check_arity(argc, 0, 1)) {
2303 rat = rb_flt_rationalize_with_prec(self, argv[0]);
2305 else {
2306 rat = rb_flt_rationalize(self);
2308 if (neg) RATIONAL_SET_NUM(rat, rb_int_uminus(RRATIONAL(rat)->num));
2309 return rat;
2312 inline static int
2313 issign(int c)
2315 return (c == '-' || c == '+');
2318 static int
2319 read_sign(const char **s, const char *const e)
2321 int sign = '?';
2323 if (*s < e && issign(**s)) {
2324 sign = **s;
2325 (*s)++;
2327 return sign;
2330 inline static int
2331 islettere(int c)
2333 return (c == 'e' || c == 'E');
2336 static VALUE
2337 negate_num(VALUE num)
2339 if (FIXNUM_P(num)) {
2340 return rb_int_uminus(num);
2342 else {
2343 BIGNUM_NEGATE(num);
2344 return rb_big_norm(num);
2348 static int
2349 read_num(const char **s, const char *const end, VALUE *num, VALUE *nexp)
2351 VALUE fp = ONE, exp, fn = ZERO, n = ZERO;
2352 int expsign = 0, ok = 0;
2353 char *e;
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;
2367 if (*s < end && **s == '.') {
2368 size_t count = 0;
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;
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);
2382 ok = 1;
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);
2397 else {
2398 if (fn != ZERO) exp = rb_int_minus(exp, fn);
2399 exp = negate_num(exp);
2401 *nexp = exp;
2405 return ok;
2408 inline static const char *
2409 skip_ws(const char *s, const char *e)
2411 while (s < e && isspace((unsigned char)*s))
2412 ++s;
2413 return s;
2416 static VALUE
2417 parse_rat(const char *s, const char *const e, int strict, int raise)
2419 int sign;
2420 VALUE num, den, nexp, dexp;
2422 s = skip_ws(s, e);
2423 sign = read_sign(&s, e);
2425 if (!read_num(&s, e, &num, &nexp)) {
2426 if (strict) return Qnil;
2427 return nurat_s_alloc(rb_cRational);
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;
2436 else if (den == ZERO) {
2437 if (!raise) return Qnil;
2438 rb_num_zerodiv();
2440 else if (strict && skip_ws(s, e) != e) {
2441 return Qnil;
2443 else {
2444 nexp = rb_int_minus(nexp, dexp);
2445 nurat_reduce(&num, &den);
2448 else if (strict && skip_ws(s, e) != e) {
2449 return Qnil;
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;
2462 return sign == '-' ? DBL2NUM(-HUGE_VAL) : DBL2NUM(HUGE_VAL);
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;
2473 return sign == '-' ? DBL2NUM(-0.0) : DBL2NUM(+0.0);
2475 reduce:
2476 nurat_reduce(&num, &den);
2479 if (sign == '-') {
2480 num = negate_num(num);
2483 return rb_rational_raw(num, den);
2486 static VALUE
2487 string_to_r_strict(VALUE self, int raise)
2489 VALUE num;
2491 rb_must_asciicompat(self);
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);
2500 if (RB_FLOAT_TYPE_P(num) && !FLOAT_ZERO_P(num)) {
2501 if (!raise) return Qnil;
2502 rb_raise(rb_eFloatDomainError, "Infinity");
2504 return num;
2508 * call-seq:
2509 * str.to_r -> rational
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.
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)
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.
2530 * "0.3".to_r == 3/10r #=> true
2531 * 0.3.to_r == 3/10r #=> false
2533 * See also Kernel#Rational.
2535 static VALUE
2536 string_to_r(VALUE self)
2538 VALUE num;
2540 rb_must_asciicompat(self);
2542 num = parse_rat(RSTRING_PTR(self), RSTRING_END(self), 0, TRUE);
2544 if (RB_FLOAT_TYPE_P(num) && !FLOAT_ZERO_P(num))
2545 rb_raise(rb_eFloatDomainError, "Infinity");
2546 return num;
2549 VALUE
2550 rb_cstr_to_rat(const char *s, int strict) /* for complex's internal */
2552 VALUE num;
2554 num = parse_rat(s, s + strlen(s), strict, TRUE);
2556 if (RB_FLOAT_TYPE_P(num) && !FLOAT_ZERO_P(num))
2557 rb_raise(rb_eFloatDomainError, "Infinity");
2558 return num;
2561 static VALUE
2562 to_rational(VALUE val)
2564 return rb_convert_type_with_id(val, T_RATIONAL, "Rational", idTo_r);
2567 static VALUE
2568 nurat_convert(VALUE klass, VALUE numv, VALUE denv, int raise)
2570 VALUE a1 = numv, a2 = denv;
2571 int state;
2573 assert(a1 != Qundef);
2575 if (NIL_P(a1) || NIL_P(a2)) {
2576 if (!raise) return Qnil;
2577 rb_raise(rb_eTypeError, "can't convert nil into Rational");
2580 if (RB_TYPE_P(a1, T_COMPLEX)) {
2581 if (k_exact_zero_p(RCOMPLEX(a1)->imag))
2582 a1 = RCOMPLEX(a1)->real;
2585 if (RB_TYPE_P(a2, T_COMPLEX)) {
2586 if (k_exact_zero_p(RCOMPLEX(a2)->imag))
2587 a2 = RCOMPLEX(a2)->real;
2590 if (RB_INTEGER_TYPE_P(a1)) {
2591 // nothing to do
2593 else if (RB_FLOAT_TYPE_P(a1)) {
2594 a1 = float_to_r(a1);
2596 else if (RB_TYPE_P(a1, T_RATIONAL)) {
2597 // nothing to do
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;
2603 else if (!rb_respond_to(a1, idTo_r)) {
2604 VALUE tmp = rb_protect(rb_check_to_int, a1, NULL);
2605 rb_set_errinfo(Qnil);
2606 if (!NIL_P(tmp)) {
2607 a1 = tmp;
2611 if (RB_INTEGER_TYPE_P(a2)) {
2612 // nothing to do
2614 else if (RB_FLOAT_TYPE_P(a2)) {
2615 a2 = float_to_r(a2);
2617 else if (RB_TYPE_P(a2, T_RATIONAL)) {
2618 // nothing to do
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;
2624 else if (a2 != Qundef && !rb_respond_to(a2, idTo_r)) {
2625 VALUE tmp = rb_protect(rb_check_to_int, a2, NULL);
2626 rb_set_errinfo(Qnil);
2627 if (!NIL_P(tmp)) {
2628 a2 = tmp;
2632 if (RB_TYPE_P(a1, T_RATIONAL)) {
2633 if (a2 == Qundef || (k_exact_one_p(a2)))
2634 return a1;
2637 if (a2 == Qundef) {
2638 if (!RB_INTEGER_TYPE_P(a1)) {
2639 if (!raise) {
2640 VALUE result = rb_protect(to_rational, a1, NULL);
2641 rb_set_errinfo(Qnil);
2642 return result;
2644 return to_rational(a1);
2647 else {
2648 if (!k_numeric_p(a1)) {
2649 if (!raise) {
2650 a1 = rb_protect(to_rational, a1, &state);
2651 if (state) {
2652 rb_set_errinfo(Qnil);
2653 return Qnil;
2656 else {
2657 a1 = rb_check_convert_type_with_id(a1, T_RATIONAL, "Rational", idTo_r);
2660 if (!k_numeric_p(a2)) {
2661 if (!raise) {
2662 a2 = rb_protect(to_rational, a2, &state);
2663 if (state) {
2664 rb_set_errinfo(Qnil);
2665 return Qnil;
2668 else {
2669 a2 = rb_check_convert_type_with_id(a2, T_RATIONAL, "Rational", idTo_r);
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;
2678 else {
2679 rb_set_errinfo(Qnil);
2681 return f_div(a1, a2);
2685 a1 = nurat_int_value(a1);
2687 if (a2 == Qundef) {
2688 a2 = ONE;
2690 else if (!k_integer_p(a2) && !raise) {
2691 return Qnil;
2693 else {
2694 a2 = nurat_int_value(a2);
2698 return nurat_s_canonicalize_internal(klass, a1, a2);
2701 static VALUE
2702 nurat_s_convert(int argc, VALUE *argv, VALUE klass)
2704 VALUE a1, a2;
2706 if (rb_scan_args(argc, argv, "11", &a1, &a2) == 1) {
2707 a2 = Qundef;
2710 return nurat_convert(klass, a1, a2, TRUE);
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.
2718 * You can create a \Rational object explicitly with:
2720 * - A {rational literal}[doc/syntax/literals_rdoc.html#label-Rational+Literals].
2722 * You can convert certain objects to Rationals with:
2724 * - \Method {Rational}[Kernel.html#method-i-Rational].
2726 * Examples
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)
2734 * You can also create rational objects from floating-point numbers or
2735 * strings.
2737 * Rational(0.3) #=> (5404319552844595/18014398509481984)
2738 * Rational('0.3') #=> (3/10)
2739 * Rational('2/3') #=> (2/3)
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)
2746 * A rational object is an exact number, which helps you to write
2747 * programs without any rounding errors.
2749 * 10.times.inject(0) {|t| t + 0.1 } #=> 0.9999999999999999
2750 * 10.times.inject(0) {|t| t + Rational('0.1') } #=> (1/1)
2752 * However, when an expression includes an inexact component (numerical value
2753 * or operation), it will produce an inexact result.
2755 * Rational(10) / 3 #=> (10/3)
2756 * Rational(10) / 3.0 #=> 3.3333333333333335
2758 * Rational(-8) ** Rational(1, 3)
2759 * #=> (1.0000000000000002+1.7320508075688772i)
2761 void
2762 Init_Rational(void)
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");
2770 rb_cRational = rb_define_class("Rational", rb_cNumeric);
2772 rb_define_alloc_func(rb_cRational, nurat_s_alloc);
2773 rb_undef_method(CLASS_OF(rb_cRational), "allocate");
2775 rb_undef_method(CLASS_OF(rb_cRational), "new");
2777 rb_define_global_function("Rational", nurat_f_rational, -1);
2779 rb_define_method(rb_cRational, "numerator", nurat_numerator, 0);
2780 rb_define_method(rb_cRational, "denominator", nurat_denominator, 0);
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);
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);
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);
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);
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);
2810 rb_define_method(rb_cRational, "hash", nurat_hash, 0);
2812 rb_define_method(rb_cRational, "to_s", nurat_to_s, 0);
2813 rb_define_method(rb_cRational, "inspect", nurat_inspect, 0);
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);
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);
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);
2829 rb_define_method(rb_cInteger, "numerator", integer_numerator, 0);
2830 rb_define_method(rb_cInteger, "denominator", integer_denominator, 0);
2832 rb_define_method(rb_cFloat, "numerator", rb_float_numerator, 0);
2833 rb_define_method(rb_cFloat, "denominator", rb_float_denominator, 0);
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);
2842 rb_define_method(rb_cString, "to_r", string_to_r, 0);
2844 rb_define_private_method(CLASS_OF(rb_cRational), "convert", nurat_s_convert, -1);
2846 rb_provide("rational.so"); /* for backward compatibility */