Ruby 2.7.0p0(2019-12-25revision647ee6f091eafcce70ffb75ddf7e121e192ab217)

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