Tempfile document updated.
[ruby.git] / rational.c
blob014cbb6c6adf87c18eccac45dd1f47ce06823d42
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(USE_GMP)
19 #if defined(HAVE_LIBGMP) && defined(HAVE_GMP_H)
20 # define USE_GMP 1
21 #else
22 # define USE_GMP 0
23 #endif
24 #endif
25 #if USE_GMP
26 #include <gmp.h>
27 #endif
29 #include "id.h"
30 #include "internal.h"
31 #include "internal/array.h"
32 #include "internal/complex.h"
33 #include "internal/gc.h"
34 #include "internal/numeric.h"
35 #include "internal/object.h"
36 #include "internal/rational.h"
37 #include "ruby_assert.h"
39 #define ZERO INT2FIX(0)
40 #define ONE INT2FIX(1)
41 #define TWO INT2FIX(2)
43 #define GMP_GCD_DIGITS 1
45 #define INT_ZERO_P(x) (FIXNUM_P(x) ? FIXNUM_ZERO_P(x) : rb_bigzero_p(x))
47 VALUE rb_cRational;
49 static ID id_abs, id_integer_p,
50 id_i_num, id_i_den;
52 #define id_idiv idDiv
53 #define id_to_i idTo_i
55 #define f_inspect rb_inspect
56 #define f_to_s rb_obj_as_string
58 static VALUE nurat_to_f(VALUE self);
59 static VALUE float_to_r(VALUE self);
61 inline static VALUE
62 f_add(VALUE x, VALUE y)
64 if (FIXNUM_ZERO_P(y))
65 return x;
66 if (FIXNUM_ZERO_P(x))
67 return y;
68 if (RB_INTEGER_TYPE_P(x))
69 return rb_int_plus(x, y);
70 return rb_funcall(x, '+', 1, y);
73 inline static VALUE
74 f_div(VALUE x, VALUE y)
76 if (y == ONE)
77 return x;
78 if (RB_INTEGER_TYPE_P(x))
79 return rb_int_div(x, y);
80 return rb_funcall(x, '/', 1, y);
83 inline static int
84 f_lt_p(VALUE x, VALUE y)
86 if (FIXNUM_P(x) && FIXNUM_P(y))
87 return (SIGNED_VALUE)x < (SIGNED_VALUE)y;
88 if (RB_INTEGER_TYPE_P(x)) {
89 VALUE r = rb_int_cmp(x, y);
90 if (!NIL_P(r)) return rb_int_negative_p(r);
92 return RTEST(rb_funcall(x, '<', 1, y));
95 #ifndef NDEBUG
96 /* f_mod is used only in f_gcd defined when NDEBUG is not defined */
97 inline static VALUE
98 f_mod(VALUE x, VALUE y)
100 if (RB_INTEGER_TYPE_P(x))
101 return rb_int_modulo(x, y);
102 return rb_funcall(x, '%', 1, y);
104 #endif
106 inline static VALUE
107 f_mul(VALUE x, VALUE y)
109 if (FIXNUM_ZERO_P(y) && RB_INTEGER_TYPE_P(x))
110 return ZERO;
111 if (y == ONE) return x;
112 if (FIXNUM_ZERO_P(x) && RB_INTEGER_TYPE_P(y))
113 return ZERO;
114 if (x == ONE) return y;
115 else if (RB_INTEGER_TYPE_P(x))
116 return rb_int_mul(x, y);
117 return rb_funcall(x, '*', 1, y);
120 inline static VALUE
121 f_sub(VALUE x, VALUE y)
123 if (FIXNUM_P(y) && FIXNUM_ZERO_P(y))
124 return x;
125 return rb_funcall(x, '-', 1, y);
128 inline static VALUE
129 f_abs(VALUE x)
131 if (RB_INTEGER_TYPE_P(x))
132 return rb_int_abs(x);
133 return rb_funcall(x, id_abs, 0);
137 inline static int
138 f_integer_p(VALUE x)
140 return RB_INTEGER_TYPE_P(x);
143 inline static VALUE
144 f_to_i(VALUE x)
146 if (RB_TYPE_P(x, T_STRING))
147 return rb_str_to_inum(x, 10, 0);
148 return rb_funcall(x, id_to_i, 0);
151 inline static int
152 f_eqeq_p(VALUE x, VALUE y)
154 if (FIXNUM_P(x) && FIXNUM_P(y))
155 return x == y;
156 if (RB_INTEGER_TYPE_P(x))
157 return RTEST(rb_int_equal(x, y));
158 return (int)rb_equal(x, y);
161 inline static VALUE
162 f_idiv(VALUE x, VALUE y)
164 if (RB_INTEGER_TYPE_P(x))
165 return rb_int_idiv(x, y);
166 return rb_funcall(x, id_idiv, 1, y);
169 #define f_expt10(x) rb_int_pow(INT2FIX(10), x)
171 inline static int
172 f_zero_p(VALUE x)
174 if (RB_INTEGER_TYPE_P(x)) {
175 return FIXNUM_ZERO_P(x);
177 else if (RB_TYPE_P(x, T_RATIONAL)) {
178 VALUE num = RRATIONAL(x)->num;
180 return FIXNUM_ZERO_P(num);
182 return (int)rb_equal(x, ZERO);
185 #define f_nonzero_p(x) (!f_zero_p(x))
187 inline static int
188 f_one_p(VALUE x)
190 if (RB_INTEGER_TYPE_P(x)) {
191 return x == LONG2FIX(1);
193 else if (RB_TYPE_P(x, T_RATIONAL)) {
194 VALUE num = RRATIONAL(x)->num;
195 VALUE den = RRATIONAL(x)->den;
197 return num == LONG2FIX(1) && den == LONG2FIX(1);
199 return (int)rb_equal(x, ONE);
202 inline static int
203 f_minus_one_p(VALUE x)
205 if (RB_INTEGER_TYPE_P(x)) {
206 return x == LONG2FIX(-1);
208 else if (RB_BIGNUM_TYPE_P(x)) {
209 return Qfalse;
211 else if (RB_TYPE_P(x, T_RATIONAL)) {
212 VALUE num = RRATIONAL(x)->num;
213 VALUE den = RRATIONAL(x)->den;
215 return num == LONG2FIX(-1) && den == LONG2FIX(1);
217 return (int)rb_equal(x, INT2FIX(-1));
220 inline static int
221 f_kind_of_p(VALUE x, VALUE c)
223 return (int)rb_obj_is_kind_of(x, c);
226 inline static int
227 k_numeric_p(VALUE x)
229 return f_kind_of_p(x, rb_cNumeric);
232 inline static int
233 k_integer_p(VALUE x)
235 return RB_INTEGER_TYPE_P(x);
238 inline static int
239 k_float_p(VALUE x)
241 return RB_FLOAT_TYPE_P(x);
244 inline static int
245 k_rational_p(VALUE x)
247 return RB_TYPE_P(x, T_RATIONAL);
250 #define k_exact_p(x) (!k_float_p(x))
251 #define k_inexact_p(x) k_float_p(x)
253 #define k_exact_zero_p(x) (k_exact_p(x) && f_zero_p(x))
254 #define k_exact_one_p(x) (k_exact_p(x) && f_one_p(x))
256 #if USE_GMP
257 VALUE
258 rb_gcd_gmp(VALUE x, VALUE y)
260 const size_t nails = (sizeof(BDIGIT)-SIZEOF_BDIGIT)*CHAR_BIT;
261 mpz_t mx, my, mz;
262 size_t count;
263 VALUE z;
264 long zn;
266 mpz_init(mx);
267 mpz_init(my);
268 mpz_init(mz);
269 mpz_import(mx, BIGNUM_LEN(x), -1, sizeof(BDIGIT), 0, nails, BIGNUM_DIGITS(x));
270 mpz_import(my, BIGNUM_LEN(y), -1, sizeof(BDIGIT), 0, nails, BIGNUM_DIGITS(y));
272 mpz_gcd(mz, mx, my);
274 mpz_clear(mx);
275 mpz_clear(my);
277 zn = (mpz_sizeinbase(mz, 16) + SIZEOF_BDIGIT*2 - 1) / (SIZEOF_BDIGIT*2);
278 z = rb_big_new(zn, 1);
279 mpz_export(BIGNUM_DIGITS(z), &count, -1, sizeof(BDIGIT), 0, nails, mz);
281 mpz_clear(mz);
283 return rb_big_norm(z);
285 #endif
287 #ifndef NDEBUG
288 #define f_gcd f_gcd_orig
289 #endif
291 inline static long
292 i_gcd(long x, long y)
294 unsigned long u, v, t;
295 int shift;
297 if (x < 0)
298 x = -x;
299 if (y < 0)
300 y = -y;
302 if (x == 0)
303 return y;
304 if (y == 0)
305 return x;
307 u = (unsigned long)x;
308 v = (unsigned long)y;
309 for (shift = 0; ((u | v) & 1) == 0; ++shift) {
310 u >>= 1;
311 v >>= 1;
314 while ((u & 1) == 0)
315 u >>= 1;
317 do {
318 while ((v & 1) == 0)
319 v >>= 1;
321 if (u > v) {
322 t = v;
323 v = u;
324 u = t;
326 v = v - u;
327 } while (v != 0);
329 return (long)(u << shift);
332 inline static VALUE
333 f_gcd_normal(VALUE x, VALUE y)
335 VALUE z;
337 if (FIXNUM_P(x) && FIXNUM_P(y))
338 return LONG2NUM(i_gcd(FIX2LONG(x), FIX2LONG(y)));
340 if (INT_NEGATIVE_P(x))
341 x = rb_int_uminus(x);
342 if (INT_NEGATIVE_P(y))
343 y = rb_int_uminus(y);
345 if (INT_ZERO_P(x))
346 return y;
347 if (INT_ZERO_P(y))
348 return x;
350 for (;;) {
351 if (FIXNUM_P(x)) {
352 if (FIXNUM_ZERO_P(x))
353 return y;
354 if (FIXNUM_P(y))
355 return LONG2NUM(i_gcd(FIX2LONG(x), FIX2LONG(y)));
357 z = x;
358 x = rb_int_modulo(y, x);
359 y = z;
361 /* NOTREACHED */
364 VALUE
365 rb_gcd_normal(VALUE x, VALUE y)
367 return f_gcd_normal(x, y);
370 inline static VALUE
371 f_gcd(VALUE x, VALUE y)
373 #if USE_GMP
374 if (RB_BIGNUM_TYPE_P(x) && RB_BIGNUM_TYPE_P(y)) {
375 size_t xn = BIGNUM_LEN(x);
376 size_t yn = BIGNUM_LEN(y);
377 if (GMP_GCD_DIGITS <= xn || GMP_GCD_DIGITS <= yn)
378 return rb_gcd_gmp(x, y);
380 #endif
381 return f_gcd_normal(x, y);
384 #ifndef NDEBUG
385 #undef f_gcd
387 inline static VALUE
388 f_gcd(VALUE x, VALUE y)
390 VALUE r = f_gcd_orig(x, y);
391 if (f_nonzero_p(r)) {
392 RUBY_ASSERT(f_zero_p(f_mod(x, r)));
393 RUBY_ASSERT(f_zero_p(f_mod(y, r)));
395 return r;
397 #endif
399 inline static VALUE
400 f_lcm(VALUE x, VALUE y)
402 if (INT_ZERO_P(x) || INT_ZERO_P(y))
403 return ZERO;
404 return f_abs(f_mul(f_div(x, f_gcd(x, y)), y));
407 #define get_dat1(x) \
408 struct RRational *dat = RRATIONAL(x)
410 #define get_dat2(x,y) \
411 struct RRational *adat = RRATIONAL(x), *bdat = RRATIONAL(y)
413 inline static VALUE
414 nurat_s_new_internal(VALUE klass, VALUE num, VALUE den)
416 NEWOBJ_OF(obj, struct RRational, klass, T_RATIONAL | (RGENGC_WB_PROTECTED_RATIONAL ? FL_WB_PROTECTED : 0),
417 sizeof(struct RRational), 0);
419 RATIONAL_SET_NUM((VALUE)obj, num);
420 RATIONAL_SET_DEN((VALUE)obj, den);
421 OBJ_FREEZE((VALUE)obj);
423 return (VALUE)obj;
426 static VALUE
427 nurat_s_alloc(VALUE klass)
429 return nurat_s_new_internal(klass, ZERO, ONE);
432 inline static VALUE
433 f_rational_new_bang1(VALUE klass, VALUE x)
435 return nurat_s_new_internal(klass, x, ONE);
438 inline static void
439 nurat_int_check(VALUE num)
441 if (!RB_INTEGER_TYPE_P(num)) {
442 if (!k_numeric_p(num) || !f_integer_p(num))
443 rb_raise(rb_eTypeError, "not an integer");
447 inline static VALUE
448 nurat_int_value(VALUE num)
450 nurat_int_check(num);
451 if (!k_integer_p(num))
452 num = f_to_i(num);
453 return num;
456 static void
457 nurat_canonicalize(VALUE *num, VALUE *den)
459 RUBY_ASSERT(num); RUBY_ASSERT(RB_INTEGER_TYPE_P(*num));
460 RUBY_ASSERT(den); RUBY_ASSERT(RB_INTEGER_TYPE_P(*den));
461 if (INT_NEGATIVE_P(*den)) {
462 *num = rb_int_uminus(*num);
463 *den = rb_int_uminus(*den);
465 else if (INT_ZERO_P(*den)) {
466 rb_num_zerodiv();
470 static void
471 nurat_reduce(VALUE *x, VALUE *y)
473 VALUE gcd;
474 if (*x == ONE || *y == ONE) return;
475 gcd = f_gcd(*x, *y);
476 *x = f_idiv(*x, gcd);
477 *y = f_idiv(*y, gcd);
480 inline static VALUE
481 nurat_s_canonicalize_internal(VALUE klass, VALUE num, VALUE den)
483 nurat_canonicalize(&num, &den);
484 nurat_reduce(&num, &den);
486 return nurat_s_new_internal(klass, num, den);
489 inline static VALUE
490 nurat_s_canonicalize_internal_no_reduce(VALUE klass, VALUE num, VALUE den)
492 nurat_canonicalize(&num, &den);
494 return nurat_s_new_internal(klass, num, den);
497 inline static VALUE
498 f_rational_new2(VALUE klass, VALUE x, VALUE y)
500 RUBY_ASSERT(!k_rational_p(x));
501 RUBY_ASSERT(!k_rational_p(y));
502 return nurat_s_canonicalize_internal(klass, x, y);
505 inline static VALUE
506 f_rational_new_no_reduce2(VALUE klass, VALUE x, VALUE y)
508 RUBY_ASSERT(!k_rational_p(x));
509 RUBY_ASSERT(!k_rational_p(y));
510 return nurat_s_canonicalize_internal_no_reduce(klass, x, y);
513 static VALUE nurat_convert(VALUE klass, VALUE numv, VALUE denv, int raise);
514 static VALUE nurat_s_convert(int argc, VALUE *argv, VALUE klass);
517 * call-seq:
518 * Rational(x, y, exception: true) -> rational or nil
519 * Rational(arg, exception: true) -> rational or nil
521 * Returns +x/y+ or +arg+ as a Rational.
523 * Rational(2, 3) #=> (2/3)
524 * Rational(5) #=> (5/1)
525 * Rational(0.5) #=> (1/2)
526 * Rational(0.3) #=> (5404319552844595/18014398509481984)
528 * Rational("2/3") #=> (2/3)
529 * Rational("0.3") #=> (3/10)
531 * Rational("10 cents") #=> ArgumentError
532 * Rational(nil) #=> TypeError
533 * Rational(1, nil) #=> TypeError
535 * Rational("10 cents", exception: false) #=> nil
537 * Syntax of the string form:
539 * string form = extra spaces , rational , extra spaces ;
540 * rational = [ sign ] , unsigned rational ;
541 * unsigned rational = numerator | numerator , "/" , denominator ;
542 * numerator = integer part | fractional part | integer part , fractional part ;
543 * denominator = digits ;
544 * integer part = digits ;
545 * fractional part = "." , digits , [ ( "e" | "E" ) , [ sign ] , digits ] ;
546 * sign = "-" | "+" ;
547 * digits = digit , { digit | "_" , digit } ;
548 * digit = "0" | "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9" ;
549 * extra spaces = ? \s* ? ;
551 * See also String#to_r.
553 static VALUE
554 nurat_f_rational(int argc, VALUE *argv, VALUE klass)
556 VALUE a1, a2, opts = Qnil;
557 int raise = TRUE;
559 if (rb_scan_args(argc, argv, "11:", &a1, &a2, &opts) == 1) {
560 a2 = Qundef;
562 if (!NIL_P(opts)) {
563 raise = rb_opts_exception_p(opts, raise);
565 return nurat_convert(rb_cRational, a1, a2, raise);
569 * call-seq:
570 * rat.numerator -> integer
572 * Returns the numerator.
574 * Rational(7).numerator #=> 7
575 * Rational(7, 1).numerator #=> 7
576 * Rational(9, -4).numerator #=> -9
577 * Rational(-2, -10).numerator #=> 1
579 static VALUE
580 nurat_numerator(VALUE self)
582 get_dat1(self);
583 return dat->num;
587 * call-seq:
588 * rat.denominator -> integer
590 * Returns the denominator (always positive).
592 * Rational(7).denominator #=> 1
593 * Rational(7, 1).denominator #=> 1
594 * Rational(9, -4).denominator #=> 4
595 * Rational(-2, -10).denominator #=> 5
597 static VALUE
598 nurat_denominator(VALUE self)
600 get_dat1(self);
601 return dat->den;
605 * call-seq:
606 * -rat -> rational
608 * Negates +rat+.
610 VALUE
611 rb_rational_uminus(VALUE self)
613 const int unused = (RUBY_ASSERT(RB_TYPE_P(self, T_RATIONAL)), 0);
614 get_dat1(self);
615 (void)unused;
616 return f_rational_new2(CLASS_OF(self), rb_int_uminus(dat->num), dat->den);
619 #ifndef NDEBUG
620 #define f_imul f_imul_orig
621 #endif
623 inline static VALUE
624 f_imul(long a, long b)
626 VALUE r;
628 if (a == 0 || b == 0)
629 return ZERO;
630 else if (a == 1)
631 return LONG2NUM(b);
632 else if (b == 1)
633 return LONG2NUM(a);
635 if (MUL_OVERFLOW_LONG_P(a, b))
636 r = rb_big_mul(rb_int2big(a), rb_int2big(b));
637 else
638 r = LONG2NUM(a * b);
639 return r;
642 #ifndef NDEBUG
643 #undef f_imul
645 inline static VALUE
646 f_imul(long x, long y)
648 VALUE r = f_imul_orig(x, y);
649 RUBY_ASSERT(f_eqeq_p(r, f_mul(LONG2NUM(x), LONG2NUM(y))));
650 return r;
652 #endif
654 inline static VALUE
655 f_addsub(VALUE self, VALUE anum, VALUE aden, VALUE bnum, VALUE bden, int k)
657 VALUE num, den;
659 if (FIXNUM_P(anum) && FIXNUM_P(aden) &&
660 FIXNUM_P(bnum) && FIXNUM_P(bden)) {
661 long an = FIX2LONG(anum);
662 long ad = FIX2LONG(aden);
663 long bn = FIX2LONG(bnum);
664 long bd = FIX2LONG(bden);
665 long ig = i_gcd(ad, bd);
667 VALUE g = LONG2NUM(ig);
668 VALUE a = f_imul(an, bd / ig);
669 VALUE b = f_imul(bn, ad / ig);
670 VALUE c;
672 if (k == '+')
673 c = rb_int_plus(a, b);
674 else
675 c = rb_int_minus(a, b);
677 b = rb_int_idiv(aden, g);
678 g = f_gcd(c, g);
679 num = rb_int_idiv(c, g);
680 a = rb_int_idiv(bden, g);
681 den = rb_int_mul(a, b);
683 else if (RB_INTEGER_TYPE_P(anum) && RB_INTEGER_TYPE_P(aden) &&
684 RB_INTEGER_TYPE_P(bnum) && RB_INTEGER_TYPE_P(bden)) {
685 VALUE g = f_gcd(aden, bden);
686 VALUE a = rb_int_mul(anum, rb_int_idiv(bden, g));
687 VALUE b = rb_int_mul(bnum, rb_int_idiv(aden, g));
688 VALUE c;
690 if (k == '+')
691 c = rb_int_plus(a, b);
692 else
693 c = rb_int_minus(a, b);
695 b = rb_int_idiv(aden, g);
696 g = f_gcd(c, g);
697 num = rb_int_idiv(c, g);
698 a = rb_int_idiv(bden, g);
699 den = rb_int_mul(a, b);
701 else {
702 double a = NUM2DBL(anum) / NUM2DBL(aden);
703 double b = NUM2DBL(bnum) / NUM2DBL(bden);
704 double c = k == '+' ? a + b : a - b;
705 return DBL2NUM(c);
707 return f_rational_new_no_reduce2(CLASS_OF(self), num, den);
710 static double nurat_to_double(VALUE self);
712 * call-seq:
713 * rat + numeric -> numeric
715 * Performs addition.
717 * Rational(2, 3) + Rational(2, 3) #=> (4/3)
718 * Rational(900) + Rational(1) #=> (901/1)
719 * Rational(-2, 9) + Rational(-9, 2) #=> (-85/18)
720 * Rational(9, 8) + 4 #=> (41/8)
721 * Rational(20, 9) + 9.8 #=> 12.022222222222222
723 VALUE
724 rb_rational_plus(VALUE self, VALUE other)
726 if (RB_INTEGER_TYPE_P(other)) {
728 get_dat1(self);
730 return f_rational_new_no_reduce2(CLASS_OF(self),
731 rb_int_plus(dat->num, rb_int_mul(other, dat->den)),
732 dat->den);
735 else if (RB_FLOAT_TYPE_P(other)) {
736 return DBL2NUM(nurat_to_double(self) + RFLOAT_VALUE(other));
738 else if (RB_TYPE_P(other, T_RATIONAL)) {
740 get_dat2(self, other);
742 return f_addsub(self,
743 adat->num, adat->den,
744 bdat->num, bdat->den, '+');
747 else {
748 return rb_num_coerce_bin(self, other, '+');
753 * call-seq:
754 * rat - numeric -> numeric
756 * Performs subtraction.
758 * Rational(2, 3) - Rational(2, 3) #=> (0/1)
759 * Rational(900) - Rational(1) #=> (899/1)
760 * Rational(-2, 9) - Rational(-9, 2) #=> (77/18)
761 * Rational(9, 8) - 4 #=> (-23/8)
762 * Rational(20, 9) - 9.8 #=> -7.577777777777778
764 VALUE
765 rb_rational_minus(VALUE self, VALUE other)
767 if (RB_INTEGER_TYPE_P(other)) {
769 get_dat1(self);
771 return f_rational_new_no_reduce2(CLASS_OF(self),
772 rb_int_minus(dat->num, rb_int_mul(other, dat->den)),
773 dat->den);
776 else if (RB_FLOAT_TYPE_P(other)) {
777 return DBL2NUM(nurat_to_double(self) - RFLOAT_VALUE(other));
779 else if (RB_TYPE_P(other, T_RATIONAL)) {
781 get_dat2(self, other);
783 return f_addsub(self,
784 adat->num, adat->den,
785 bdat->num, bdat->den, '-');
788 else {
789 return rb_num_coerce_bin(self, other, '-');
793 inline static VALUE
794 f_muldiv(VALUE self, VALUE anum, VALUE aden, VALUE bnum, VALUE bden, int k)
796 VALUE num, den;
798 RUBY_ASSERT(RB_TYPE_P(self, T_RATIONAL));
800 /* Integer#** can return Rational with Float right now */
801 if (RB_FLOAT_TYPE_P(anum) || RB_FLOAT_TYPE_P(aden) ||
802 RB_FLOAT_TYPE_P(bnum) || RB_FLOAT_TYPE_P(bden)) {
803 double an = NUM2DBL(anum), ad = NUM2DBL(aden);
804 double bn = NUM2DBL(bnum), bd = NUM2DBL(bden);
805 double x = (an * bn) / (ad * bd);
806 return DBL2NUM(x);
809 RUBY_ASSERT(RB_INTEGER_TYPE_P(anum));
810 RUBY_ASSERT(RB_INTEGER_TYPE_P(aden));
811 RUBY_ASSERT(RB_INTEGER_TYPE_P(bnum));
812 RUBY_ASSERT(RB_INTEGER_TYPE_P(bden));
814 if (k == '/') {
815 VALUE t;
817 if (INT_NEGATIVE_P(bnum)) {
818 anum = rb_int_uminus(anum);
819 bnum = rb_int_uminus(bnum);
821 t = bnum;
822 bnum = bden;
823 bden = t;
826 if (FIXNUM_P(anum) && FIXNUM_P(aden) &&
827 FIXNUM_P(bnum) && FIXNUM_P(bden)) {
828 long an = FIX2LONG(anum);
829 long ad = FIX2LONG(aden);
830 long bn = FIX2LONG(bnum);
831 long bd = FIX2LONG(bden);
832 long g1 = i_gcd(an, bd);
833 long g2 = i_gcd(ad, bn);
835 num = f_imul(an / g1, bn / g2);
836 den = f_imul(ad / g2, bd / g1);
838 else {
839 VALUE g1 = f_gcd(anum, bden);
840 VALUE g2 = f_gcd(aden, bnum);
842 num = rb_int_mul(rb_int_idiv(anum, g1), rb_int_idiv(bnum, g2));
843 den = rb_int_mul(rb_int_idiv(aden, g2), rb_int_idiv(bden, g1));
845 return f_rational_new_no_reduce2(CLASS_OF(self), num, den);
849 * call-seq:
850 * rat * numeric -> numeric
852 * Performs multiplication.
854 * Rational(2, 3) * Rational(2, 3) #=> (4/9)
855 * Rational(900) * Rational(1) #=> (900/1)
856 * Rational(-2, 9) * Rational(-9, 2) #=> (1/1)
857 * Rational(9, 8) * 4 #=> (9/2)
858 * Rational(20, 9) * 9.8 #=> 21.77777777777778
860 VALUE
861 rb_rational_mul(VALUE self, VALUE other)
863 if (RB_INTEGER_TYPE_P(other)) {
865 get_dat1(self);
867 return f_muldiv(self,
868 dat->num, dat->den,
869 other, ONE, '*');
872 else if (RB_FLOAT_TYPE_P(other)) {
873 return DBL2NUM(nurat_to_double(self) * RFLOAT_VALUE(other));
875 else if (RB_TYPE_P(other, T_RATIONAL)) {
877 get_dat2(self, other);
879 return f_muldiv(self,
880 adat->num, adat->den,
881 bdat->num, bdat->den, '*');
884 else {
885 return rb_num_coerce_bin(self, other, '*');
890 * call-seq:
891 * rat / numeric -> numeric
892 * rat.quo(numeric) -> numeric
894 * Performs division.
896 * Rational(2, 3) / Rational(2, 3) #=> (1/1)
897 * Rational(900) / Rational(1) #=> (900/1)
898 * Rational(-2, 9) / Rational(-9, 2) #=> (4/81)
899 * Rational(9, 8) / 4 #=> (9/32)
900 * Rational(20, 9) / 9.8 #=> 0.22675736961451246
902 VALUE
903 rb_rational_div(VALUE self, VALUE other)
905 if (RB_INTEGER_TYPE_P(other)) {
906 if (f_zero_p(other))
907 rb_num_zerodiv();
909 get_dat1(self);
911 return f_muldiv(self,
912 dat->num, dat->den,
913 other, ONE, '/');
916 else if (RB_FLOAT_TYPE_P(other)) {
917 VALUE v = nurat_to_f(self);
918 return rb_flo_div_flo(v, other);
920 else if (RB_TYPE_P(other, T_RATIONAL)) {
921 if (f_zero_p(other))
922 rb_num_zerodiv();
924 get_dat2(self, other);
926 if (f_one_p(self))
927 return f_rational_new_no_reduce2(CLASS_OF(self),
928 bdat->den, bdat->num);
930 return f_muldiv(self,
931 adat->num, adat->den,
932 bdat->num, bdat->den, '/');
935 else {
936 return rb_num_coerce_bin(self, other, '/');
941 * call-seq:
942 * rat.fdiv(numeric) -> float
944 * Performs division and returns the value as a Float.
946 * Rational(2, 3).fdiv(1) #=> 0.6666666666666666
947 * Rational(2, 3).fdiv(0.5) #=> 1.3333333333333333
948 * Rational(2).fdiv(3) #=> 0.6666666666666666
950 static VALUE
951 nurat_fdiv(VALUE self, VALUE other)
953 VALUE div;
954 if (f_zero_p(other))
955 return rb_rational_div(self, rb_float_new(0.0));
956 if (FIXNUM_P(other) && other == LONG2FIX(1))
957 return nurat_to_f(self);
958 div = rb_rational_div(self, other);
959 if (RB_TYPE_P(div, T_RATIONAL))
960 return nurat_to_f(div);
961 if (RB_FLOAT_TYPE_P(div))
962 return div;
963 return rb_funcall(div, idTo_f, 0);
967 * call-seq:
968 * rat ** numeric -> numeric
970 * Performs exponentiation.
972 * Rational(2) ** Rational(3) #=> (8/1)
973 * Rational(10) ** -2 #=> (1/100)
974 * Rational(10) ** -2.0 #=> 0.01
975 * Rational(-4) ** Rational(1, 2) #=> (0.0+2.0i)
976 * Rational(1, 2) ** 0 #=> (1/1)
977 * Rational(1, 2) ** 0.0 #=> 1.0
979 VALUE
980 rb_rational_pow(VALUE self, VALUE other)
982 if (k_numeric_p(other) && k_exact_zero_p(other))
983 return f_rational_new_bang1(CLASS_OF(self), ONE);
985 if (k_rational_p(other)) {
986 get_dat1(other);
988 if (f_one_p(dat->den))
989 other = dat->num; /* c14n */
992 /* Deal with special cases of 0**n and 1**n */
993 if (k_numeric_p(other) && k_exact_p(other)) {
994 get_dat1(self);
995 if (f_one_p(dat->den)) {
996 if (f_one_p(dat->num)) {
997 return f_rational_new_bang1(CLASS_OF(self), ONE);
999 else if (f_minus_one_p(dat->num) && RB_INTEGER_TYPE_P(other)) {
1000 return f_rational_new_bang1(CLASS_OF(self), INT2FIX(rb_int_odd_p(other) ? -1 : 1));
1002 else if (INT_ZERO_P(dat->num)) {
1003 if (rb_num_negative_p(other)) {
1004 rb_num_zerodiv();
1006 else {
1007 return f_rational_new_bang1(CLASS_OF(self), ZERO);
1013 /* General case */
1014 if (FIXNUM_P(other)) {
1016 VALUE num, den;
1018 get_dat1(self);
1020 if (INT_POSITIVE_P(other)) {
1021 num = rb_int_pow(dat->num, other);
1022 den = rb_int_pow(dat->den, other);
1024 else if (INT_NEGATIVE_P(other)) {
1025 num = rb_int_pow(dat->den, rb_int_uminus(other));
1026 den = rb_int_pow(dat->num, rb_int_uminus(other));
1028 else {
1029 num = ONE;
1030 den = ONE;
1032 if (RB_FLOAT_TYPE_P(num)) { /* infinity due to overflow */
1033 if (RB_FLOAT_TYPE_P(den))
1034 return DBL2NUM(nan(""));
1035 return num;
1037 if (RB_FLOAT_TYPE_P(den)) { /* infinity due to overflow */
1038 num = ZERO;
1039 den = ONE;
1041 return f_rational_new2(CLASS_OF(self), num, den);
1044 else if (RB_BIGNUM_TYPE_P(other)) {
1045 rb_warn("in a**b, b may be too big");
1046 return rb_float_pow(nurat_to_f(self), other);
1048 else if (RB_FLOAT_TYPE_P(other) || RB_TYPE_P(other, T_RATIONAL)) {
1049 return rb_float_pow(nurat_to_f(self), other);
1051 else {
1052 return rb_num_coerce_bin(self, other, idPow);
1055 #define nurat_expt rb_rational_pow
1058 * call-seq:
1059 * rational <=> numeric -> -1, 0, +1, or nil
1061 * Returns -1, 0, or +1 depending on whether +rational+ is
1062 * less than, equal to, or greater than +numeric+.
1064 * +nil+ is returned if the two values are incomparable.
1066 * Rational(2, 3) <=> Rational(2, 3) #=> 0
1067 * Rational(5) <=> 5 #=> 0
1068 * Rational(2, 3) <=> Rational(1, 3) #=> 1
1069 * Rational(1, 3) <=> 1 #=> -1
1070 * Rational(1, 3) <=> 0.3 #=> 1
1072 * Rational(1, 3) <=> "0.3" #=> nil
1074 VALUE
1075 rb_rational_cmp(VALUE self, VALUE other)
1077 switch (TYPE(other)) {
1078 case T_FIXNUM:
1079 case T_BIGNUM:
1081 get_dat1(self);
1083 if (dat->den == LONG2FIX(1))
1084 return rb_int_cmp(dat->num, other); /* c14n */
1085 other = f_rational_new_bang1(CLASS_OF(self), other);
1086 /* FALLTHROUGH */
1089 case T_RATIONAL:
1091 VALUE num1, num2;
1093 get_dat2(self, other);
1095 if (FIXNUM_P(adat->num) && FIXNUM_P(adat->den) &&
1096 FIXNUM_P(bdat->num) && FIXNUM_P(bdat->den)) {
1097 num1 = f_imul(FIX2LONG(adat->num), FIX2LONG(bdat->den));
1098 num2 = f_imul(FIX2LONG(bdat->num), FIX2LONG(adat->den));
1100 else {
1101 num1 = rb_int_mul(adat->num, bdat->den);
1102 num2 = rb_int_mul(bdat->num, adat->den);
1104 return rb_int_cmp(rb_int_minus(num1, num2), ZERO);
1107 case T_FLOAT:
1108 return rb_dbl_cmp(nurat_to_double(self), RFLOAT_VALUE(other));
1110 default:
1111 return rb_num_coerce_cmp(self, other, idCmp);
1116 * call-seq:
1117 * rat == object -> true or false
1119 * Returns +true+ if +rat+ equals +object+ numerically.
1121 * Rational(2, 3) == Rational(2, 3) #=> true
1122 * Rational(5) == 5 #=> true
1123 * Rational(0) == 0.0 #=> true
1124 * Rational('1/3') == 0.33 #=> false
1125 * Rational('1/2') == '1/2' #=> false
1127 static VALUE
1128 nurat_eqeq_p(VALUE self, VALUE other)
1130 if (RB_INTEGER_TYPE_P(other)) {
1131 get_dat1(self);
1133 if (RB_INTEGER_TYPE_P(dat->num) && RB_INTEGER_TYPE_P(dat->den)) {
1134 if (INT_ZERO_P(dat->num) && INT_ZERO_P(other))
1135 return Qtrue;
1137 if (!FIXNUM_P(dat->den))
1138 return Qfalse;
1139 if (FIX2LONG(dat->den) != 1)
1140 return Qfalse;
1141 return rb_int_equal(dat->num, other);
1143 else {
1144 const double d = nurat_to_double(self);
1145 return RBOOL(FIXNUM_ZERO_P(rb_dbl_cmp(d, NUM2DBL(other))));
1148 else if (RB_FLOAT_TYPE_P(other)) {
1149 const double d = nurat_to_double(self);
1150 return RBOOL(FIXNUM_ZERO_P(rb_dbl_cmp(d, RFLOAT_VALUE(other))));
1152 else if (RB_TYPE_P(other, T_RATIONAL)) {
1154 get_dat2(self, other);
1156 if (INT_ZERO_P(adat->num) && INT_ZERO_P(bdat->num))
1157 return Qtrue;
1159 return RBOOL(rb_int_equal(adat->num, bdat->num) &&
1160 rb_int_equal(adat->den, bdat->den));
1163 else {
1164 return rb_equal(other, self);
1168 /* :nodoc: */
1169 static VALUE
1170 nurat_coerce(VALUE self, VALUE other)
1172 if (RB_INTEGER_TYPE_P(other)) {
1173 return rb_assoc_new(f_rational_new_bang1(CLASS_OF(self), other), self);
1175 else if (RB_FLOAT_TYPE_P(other)) {
1176 return rb_assoc_new(other, nurat_to_f(self));
1178 else if (RB_TYPE_P(other, T_RATIONAL)) {
1179 return rb_assoc_new(other, self);
1181 else if (RB_TYPE_P(other, T_COMPLEX)) {
1182 if (!k_exact_zero_p(RCOMPLEX(other)->imag))
1183 return rb_assoc_new(other, rb_Complex(self, INT2FIX(0)));
1184 other = RCOMPLEX(other)->real;
1185 if (RB_FLOAT_TYPE_P(other)) {
1186 other = float_to_r(other);
1187 RBASIC_SET_CLASS(other, CLASS_OF(self));
1189 else {
1190 other = f_rational_new_bang1(CLASS_OF(self), other);
1192 return rb_assoc_new(other, self);
1195 rb_raise(rb_eTypeError, "%s can't be coerced into %s",
1196 rb_obj_classname(other), rb_obj_classname(self));
1197 return Qnil;
1201 * call-seq:
1202 * rat.positive? -> true or false
1204 * Returns +true+ if +rat+ is greater than 0.
1206 static VALUE
1207 nurat_positive_p(VALUE self)
1209 get_dat1(self);
1210 return RBOOL(INT_POSITIVE_P(dat->num));
1214 * call-seq:
1215 * rat.negative? -> true or false
1217 * Returns +true+ if +rat+ is less than 0.
1219 static VALUE
1220 nurat_negative_p(VALUE self)
1222 get_dat1(self);
1223 return RBOOL(INT_NEGATIVE_P(dat->num));
1227 * call-seq:
1228 * rat.abs -> rational
1229 * rat.magnitude -> rational
1231 * Returns the absolute value of +rat+.
1233 * (1/2r).abs #=> (1/2)
1234 * (-1/2r).abs #=> (1/2)
1238 VALUE
1239 rb_rational_abs(VALUE self)
1241 get_dat1(self);
1242 if (INT_NEGATIVE_P(dat->num)) {
1243 VALUE num = rb_int_abs(dat->num);
1244 return nurat_s_canonicalize_internal_no_reduce(CLASS_OF(self), num, dat->den);
1246 return self;
1249 static VALUE
1250 nurat_floor(VALUE self)
1252 get_dat1(self);
1253 return rb_int_idiv(dat->num, dat->den);
1256 static VALUE
1257 nurat_ceil(VALUE self)
1259 get_dat1(self);
1260 return rb_int_uminus(rb_int_idiv(rb_int_uminus(dat->num), dat->den));
1264 * call-seq:
1265 * rat.to_i -> integer
1267 * Returns the truncated value as an integer.
1269 * Equivalent to Rational#truncate.
1271 * Rational(2, 3).to_i #=> 0
1272 * Rational(3).to_i #=> 3
1273 * Rational(300.6).to_i #=> 300
1274 * Rational(98, 71).to_i #=> 1
1275 * Rational(-31, 2).to_i #=> -15
1277 static VALUE
1278 nurat_truncate(VALUE self)
1280 get_dat1(self);
1281 if (INT_NEGATIVE_P(dat->num))
1282 return rb_int_uminus(rb_int_idiv(rb_int_uminus(dat->num), dat->den));
1283 return rb_int_idiv(dat->num, dat->den);
1286 static VALUE
1287 nurat_round_half_up(VALUE self)
1289 VALUE num, den, neg;
1291 get_dat1(self);
1293 num = dat->num;
1294 den = dat->den;
1295 neg = INT_NEGATIVE_P(num);
1297 if (neg)
1298 num = rb_int_uminus(num);
1300 num = rb_int_plus(rb_int_mul(num, TWO), den);
1301 den = rb_int_mul(den, TWO);
1302 num = rb_int_idiv(num, den);
1304 if (neg)
1305 num = rb_int_uminus(num);
1307 return num;
1310 static VALUE
1311 nurat_round_half_down(VALUE self)
1313 VALUE num, den, neg;
1315 get_dat1(self);
1317 num = dat->num;
1318 den = dat->den;
1319 neg = INT_NEGATIVE_P(num);
1321 if (neg)
1322 num = rb_int_uminus(num);
1324 num = rb_int_plus(rb_int_mul(num, TWO), den);
1325 num = rb_int_minus(num, ONE);
1326 den = rb_int_mul(den, TWO);
1327 num = rb_int_idiv(num, den);
1329 if (neg)
1330 num = rb_int_uminus(num);
1332 return num;
1335 static VALUE
1336 nurat_round_half_even(VALUE self)
1338 VALUE num, den, neg, qr;
1340 get_dat1(self);
1342 num = dat->num;
1343 den = dat->den;
1344 neg = INT_NEGATIVE_P(num);
1346 if (neg)
1347 num = rb_int_uminus(num);
1349 num = rb_int_plus(rb_int_mul(num, TWO), den);
1350 den = rb_int_mul(den, TWO);
1351 qr = rb_int_divmod(num, den);
1352 num = RARRAY_AREF(qr, 0);
1353 if (INT_ZERO_P(RARRAY_AREF(qr, 1)))
1354 num = rb_int_and(num, LONG2FIX(((int)~1)));
1356 if (neg)
1357 num = rb_int_uminus(num);
1359 return num;
1362 static VALUE
1363 f_round_common(int argc, VALUE *argv, VALUE self, VALUE (*func)(VALUE))
1365 VALUE n, b, s;
1367 if (rb_check_arity(argc, 0, 1) == 0)
1368 return (*func)(self);
1370 n = argv[0];
1372 if (!k_integer_p(n))
1373 rb_raise(rb_eTypeError, "not an integer");
1375 b = f_expt10(n);
1376 s = rb_rational_mul(self, b);
1378 if (k_float_p(s)) {
1379 if (INT_NEGATIVE_P(n))
1380 return ZERO;
1381 return self;
1384 if (!k_rational_p(s)) {
1385 s = f_rational_new_bang1(CLASS_OF(self), s);
1388 s = (*func)(s);
1390 s = rb_rational_div(f_rational_new_bang1(CLASS_OF(self), s), b);
1392 if (RB_TYPE_P(s, T_RATIONAL) && FIX2INT(rb_int_cmp(n, ONE)) < 0)
1393 s = nurat_truncate(s);
1395 return s;
1398 VALUE
1399 rb_rational_floor(VALUE self, int ndigits)
1401 if (ndigits == 0) {
1402 return nurat_floor(self);
1404 else {
1405 VALUE n = INT2NUM(ndigits);
1406 return f_round_common(1, &n, self, nurat_floor);
1411 * call-seq:
1412 * rat.floor([ndigits]) -> integer or rational
1414 * Returns the largest number less than or equal to +rat+ with
1415 * a precision of +ndigits+ decimal digits (default: 0).
1417 * When the precision is negative, the returned value is an integer
1418 * with at least <code>ndigits.abs</code> trailing zeros.
1420 * Returns a rational when +ndigits+ is positive,
1421 * otherwise returns an integer.
1423 * Rational(3).floor #=> 3
1424 * Rational(2, 3).floor #=> 0
1425 * Rational(-3, 2).floor #=> -2
1427 * # decimal - 1 2 3 . 4 5 6
1428 * # ^ ^ ^ ^ ^ ^
1429 * # precision -3 -2 -1 0 +1 +2
1431 * Rational('-123.456').floor(+1).to_f #=> -123.5
1432 * Rational('-123.456').floor(-1) #=> -130
1434 static VALUE
1435 nurat_floor_n(int argc, VALUE *argv, VALUE self)
1437 return f_round_common(argc, argv, self, nurat_floor);
1441 * call-seq:
1442 * rat.ceil([ndigits]) -> integer or rational
1444 * Returns the smallest number greater than or equal to +rat+ with
1445 * a precision of +ndigits+ decimal digits (default: 0).
1447 * When the precision is negative, the returned value is an integer
1448 * with at least <code>ndigits.abs</code> trailing zeros.
1450 * Returns a rational when +ndigits+ is positive,
1451 * otherwise returns an integer.
1453 * Rational(3).ceil #=> 3
1454 * Rational(2, 3).ceil #=> 1
1455 * Rational(-3, 2).ceil #=> -1
1457 * # decimal - 1 2 3 . 4 5 6
1458 * # ^ ^ ^ ^ ^ ^
1459 * # precision -3 -2 -1 0 +1 +2
1461 * Rational('-123.456').ceil(+1).to_f #=> -123.4
1462 * Rational('-123.456').ceil(-1) #=> -120
1464 static VALUE
1465 nurat_ceil_n(int argc, VALUE *argv, VALUE self)
1467 return f_round_common(argc, argv, self, nurat_ceil);
1471 * call-seq:
1472 * rat.truncate([ndigits]) -> integer or rational
1474 * Returns +rat+ truncated (toward zero) to
1475 * a precision of +ndigits+ decimal digits (default: 0).
1477 * When the precision is negative, the returned value is an integer
1478 * with at least <code>ndigits.abs</code> trailing zeros.
1480 * Returns a rational when +ndigits+ is positive,
1481 * otherwise returns an integer.
1483 * Rational(3).truncate #=> 3
1484 * Rational(2, 3).truncate #=> 0
1485 * Rational(-3, 2).truncate #=> -1
1487 * # decimal - 1 2 3 . 4 5 6
1488 * # ^ ^ ^ ^ ^ ^
1489 * # precision -3 -2 -1 0 +1 +2
1491 * Rational('-123.456').truncate(+1).to_f #=> -123.4
1492 * Rational('-123.456').truncate(-1) #=> -120
1494 static VALUE
1495 nurat_truncate_n(int argc, VALUE *argv, VALUE self)
1497 return f_round_common(argc, argv, self, nurat_truncate);
1501 * call-seq:
1502 * rat.round([ndigits] [, half: mode]) -> integer or rational
1504 * Returns +rat+ rounded to the nearest value with
1505 * a precision of +ndigits+ decimal digits (default: 0).
1507 * When the precision is negative, the returned value is an integer
1508 * with at least <code>ndigits.abs</code> trailing zeros.
1510 * Returns a rational when +ndigits+ is positive,
1511 * otherwise returns an integer.
1513 * Rational(3).round #=> 3
1514 * Rational(2, 3).round #=> 1
1515 * Rational(-3, 2).round #=> -2
1517 * # decimal - 1 2 3 . 4 5 6
1518 * # ^ ^ ^ ^ ^ ^
1519 * # precision -3 -2 -1 0 +1 +2
1521 * Rational('-123.456').round(+1).to_f #=> -123.5
1522 * Rational('-123.456').round(-1) #=> -120
1524 * The optional +half+ keyword argument is available
1525 * similar to Float#round.
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 * Rational(35, 100).round(1, half: :up) #=> (2/5)
1531 * Rational(35, 100).round(1, half: :down) #=> (3/10)
1532 * Rational(35, 100).round(1, half: :even) #=> (2/5)
1533 * Rational(-25, 100).round(1, half: :up) #=> (-3/10)
1534 * Rational(-25, 100).round(1, half: :down) #=> (-1/5)
1535 * Rational(-25, 100).round(1, half: :even) #=> (-1/5)
1537 static VALUE
1538 nurat_round_n(int argc, VALUE *argv, VALUE self)
1540 VALUE opt;
1541 enum ruby_num_rounding_mode mode = (
1542 argc = rb_scan_args(argc, argv, "*:", NULL, &opt),
1543 rb_num_get_rounding_option(opt));
1544 VALUE (*round_func)(VALUE) = ROUND_FUNC(mode, nurat_round);
1545 return f_round_common(argc, argv, self, round_func);
1548 VALUE
1549 rb_flo_round_by_rational(int argc, VALUE *argv, VALUE num)
1551 return nurat_to_f(nurat_round_n(argc, argv, float_to_r(num)));
1554 static double
1555 nurat_to_double(VALUE self)
1557 get_dat1(self);
1558 if (!RB_INTEGER_TYPE_P(dat->num) || !RB_INTEGER_TYPE_P(dat->den)) {
1559 return NUM2DBL(dat->num) / NUM2DBL(dat->den);
1561 return rb_int_fdiv_double(dat->num, dat->den);
1565 * call-seq:
1566 * rat.to_f -> float
1568 * Returns the value as a Float.
1570 * Rational(2).to_f #=> 2.0
1571 * Rational(9, 4).to_f #=> 2.25
1572 * Rational(-3, 4).to_f #=> -0.75
1573 * Rational(20, 3).to_f #=> 6.666666666666667
1575 static VALUE
1576 nurat_to_f(VALUE self)
1578 return DBL2NUM(nurat_to_double(self));
1582 * call-seq:
1583 * rat.to_r -> self
1585 * Returns self.
1587 * Rational(2).to_r #=> (2/1)
1588 * Rational(-8, 6).to_r #=> (-4/3)
1590 static VALUE
1591 nurat_to_r(VALUE self)
1593 return self;
1596 #define id_ceil rb_intern("ceil")
1597 static VALUE
1598 f_ceil(VALUE x)
1600 if (RB_INTEGER_TYPE_P(x))
1601 return x;
1602 if (RB_FLOAT_TYPE_P(x))
1603 return rb_float_ceil(x, 0);
1605 return rb_funcall(x, id_ceil, 0);
1608 #define id_quo idQuo
1609 static VALUE
1610 f_quo(VALUE x, VALUE y)
1612 if (RB_INTEGER_TYPE_P(x))
1613 return rb_int_div(x, y);
1614 if (RB_FLOAT_TYPE_P(x))
1615 return DBL2NUM(RFLOAT_VALUE(x) / RFLOAT_VALUE(y));
1617 return rb_funcallv(x, id_quo, 1, &y);
1620 #define f_reciprocal(x) f_quo(ONE, (x))
1623 The algorithm here is the method described in CLISP. Bruno Haible has
1624 graciously given permission to use this algorithm. He says, "You can use
1625 it, if you present the following explanation of the algorithm."
1627 Algorithm (recursively presented):
1628 If x is a rational number, return x.
1629 If x = 0.0, return 0.
1630 If x < 0.0, return (- (rationalize (- x))).
1631 If x > 0.0:
1632 Call (integer-decode-float x). It returns a m,e,s=1 (mantissa,
1633 exponent, sign).
1634 If m = 0 or e >= 0: return x = m*2^e.
1635 Search a rational number between a = (m-1/2)*2^e and b = (m+1/2)*2^e
1636 with smallest possible numerator and denominator.
1637 Note 1: If m is a power of 2, we ought to take a = (m-1/4)*2^e.
1638 But in this case the result will be x itself anyway, regardless of
1639 the choice of a. Therefore we can simply ignore this case.
1640 Note 2: At first, we need to consider the closed interval [a,b].
1641 but since a and b have the denominator 2^(|e|+1) whereas x itself
1642 has a denominator <= 2^|e|, we can restrict the search to the open
1643 interval (a,b).
1644 So, for given a and b (0 < a < b) we are searching a rational number
1645 y with a <= y <= b.
1646 Recursive algorithm fraction_between(a,b):
1647 c := (ceiling a)
1648 if c < b
1649 then return c ; because a <= c < b, c integer
1650 else
1651 ; a is not integer (otherwise we would have had c = a < b)
1652 k := c-1 ; k = floor(a), k < a < b <= k+1
1653 return y = k + 1/fraction_between(1/(b-k), 1/(a-k))
1654 ; note 1 <= 1/(b-k) < 1/(a-k)
1656 You can see that we are actually computing a continued fraction expansion.
1658 Algorithm (iterative):
1659 If x is rational, return x.
1660 Call (integer-decode-float x). It returns a m,e,s (mantissa,
1661 exponent, sign).
1662 If m = 0 or e >= 0, return m*2^e*s. (This includes the case x = 0.0.)
1663 Create rational numbers a := (2*m-1)*2^(e-1) and b := (2*m+1)*2^(e-1)
1664 (positive and already in lowest terms because the denominator is a
1665 power of two and the numerator is odd).
1666 Start a continued fraction expansion
1667 p[-1] := 0, p[0] := 1, q[-1] := 1, q[0] := 0, i := 0.
1668 Loop
1669 c := (ceiling a)
1670 if c >= b
1671 then k := c-1, partial_quotient(k), (a,b) := (1/(b-k),1/(a-k)),
1672 goto Loop
1673 finally partial_quotient(c).
1674 Here partial_quotient(c) denotes the iteration
1675 i := i+1, p[i] := c*p[i-1]+p[i-2], q[i] := c*q[i-1]+q[i-2].
1676 At the end, return s * (p[i]/q[i]).
1677 This rational number is already in lowest terms because
1678 p[i]*q[i-1]-p[i-1]*q[i] = (-1)^i.
1681 static void
1682 nurat_rationalize_internal(VALUE a, VALUE b, VALUE *p, VALUE *q)
1684 VALUE c, k, t, p0, p1, p2, q0, q1, q2;
1686 p0 = ZERO;
1687 p1 = ONE;
1688 q0 = ONE;
1689 q1 = ZERO;
1691 while (1) {
1692 c = f_ceil(a);
1693 if (f_lt_p(c, b))
1694 break;
1695 k = f_sub(c, ONE);
1696 p2 = f_add(f_mul(k, p1), p0);
1697 q2 = f_add(f_mul(k, q1), q0);
1698 t = f_reciprocal(f_sub(b, k));
1699 b = f_reciprocal(f_sub(a, k));
1700 a = t;
1701 p0 = p1;
1702 q0 = q1;
1703 p1 = p2;
1704 q1 = q2;
1706 *p = f_add(f_mul(c, p1), p0);
1707 *q = f_add(f_mul(c, q1), q0);
1711 * call-seq:
1712 * rat.rationalize -> self
1713 * rat.rationalize(eps) -> rational
1715 * Returns a simpler approximation of the value if the optional
1716 * argument +eps+ is given (rat-|eps| <= result <= rat+|eps|),
1717 * self otherwise.
1719 * r = Rational(5033165, 16777216)
1720 * r.rationalize #=> (5033165/16777216)
1721 * r.rationalize(Rational('0.01')) #=> (3/10)
1722 * r.rationalize(Rational('0.1')) #=> (1/3)
1724 static VALUE
1725 nurat_rationalize(int argc, VALUE *argv, VALUE self)
1727 VALUE e, a, b, p, q;
1728 VALUE rat = self;
1729 get_dat1(self);
1731 if (rb_check_arity(argc, 0, 1) == 0)
1732 return self;
1734 e = f_abs(argv[0]);
1736 if (INT_NEGATIVE_P(dat->num)) {
1737 rat = f_rational_new2(RBASIC_CLASS(self), rb_int_uminus(dat->num), dat->den);
1740 a = FIXNUM_ZERO_P(e) ? rat : rb_rational_minus(rat, e);
1741 b = FIXNUM_ZERO_P(e) ? rat : rb_rational_plus(rat, e);
1743 if (f_eqeq_p(a, b))
1744 return self;
1746 nurat_rationalize_internal(a, b, &p, &q);
1747 if (rat != self) {
1748 RATIONAL_SET_NUM(rat, rb_int_uminus(p));
1749 RATIONAL_SET_DEN(rat, q);
1750 return rat;
1752 return f_rational_new2(CLASS_OF(self), p, q);
1755 /* :nodoc: */
1756 st_index_t
1757 rb_rational_hash(VALUE self)
1759 st_index_t v, h[2];
1760 VALUE n;
1762 get_dat1(self);
1763 n = rb_hash(dat->num);
1764 h[0] = NUM2LONG(n);
1765 n = rb_hash(dat->den);
1766 h[1] = NUM2LONG(n);
1767 v = rb_memhash(h, sizeof(h));
1768 return v;
1771 static VALUE
1772 nurat_hash(VALUE self)
1774 return ST2FIX(rb_rational_hash(self));
1778 static VALUE
1779 f_format(VALUE self, VALUE (*func)(VALUE))
1781 VALUE s;
1782 get_dat1(self);
1784 s = (*func)(dat->num);
1785 rb_str_cat2(s, "/");
1786 rb_str_concat(s, (*func)(dat->den));
1788 return s;
1792 * call-seq:
1793 * rat.to_s -> string
1795 * Returns the value as a string.
1797 * Rational(2).to_s #=> "2/1"
1798 * Rational(-8, 6).to_s #=> "-4/3"
1799 * Rational('1/2').to_s #=> "1/2"
1801 static VALUE
1802 nurat_to_s(VALUE self)
1804 return f_format(self, f_to_s);
1808 * call-seq:
1809 * rat.inspect -> string
1811 * Returns the value as a string for inspection.
1813 * Rational(2).inspect #=> "(2/1)"
1814 * Rational(-8, 6).inspect #=> "(-4/3)"
1815 * Rational('1/2').inspect #=> "(1/2)"
1817 static VALUE
1818 nurat_inspect(VALUE self)
1820 VALUE s;
1822 s = rb_usascii_str_new2("(");
1823 rb_str_concat(s, f_format(self, f_inspect));
1824 rb_str_cat2(s, ")");
1826 return s;
1829 /* :nodoc: */
1830 static VALUE
1831 nurat_dumper(VALUE self)
1833 return self;
1836 /* :nodoc: */
1837 static VALUE
1838 nurat_loader(VALUE self, VALUE a)
1840 VALUE num, den;
1842 get_dat1(self);
1843 num = rb_ivar_get(a, id_i_num);
1844 den = rb_ivar_get(a, id_i_den);
1845 nurat_int_check(num);
1846 nurat_int_check(den);
1847 nurat_canonicalize(&num, &den);
1848 RATIONAL_SET_NUM((VALUE)dat, num);
1849 RATIONAL_SET_DEN((VALUE)dat, den);
1850 OBJ_FREEZE(self);
1852 return self;
1855 /* :nodoc: */
1856 static VALUE
1857 nurat_marshal_dump(VALUE self)
1859 VALUE a;
1860 get_dat1(self);
1862 a = rb_assoc_new(dat->num, dat->den);
1863 rb_copy_generic_ivar(a, self);
1864 return a;
1867 /* :nodoc: */
1868 static VALUE
1869 nurat_marshal_load(VALUE self, VALUE a)
1871 VALUE num, den;
1873 rb_check_frozen(self);
1875 Check_Type(a, T_ARRAY);
1876 if (RARRAY_LEN(a) != 2)
1877 rb_raise(rb_eArgError, "marshaled rational must have an array whose length is 2 but %ld", RARRAY_LEN(a));
1879 num = RARRAY_AREF(a, 0);
1880 den = RARRAY_AREF(a, 1);
1881 nurat_int_check(num);
1882 nurat_int_check(den);
1883 nurat_canonicalize(&num, &den);
1884 rb_ivar_set(self, id_i_num, num);
1885 rb_ivar_set(self, id_i_den, den);
1887 return self;
1890 VALUE
1891 rb_rational_reciprocal(VALUE x)
1893 get_dat1(x);
1894 return nurat_convert(CLASS_OF(x), dat->den, dat->num, FALSE);
1898 * call-seq:
1899 * int.gcd(other_int) -> integer
1901 * Returns the greatest common divisor of the two integers.
1902 * The result is always positive. 0.gcd(x) and x.gcd(0) return x.abs.
1904 * 36.gcd(60) #=> 12
1905 * 2.gcd(2) #=> 2
1906 * 3.gcd(-7) #=> 1
1907 * ((1<<31)-1).gcd((1<<61)-1) #=> 1
1909 VALUE
1910 rb_gcd(VALUE self, VALUE other)
1912 other = nurat_int_value(other);
1913 return f_gcd(self, other);
1917 * call-seq:
1918 * int.lcm(other_int) -> integer
1920 * Returns the least common multiple of the two integers.
1921 * The result is always positive. 0.lcm(x) and x.lcm(0) return zero.
1923 * 36.lcm(60) #=> 180
1924 * 2.lcm(2) #=> 2
1925 * 3.lcm(-7) #=> 21
1926 * ((1<<31)-1).lcm((1<<61)-1) #=> 4951760154835678088235319297
1928 VALUE
1929 rb_lcm(VALUE self, VALUE other)
1931 other = nurat_int_value(other);
1932 return f_lcm(self, other);
1936 * call-seq:
1937 * int.gcdlcm(other_int) -> array
1939 * Returns an array with the greatest common divisor and
1940 * the least common multiple of the two integers, [gcd, lcm].
1942 * 36.gcdlcm(60) #=> [12, 180]
1943 * 2.gcdlcm(2) #=> [2, 2]
1944 * 3.gcdlcm(-7) #=> [1, 21]
1945 * ((1<<31)-1).gcdlcm((1<<61)-1) #=> [1, 4951760154835678088235319297]
1947 VALUE
1948 rb_gcdlcm(VALUE self, VALUE other)
1950 other = nurat_int_value(other);
1951 return rb_assoc_new(f_gcd(self, other), f_lcm(self, other));
1954 VALUE
1955 rb_rational_raw(VALUE x, VALUE y)
1957 if (! RB_INTEGER_TYPE_P(x))
1958 x = rb_to_int(x);
1959 if (! RB_INTEGER_TYPE_P(y))
1960 y = rb_to_int(y);
1961 if (INT_NEGATIVE_P(y)) {
1962 x = rb_int_uminus(x);
1963 y = rb_int_uminus(y);
1965 return nurat_s_new_internal(rb_cRational, x, y);
1968 VALUE
1969 rb_rational_new(VALUE x, VALUE y)
1971 return nurat_s_canonicalize_internal(rb_cRational, x, y);
1974 VALUE
1975 rb_Rational(VALUE x, VALUE y)
1977 VALUE a[2];
1978 a[0] = x;
1979 a[1] = y;
1980 return nurat_s_convert(2, a, rb_cRational);
1983 VALUE
1984 rb_rational_num(VALUE rat)
1986 return nurat_numerator(rat);
1989 VALUE
1990 rb_rational_den(VALUE rat)
1992 return nurat_denominator(rat);
1995 #define id_numerator rb_intern("numerator")
1996 #define f_numerator(x) rb_funcall((x), id_numerator, 0)
1998 #define id_denominator rb_intern("denominator")
1999 #define f_denominator(x) rb_funcall((x), id_denominator, 0)
2001 #define id_to_r idTo_r
2002 #define f_to_r(x) rb_funcall((x), id_to_r, 0)
2005 * call-seq:
2006 * num.numerator -> integer
2008 * Returns the numerator.
2010 static VALUE
2011 numeric_numerator(VALUE self)
2013 return f_numerator(f_to_r(self));
2017 * call-seq:
2018 * num.denominator -> integer
2020 * Returns the denominator (always positive).
2022 static VALUE
2023 numeric_denominator(VALUE self)
2025 return f_denominator(f_to_r(self));
2030 * call-seq:
2031 * num.quo(int_or_rat) -> rat
2032 * num.quo(flo) -> flo
2034 * Returns the most exact division (rational for integers, float for floats).
2037 VALUE
2038 rb_numeric_quo(VALUE x, VALUE y)
2040 if (RB_TYPE_P(x, T_COMPLEX)) {
2041 return rb_complex_div(x, y);
2044 if (RB_FLOAT_TYPE_P(y)) {
2045 return rb_funcallv(x, idFdiv, 1, &y);
2048 x = rb_convert_type(x, T_RATIONAL, "Rational", "to_r");
2049 return rb_rational_div(x, y);
2052 VALUE
2053 rb_rational_canonicalize(VALUE x)
2055 if (RB_TYPE_P(x, T_RATIONAL)) {
2056 get_dat1(x);
2057 if (f_one_p(dat->den)) return dat->num;
2059 return x;
2063 * call-seq:
2064 * flo.numerator -> integer
2066 * Returns the numerator. The result is machine dependent.
2068 * n = 0.3.numerator #=> 5404319552844595
2069 * d = 0.3.denominator #=> 18014398509481984
2070 * n.fdiv(d) #=> 0.3
2072 * See also Float#denominator.
2074 VALUE
2075 rb_float_numerator(VALUE self)
2077 double d = RFLOAT_VALUE(self);
2078 VALUE r;
2079 if (!isfinite(d))
2080 return self;
2081 r = float_to_r(self);
2082 return nurat_numerator(r);
2086 * call-seq:
2087 * flo.denominator -> integer
2089 * Returns the denominator (always positive). The result is machine
2090 * dependent.
2092 * See also Float#numerator.
2094 VALUE
2095 rb_float_denominator(VALUE self)
2097 double d = RFLOAT_VALUE(self);
2098 VALUE r;
2099 if (!isfinite(d))
2100 return INT2FIX(1);
2101 r = float_to_r(self);
2102 return nurat_denominator(r);
2106 * call-seq:
2107 * to_r -> (0/1)
2109 * Returns zero as a Rational:
2111 * nil.to_r # => (0/1)
2114 static VALUE
2115 nilclass_to_r(VALUE self)
2117 return rb_rational_new1(INT2FIX(0));
2121 * call-seq:
2122 * rationalize(eps = nil) -> (0/1)
2124 * Returns zero as a Rational:
2126 * nil.rationalize # => (0/1)
2128 * Argument +eps+ is ignored.
2131 static VALUE
2132 nilclass_rationalize(int argc, VALUE *argv, VALUE self)
2134 rb_check_arity(argc, 0, 1);
2135 return nilclass_to_r(self);
2139 * call-seq:
2140 * int.to_r -> rational
2142 * Returns the value as a rational.
2144 * 1.to_r #=> (1/1)
2145 * (1<<64).to_r #=> (18446744073709551616/1)
2147 static VALUE
2148 integer_to_r(VALUE self)
2150 return rb_rational_new1(self);
2154 * call-seq:
2155 * int.rationalize([eps]) -> rational
2157 * Returns the value as a rational. The optional argument +eps+ is
2158 * always ignored.
2160 static VALUE
2161 integer_rationalize(int argc, VALUE *argv, VALUE self)
2163 rb_check_arity(argc, 0, 1);
2164 return integer_to_r(self);
2167 static void
2168 float_decode_internal(VALUE self, VALUE *rf, int *n)
2170 double f;
2172 f = frexp(RFLOAT_VALUE(self), n);
2173 f = ldexp(f, DBL_MANT_DIG);
2174 *n -= DBL_MANT_DIG;
2175 *rf = rb_dbl2big(f);
2179 * call-seq:
2180 * flt.to_r -> rational
2182 * Returns the value as a rational.
2184 * 2.0.to_r #=> (2/1)
2185 * 2.5.to_r #=> (5/2)
2186 * -0.75.to_r #=> (-3/4)
2187 * 0.0.to_r #=> (0/1)
2188 * 0.3.to_r #=> (5404319552844595/18014398509481984)
2190 * NOTE: 0.3.to_r isn't the same as "0.3".to_r. The latter is
2191 * equivalent to "3/10".to_r, but the former isn't so.
2193 * 0.3.to_r == 3/10r #=> false
2194 * "0.3".to_r == 3/10r #=> true
2196 * See also Float#rationalize.
2198 static VALUE
2199 float_to_r(VALUE self)
2201 VALUE f;
2202 int n;
2204 float_decode_internal(self, &f, &n);
2205 #if FLT_RADIX == 2
2206 if (n == 0)
2207 return rb_rational_new1(f);
2208 if (n > 0)
2209 return rb_rational_new1(rb_int_lshift(f, INT2FIX(n)));
2210 n = -n;
2211 return rb_rational_new2(f, rb_int_lshift(ONE, INT2FIX(n)));
2212 #else
2213 f = rb_int_mul(f, rb_int_pow(INT2FIX(FLT_RADIX), n));
2214 if (RB_TYPE_P(f, T_RATIONAL))
2215 return f;
2216 return rb_rational_new1(f);
2217 #endif
2220 VALUE
2221 rb_flt_rationalize_with_prec(VALUE flt, VALUE prec)
2223 VALUE e, a, b, p, q;
2225 e = f_abs(prec);
2226 a = f_sub(flt, e);
2227 b = f_add(flt, e);
2229 if (f_eqeq_p(a, b))
2230 return float_to_r(flt);
2232 nurat_rationalize_internal(a, b, &p, &q);
2233 return rb_rational_new2(p, q);
2236 VALUE
2237 rb_flt_rationalize(VALUE flt)
2239 VALUE a, b, f, p, q, den;
2240 int n;
2242 float_decode_internal(flt, &f, &n);
2243 if (INT_ZERO_P(f) || n >= 0)
2244 return rb_rational_new1(rb_int_lshift(f, INT2FIX(n)));
2247 VALUE radix_times_f;
2249 radix_times_f = rb_int_mul(INT2FIX(FLT_RADIX), f);
2250 #if FLT_RADIX == 2 && 0
2251 den = rb_int_lshift(ONE, INT2FIX(1-n));
2252 #else
2253 den = rb_int_positive_pow(FLT_RADIX, 1-n);
2254 #endif
2256 a = rb_int_minus(radix_times_f, INT2FIX(FLT_RADIX - 1));
2257 b = rb_int_plus(radix_times_f, INT2FIX(FLT_RADIX - 1));
2260 if (f_eqeq_p(a, b))
2261 return float_to_r(flt);
2263 a = rb_rational_new2(a, den);
2264 b = rb_rational_new2(b, den);
2265 nurat_rationalize_internal(a, b, &p, &q);
2266 return rb_rational_new2(p, q);
2270 * call-seq:
2271 * flt.rationalize([eps]) -> rational
2273 * Returns a simpler approximation of the value (flt-|eps| <= result
2274 * <= flt+|eps|). If the optional argument +eps+ is not given,
2275 * it will be chosen automatically.
2277 * 0.3.rationalize #=> (3/10)
2278 * 1.333.rationalize #=> (1333/1000)
2279 * 1.333.rationalize(0.01) #=> (4/3)
2281 * See also Float#to_r.
2283 static VALUE
2284 float_rationalize(int argc, VALUE *argv, VALUE self)
2286 double d = RFLOAT_VALUE(self);
2287 VALUE rat;
2288 int neg = d < 0.0;
2289 if (neg) self = DBL2NUM(-d);
2291 if (rb_check_arity(argc, 0, 1)) {
2292 rat = rb_flt_rationalize_with_prec(self, argv[0]);
2294 else {
2295 rat = rb_flt_rationalize(self);
2297 if (neg) RATIONAL_SET_NUM(rat, rb_int_uminus(RRATIONAL(rat)->num));
2298 return rat;
2301 inline static int
2302 issign(int c)
2304 return (c == '-' || c == '+');
2307 static int
2308 read_sign(const char **s, const char *const e)
2310 int sign = '?';
2312 if (*s < e && issign(**s)) {
2313 sign = **s;
2314 (*s)++;
2316 return sign;
2319 inline static int
2320 islettere(int c)
2322 return (c == 'e' || c == 'E');
2325 static VALUE
2326 negate_num(VALUE num)
2328 if (FIXNUM_P(num)) {
2329 return rb_int_uminus(num);
2331 else {
2332 BIGNUM_NEGATE(num);
2333 return rb_big_norm(num);
2337 static int
2338 read_num(const char **s, const char *const end, VALUE *num, VALUE *nexp)
2340 VALUE fp = ONE, exp, fn = ZERO, n = ZERO;
2341 int expsign = 0, ok = 0;
2342 char *e;
2344 *nexp = ZERO;
2345 *num = ZERO;
2346 if (*s < end && **s != '.') {
2347 n = rb_int_parse_cstr(*s, end-*s, &e, NULL,
2348 10, RB_INT_PARSE_UNDERSCORE);
2349 if (NIL_P(n))
2350 return 0;
2351 *s = e;
2352 *num = n;
2353 ok = 1;
2356 if (*s < end && **s == '.') {
2357 size_t count = 0;
2359 (*s)++;
2360 fp = rb_int_parse_cstr(*s, end-*s, &e, &count,
2361 10, RB_INT_PARSE_UNDERSCORE);
2362 if (NIL_P(fp))
2363 return 1;
2364 *s = e;
2366 VALUE l = f_expt10(*nexp = SIZET2NUM(count));
2367 n = n == ZERO ? fp : rb_int_plus(rb_int_mul(*num, l), fp);
2368 *num = n;
2369 fn = SIZET2NUM(count);
2371 ok = 1;
2374 if (ok && *s + 1 < end && islettere(**s)) {
2375 (*s)++;
2376 expsign = read_sign(s, end);
2377 exp = rb_int_parse_cstr(*s, end-*s, &e, NULL,
2378 10, RB_INT_PARSE_UNDERSCORE);
2379 if (NIL_P(exp))
2380 return 1;
2381 *s = e;
2382 if (exp != ZERO) {
2383 if (expsign == '-') {
2384 if (fn != ZERO) exp = rb_int_plus(exp, fn);
2386 else {
2387 if (fn != ZERO) exp = rb_int_minus(exp, fn);
2388 exp = negate_num(exp);
2390 *nexp = exp;
2394 return ok;
2397 inline static const char *
2398 skip_ws(const char *s, const char *e)
2400 while (s < e && isspace((unsigned char)*s))
2401 ++s;
2402 return s;
2405 static VALUE
2406 parse_rat(const char *s, const char *const e, int strict, int raise)
2408 int sign;
2409 VALUE num, den, nexp, dexp;
2411 s = skip_ws(s, e);
2412 sign = read_sign(&s, e);
2414 if (!read_num(&s, e, &num, &nexp)) {
2415 if (strict) return Qnil;
2416 return nurat_s_alloc(rb_cRational);
2418 den = ONE;
2419 if (s < e && *s == '/') {
2420 s++;
2421 if (!read_num(&s, e, &den, &dexp)) {
2422 if (strict) return Qnil;
2423 den = ONE;
2425 else if (den == ZERO) {
2426 if (!raise) return Qnil;
2427 rb_num_zerodiv();
2429 else if (strict && skip_ws(s, e) != e) {
2430 return Qnil;
2432 else {
2433 nexp = rb_int_minus(nexp, dexp);
2434 nurat_reduce(&num, &den);
2437 else if (strict && skip_ws(s, e) != e) {
2438 return Qnil;
2441 if (nexp != ZERO) {
2442 if (INT_NEGATIVE_P(nexp)) {
2443 VALUE mul;
2444 if (FIXNUM_P(nexp)) {
2445 mul = f_expt10(LONG2NUM(-FIX2LONG(nexp)));
2446 if (! RB_FLOAT_TYPE_P(mul)) {
2447 num = rb_int_mul(num, mul);
2448 goto reduce;
2451 return sign == '-' ? DBL2NUM(-HUGE_VAL) : DBL2NUM(HUGE_VAL);
2453 else {
2454 VALUE div;
2455 if (FIXNUM_P(nexp)) {
2456 div = f_expt10(nexp);
2457 if (! RB_FLOAT_TYPE_P(div)) {
2458 den = rb_int_mul(den, div);
2459 goto reduce;
2462 return sign == '-' ? DBL2NUM(-0.0) : DBL2NUM(+0.0);
2464 reduce:
2465 nurat_reduce(&num, &den);
2468 if (sign == '-') {
2469 num = negate_num(num);
2472 return rb_rational_raw(num, den);
2475 static VALUE
2476 string_to_r_strict(VALUE self, int raise)
2478 VALUE num;
2480 rb_must_asciicompat(self);
2482 num = parse_rat(RSTRING_PTR(self), RSTRING_END(self), 1, raise);
2483 if (NIL_P(num)) {
2484 if (!raise) return Qnil;
2485 rb_raise(rb_eArgError, "invalid value for convert(): %+"PRIsVALUE,
2486 self);
2489 if (RB_FLOAT_TYPE_P(num) && !FLOAT_ZERO_P(num)) {
2490 if (!raise) return Qnil;
2491 rb_raise(rb_eFloatDomainError, "Infinity");
2493 return num;
2497 * call-seq:
2498 * str.to_r -> rational
2500 * Returns the result of interpreting leading characters in +str+
2501 * as a rational. Leading whitespace and extraneous characters
2502 * past the end of a valid number are ignored.
2503 * Digit sequences can be separated by an underscore.
2504 * If there is not a valid number at the start of +str+,
2505 * zero is returned. This method never raises an exception.
2507 * ' 2 '.to_r #=> (2/1)
2508 * '300/2'.to_r #=> (150/1)
2509 * '-9.2'.to_r #=> (-46/5)
2510 * '-9.2e2'.to_r #=> (-920/1)
2511 * '1_234_567'.to_r #=> (1234567/1)
2512 * '21 June 09'.to_r #=> (21/1)
2513 * '21/06/09'.to_r #=> (7/2)
2514 * 'BWV 1079'.to_r #=> (0/1)
2516 * NOTE: "0.3".to_r isn't the same as 0.3.to_r. The former is
2517 * equivalent to "3/10".to_r, but the latter isn't so.
2519 * "0.3".to_r == 3/10r #=> true
2520 * 0.3.to_r == 3/10r #=> false
2522 * See also Kernel#Rational.
2524 static VALUE
2525 string_to_r(VALUE self)
2527 VALUE num;
2529 rb_must_asciicompat(self);
2531 num = parse_rat(RSTRING_PTR(self), RSTRING_END(self), 0, TRUE);
2533 if (RB_FLOAT_TYPE_P(num) && !FLOAT_ZERO_P(num))
2534 rb_raise(rb_eFloatDomainError, "Infinity");
2535 return num;
2538 VALUE
2539 rb_cstr_to_rat(const char *s, int strict) /* for complex's internal */
2541 VALUE num;
2543 num = parse_rat(s, s + strlen(s), strict, TRUE);
2545 if (RB_FLOAT_TYPE_P(num) && !FLOAT_ZERO_P(num))
2546 rb_raise(rb_eFloatDomainError, "Infinity");
2547 return num;
2550 static VALUE
2551 to_rational(VALUE val)
2553 return rb_convert_type_with_id(val, T_RATIONAL, "Rational", idTo_r);
2556 static VALUE
2557 nurat_convert(VALUE klass, VALUE numv, VALUE denv, int raise)
2559 VALUE a1 = numv, a2 = denv;
2560 int state;
2562 RUBY_ASSERT(!UNDEF_P(a1));
2564 if (NIL_P(a1) || NIL_P(a2)) {
2565 if (!raise) return Qnil;
2566 rb_raise(rb_eTypeError, "can't convert nil into Rational");
2569 if (RB_TYPE_P(a1, T_COMPLEX)) {
2570 if (k_exact_zero_p(RCOMPLEX(a1)->imag))
2571 a1 = RCOMPLEX(a1)->real;
2574 if (RB_TYPE_P(a2, T_COMPLEX)) {
2575 if (k_exact_zero_p(RCOMPLEX(a2)->imag))
2576 a2 = RCOMPLEX(a2)->real;
2579 if (RB_INTEGER_TYPE_P(a1)) {
2580 // nothing to do
2582 else if (RB_FLOAT_TYPE_P(a1)) {
2583 a1 = float_to_r(a1);
2585 else if (RB_TYPE_P(a1, T_RATIONAL)) {
2586 // nothing to do
2588 else if (RB_TYPE_P(a1, T_STRING)) {
2589 a1 = string_to_r_strict(a1, raise);
2590 if (!raise && NIL_P(a1)) return Qnil;
2592 else if (!rb_respond_to(a1, idTo_r)) {
2593 VALUE tmp = rb_protect(rb_check_to_int, a1, NULL);
2594 rb_set_errinfo(Qnil);
2595 if (!NIL_P(tmp)) {
2596 a1 = tmp;
2600 if (RB_INTEGER_TYPE_P(a2)) {
2601 // nothing to do
2603 else if (RB_FLOAT_TYPE_P(a2)) {
2604 a2 = float_to_r(a2);
2606 else if (RB_TYPE_P(a2, T_RATIONAL)) {
2607 // nothing to do
2609 else if (RB_TYPE_P(a2, T_STRING)) {
2610 a2 = string_to_r_strict(a2, raise);
2611 if (!raise && NIL_P(a2)) return Qnil;
2613 else if (!UNDEF_P(a2) && !rb_respond_to(a2, idTo_r)) {
2614 VALUE tmp = rb_protect(rb_check_to_int, a2, NULL);
2615 rb_set_errinfo(Qnil);
2616 if (!NIL_P(tmp)) {
2617 a2 = tmp;
2621 if (RB_TYPE_P(a1, T_RATIONAL)) {
2622 if (UNDEF_P(a2) || (k_exact_one_p(a2)))
2623 return a1;
2626 if (UNDEF_P(a2)) {
2627 if (!RB_INTEGER_TYPE_P(a1)) {
2628 if (!raise) {
2629 VALUE result = rb_protect(to_rational, a1, NULL);
2630 rb_set_errinfo(Qnil);
2631 return result;
2633 return to_rational(a1);
2636 else {
2637 if (!k_numeric_p(a1)) {
2638 if (!raise) {
2639 a1 = rb_protect(to_rational, a1, &state);
2640 if (state) {
2641 rb_set_errinfo(Qnil);
2642 return Qnil;
2645 else {
2646 a1 = rb_check_convert_type_with_id(a1, T_RATIONAL, "Rational", idTo_r);
2649 if (!k_numeric_p(a2)) {
2650 if (!raise) {
2651 a2 = rb_protect(to_rational, a2, &state);
2652 if (state) {
2653 rb_set_errinfo(Qnil);
2654 return Qnil;
2657 else {
2658 a2 = rb_check_convert_type_with_id(a2, T_RATIONAL, "Rational", idTo_r);
2661 if ((k_numeric_p(a1) && k_numeric_p(a2)) &&
2662 (!f_integer_p(a1) || !f_integer_p(a2))) {
2663 VALUE tmp = rb_protect(to_rational, a1, &state);
2664 if (!state) {
2665 a1 = tmp;
2667 else {
2668 rb_set_errinfo(Qnil);
2670 return f_div(a1, a2);
2674 a1 = nurat_int_value(a1);
2676 if (UNDEF_P(a2)) {
2677 a2 = ONE;
2679 else if (!k_integer_p(a2) && !raise) {
2680 return Qnil;
2682 else {
2683 a2 = nurat_int_value(a2);
2687 return nurat_s_canonicalize_internal(klass, a1, a2);
2690 static VALUE
2691 nurat_s_convert(int argc, VALUE *argv, VALUE klass)
2693 VALUE a1, a2;
2695 if (rb_scan_args(argc, argv, "11", &a1, &a2) == 1) {
2696 a2 = Qundef;
2699 return nurat_convert(klass, a1, a2, TRUE);
2703 * A rational number can be represented as a pair of integer numbers:
2704 * a/b (b>0), where a is the numerator and b is the denominator.
2705 * Integer a equals rational a/1 mathematically.
2707 * You can create a \Rational object explicitly with:
2709 * - A {rational literal}[rdoc-ref:syntax/literals.rdoc@Rational+Literals].
2711 * You can convert certain objects to Rationals with:
2713 * - \Method #Rational.
2715 * Examples
2717 * Rational(1) #=> (1/1)
2718 * Rational(2, 3) #=> (2/3)
2719 * Rational(4, -6) #=> (-2/3) # Reduced.
2720 * 3.to_r #=> (3/1)
2721 * 2/3r #=> (2/3)
2723 * You can also create rational objects from floating-point numbers or
2724 * strings.
2726 * Rational(0.3) #=> (5404319552844595/18014398509481984)
2727 * Rational('0.3') #=> (3/10)
2728 * Rational('2/3') #=> (2/3)
2730 * 0.3.to_r #=> (5404319552844595/18014398509481984)
2731 * '0.3'.to_r #=> (3/10)
2732 * '2/3'.to_r #=> (2/3)
2733 * 0.3.rationalize #=> (3/10)
2735 * A rational object is an exact number, which helps you to write
2736 * programs without any rounding errors.
2738 * 10.times.inject(0) {|t| t + 0.1 } #=> 0.9999999999999999
2739 * 10.times.inject(0) {|t| t + Rational('0.1') } #=> (1/1)
2741 * However, when an expression includes an inexact component (numerical value
2742 * or operation), it will produce an inexact result.
2744 * Rational(10) / 3 #=> (10/3)
2745 * Rational(10) / 3.0 #=> 3.3333333333333335
2747 * Rational(-8) ** Rational(1, 3)
2748 * #=> (1.0000000000000002+1.7320508075688772i)
2750 void
2751 Init_Rational(void)
2753 VALUE compat;
2754 id_abs = rb_intern_const("abs");
2755 id_integer_p = rb_intern_const("integer?");
2756 id_i_num = rb_intern_const("@numerator");
2757 id_i_den = rb_intern_const("@denominator");
2759 rb_cRational = rb_define_class("Rational", rb_cNumeric);
2761 rb_define_alloc_func(rb_cRational, nurat_s_alloc);
2762 rb_undef_method(CLASS_OF(rb_cRational), "allocate");
2764 rb_undef_method(CLASS_OF(rb_cRational), "new");
2766 rb_define_global_function("Rational", nurat_f_rational, -1);
2768 rb_define_method(rb_cRational, "numerator", nurat_numerator, 0);
2769 rb_define_method(rb_cRational, "denominator", nurat_denominator, 0);
2771 rb_define_method(rb_cRational, "-@", rb_rational_uminus, 0);
2772 rb_define_method(rb_cRational, "+", rb_rational_plus, 1);
2773 rb_define_method(rb_cRational, "-", rb_rational_minus, 1);
2774 rb_define_method(rb_cRational, "*", rb_rational_mul, 1);
2775 rb_define_method(rb_cRational, "/", rb_rational_div, 1);
2776 rb_define_method(rb_cRational, "quo", rb_rational_div, 1);
2777 rb_define_method(rb_cRational, "fdiv", nurat_fdiv, 1);
2778 rb_define_method(rb_cRational, "**", nurat_expt, 1);
2780 rb_define_method(rb_cRational, "<=>", rb_rational_cmp, 1);
2781 rb_define_method(rb_cRational, "==", nurat_eqeq_p, 1);
2782 rb_define_method(rb_cRational, "coerce", nurat_coerce, 1);
2784 rb_define_method(rb_cRational, "positive?", nurat_positive_p, 0);
2785 rb_define_method(rb_cRational, "negative?", nurat_negative_p, 0);
2786 rb_define_method(rb_cRational, "abs", rb_rational_abs, 0);
2787 rb_define_method(rb_cRational, "magnitude", rb_rational_abs, 0);
2789 rb_define_method(rb_cRational, "floor", nurat_floor_n, -1);
2790 rb_define_method(rb_cRational, "ceil", nurat_ceil_n, -1);
2791 rb_define_method(rb_cRational, "truncate", nurat_truncate_n, -1);
2792 rb_define_method(rb_cRational, "round", nurat_round_n, -1);
2794 rb_define_method(rb_cRational, "to_i", nurat_truncate, 0);
2795 rb_define_method(rb_cRational, "to_f", nurat_to_f, 0);
2796 rb_define_method(rb_cRational, "to_r", nurat_to_r, 0);
2797 rb_define_method(rb_cRational, "rationalize", nurat_rationalize, -1);
2799 rb_define_method(rb_cRational, "hash", nurat_hash, 0);
2801 rb_define_method(rb_cRational, "to_s", nurat_to_s, 0);
2802 rb_define_method(rb_cRational, "inspect", nurat_inspect, 0);
2804 rb_define_private_method(rb_cRational, "marshal_dump", nurat_marshal_dump, 0);
2805 /* :nodoc: */
2806 compat = rb_define_class_under(rb_cRational, "compatible", rb_cObject);
2807 rb_define_private_method(compat, "marshal_load", nurat_marshal_load, 1);
2808 rb_marshal_define_compat(rb_cRational, compat, nurat_dumper, nurat_loader);
2810 rb_define_method(rb_cInteger, "gcd", rb_gcd, 1);
2811 rb_define_method(rb_cInteger, "lcm", rb_lcm, 1);
2812 rb_define_method(rb_cInteger, "gcdlcm", rb_gcdlcm, 1);
2814 rb_define_method(rb_cNumeric, "numerator", numeric_numerator, 0);
2815 rb_define_method(rb_cNumeric, "denominator", numeric_denominator, 0);
2816 rb_define_method(rb_cNumeric, "quo", rb_numeric_quo, 1);
2818 rb_define_method(rb_cFloat, "numerator", rb_float_numerator, 0);
2819 rb_define_method(rb_cFloat, "denominator", rb_float_denominator, 0);
2821 rb_define_method(rb_cNilClass, "to_r", nilclass_to_r, 0);
2822 rb_define_method(rb_cNilClass, "rationalize", nilclass_rationalize, -1);
2823 rb_define_method(rb_cInteger, "to_r", integer_to_r, 0);
2824 rb_define_method(rb_cInteger, "rationalize", integer_rationalize, -1);
2825 rb_define_method(rb_cFloat, "to_r", float_to_r, 0);
2826 rb_define_method(rb_cFloat, "rationalize", float_rationalize, -1);
2828 rb_define_method(rb_cString, "to_r", string_to_r, 0);
2830 rb_define_private_method(CLASS_OF(rb_cRational), "convert", nurat_s_convert, -1);
2832 rb_provide("rational.so"); /* for backward compatibility */