Ruby 2.7.6p219 (2022-04-12 revision c9c2245c0a25176072e02db9254f0e0c84c805cd)
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
35
36static 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
46static VALUE nurat_to_f(VALUE self);
47
48inline static VALUE
49f_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
58inline static VALUE
59f_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
68inline static int
69f_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 */
78inline static VALUE
79f_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
87inline static VALUE
88f_mul(VALUE x, VALUE y)
89{
91 return ZERO;
92 if (y == ONE) return x;
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
101inline static VALUE
102f_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
109inline static VALUE
110f_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
118inline static VALUE
119f_integer_p(VALUE x)
120{
121 return RB_INTEGER_TYPE_P(x);
122}
123
124inline static VALUE
125f_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
132inline static VALUE
133f_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
140inline static VALUE
141f_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
150inline static int
151f_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
166inline static int
167f_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
181inline static int
182f_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
199inline static int
200f_kind_of_p(VALUE x, VALUE c)
201{
202 return (int)rb_obj_is_kind_of(x, c);
203}
204
205inline static int
206k_numeric_p(VALUE x)
207{
208 return f_kind_of_p(x, rb_cNumeric);
209}
210
211inline static int
212k_integer_p(VALUE x)
213{
214 return RB_INTEGER_TYPE_P(x);
215}
216
217inline static int
218k_float_p(VALUE x)
219{
220 return RB_FLOAT_TYPE_P(x);
221}
222
223inline static int
224k_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
236VALUE
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
270inline static long
271i_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
311inline static VALUE
312f_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
343VALUE
345{
346 return f_gcd_normal(x, y);
347}
348
349inline static VALUE
350f_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
366inline static VALUE
367f_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
378inline static VALUE
379f_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
392inline static VALUE
393nurat_s_new_internal(VALUE klass, VALUE num, VALUE den)
394{
396
400
401 return (VALUE)obj;
402}
403
404static VALUE
405nurat_s_alloc(VALUE klass)
406{
407 return nurat_s_new_internal(klass, ZERO, ONE);
408}
409
410inline static VALUE
411f_rational_new_bang1(VALUE klass, VALUE x)
412{
413 return nurat_s_new_internal(klass, x, ONE);
414}
415
416#ifdef CANONICALIZATION_FOR_MATHN
417static int canonicalization = 0;
418
420nurat_canonicalization(int f)
421{
423}
424#else
425# define canonicalization 0
426#endif
427
428inline static void
429nurat_int_check(VALUE num)
430{
431 if (!RB_INTEGER_TYPE_P(num)) {
432 if (!k_numeric_p(num) || !f_integer_p(num))
433 rb_raise(rb_eTypeError, "not an integer");
434 }
435}
436
437inline static VALUE
438nurat_int_value(VALUE num)
439{
440 nurat_int_check(num);
441 if (!k_integer_p(num))
442 num = f_to_i(num);
443 return num;
444}
445
446static void
447nurat_canonicalize(VALUE *num, VALUE *den)
448{
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)) {
457 }
458}
459
460static void
461nurat_reduce(VALUE *x, VALUE *y)
462{
463 VALUE gcd;
464 if (*x == ONE || *y == ONE) return;
465 gcd = f_gcd(*x, *y);
466 *x = f_idiv(*x, gcd);
467 *y = f_idiv(*y, gcd);
468}
469
470inline static VALUE
471nurat_s_canonicalize_internal(VALUE klass, VALUE num, VALUE den)
472{
473 nurat_canonicalize(&num, &den);
474 nurat_reduce(&num, &den);
475
476 if (canonicalization && f_one_p(den))
477 return num;
478 return nurat_s_new_internal(klass, num, den);
479}
480
481inline static VALUE
482nurat_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
491static VALUE
492nurat_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
510inline static VALUE
511f_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
518inline static VALUE
519f_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
526static VALUE nurat_convert(VALUE klass, VALUE numv, VALUE denv, int raise);
527static 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 */
566static VALUE
567nurat_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 */
592static VALUE
593nurat_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 */
610static VALUE
611nurat_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 */
623VALUE
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
636inline static VALUE
637f_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
658inline static VALUE
659f_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
667inline static VALUE
668f_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
723static 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 */
736VALUE
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 */
777VALUE
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
806inline static VALUE
807f_muldiv(VALUE self, VALUE anum, VALUE aden, VALUE bnum, VALUE bden, int k)
808{
809 VALUE num, den;
810
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
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 */
873VALUE
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 */
915VALUE
917{
918 if (RB_INTEGER_TYPE_P(other)) {
919 if (f_zero_p(other))
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))
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 */
963static VALUE
964nurat_fdiv(VALUE self, VALUE other)
965{
966 VALUE div;
967 if (f_zero_p(other))
968 return rb_rational_div(self, rb_float_new(0.0));
969 if (FIXNUM_P(other) && other == LONG2FIX(1))
970 return nurat_to_f(self);
971 div = rb_rational_div(self, other);
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
979inline static VALUE
980f_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 */
1001VALUE
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)) {
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 */
1096VALUE
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 */
1148static VALUE
1149nurat_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: */
1190static VALUE
1191nurat_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 */
1221static VALUE
1222nurat_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 */
1234static VALUE
1235nurat_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
1254VALUE
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
1265static VALUE
1266nurat_floor(VALUE self)
1267{
1268 get_dat1(self);
1269 return rb_int_idiv(dat->num, dat->den);
1270}
1271
1272static VALUE
1273nurat_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 */
1293static VALUE
1294nurat_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
1302static VALUE
1303nurat_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
1326static VALUE
1327nurat_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
1351static VALUE
1352nurat_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
1378static VALUE
1379f_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 = rb_rational_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
1414VALUE
1415rb_rational_floor(VALUE self, int ndigits)
1416{
1417 if (ndigits == 0) {
1418 return nurat_floor(self);
1419 }
1420 else {
1421 VALUE n = INT2NUM(ndigits);
1422 return f_round_common(1, &n, self, nurat_floor);
1423 }
1424}
1425
1426/*
1427 * call-seq:
1428 * rat.floor([ndigits]) -> integer or rational
1429 *
1430 * Returns the largest number less than or equal to +rat+ with
1431 * a precision of +ndigits+ decimal digits (default: 0).
1432 *
1433 * When the precision is negative, the returned value is an integer
1434 * with at least <code>ndigits.abs</code> trailing zeros.
1435 *
1436 * Returns a rational when +ndigits+ is positive,
1437 * otherwise returns an integer.
1438 *
1439 * Rational(3).floor #=> 3
1440 * Rational(2, 3).floor #=> 0
1441 * Rational(-3, 2).floor #=> -2
1442 *
1443 * # decimal - 1 2 3 . 4 5 6
1444 * # ^ ^ ^ ^ ^ ^
1445 * # precision -3 -2 -1 0 +1 +2
1446 *
1447 * Rational('-123.456').floor(+1).to_f #=> -123.5
1448 * Rational('-123.456').floor(-1) #=> -130
1449 */
1450static VALUE
1451nurat_floor_n(int argc, VALUE *argv, VALUE self)
1452{
1453 return f_round_common(argc, argv, self, nurat_floor);
1454}
1455
1456/*
1457 * call-seq:
1458 * rat.ceil([ndigits]) -> integer or rational
1459 *
1460 * Returns the smallest number greater than or equal to +rat+ with
1461 * a precision of +ndigits+ decimal digits (default: 0).
1462 *
1463 * When the precision is negative, the returned value is an integer
1464 * with at least <code>ndigits.abs</code> trailing zeros.
1465 *
1466 * Returns a rational when +ndigits+ is positive,
1467 * otherwise returns an integer.
1468 *
1469 * Rational(3).ceil #=> 3
1470 * Rational(2, 3).ceil #=> 1
1471 * Rational(-3, 2).ceil #=> -1
1472 *
1473 * # decimal - 1 2 3 . 4 5 6
1474 * # ^ ^ ^ ^ ^ ^
1475 * # precision -3 -2 -1 0 +1 +2
1476 *
1477 * Rational('-123.456').ceil(+1).to_f #=> -123.4
1478 * Rational('-123.456').ceil(-1) #=> -120
1479 */
1480static VALUE
1481nurat_ceil_n(int argc, VALUE *argv, VALUE self)
1482{
1483 return f_round_common(argc, argv, self, nurat_ceil);
1484}
1485
1486/*
1487 * call-seq:
1488 * rat.truncate([ndigits]) -> integer or rational
1489 *
1490 * Returns +rat+ truncated (toward zero) to
1491 * a precision of +ndigits+ decimal digits (default: 0).
1492 *
1493 * When the precision is negative, the returned value is an integer
1494 * with at least <code>ndigits.abs</code> trailing zeros.
1495 *
1496 * Returns a rational when +ndigits+ is positive,
1497 * otherwise returns an integer.
1498 *
1499 * Rational(3).truncate #=> 3
1500 * Rational(2, 3).truncate #=> 0
1501 * Rational(-3, 2).truncate #=> -1
1502 *
1503 * # decimal - 1 2 3 . 4 5 6
1504 * # ^ ^ ^ ^ ^ ^
1505 * # precision -3 -2 -1 0 +1 +2
1506 *
1507 * Rational('-123.456').truncate(+1).to_f #=> -123.4
1508 * Rational('-123.456').truncate(-1) #=> -120
1509 */
1510static VALUE
1511nurat_truncate_n(int argc, VALUE *argv, VALUE self)
1512{
1513 return f_round_common(argc, argv, self, nurat_truncate);
1514}
1515
1516/*
1517 * call-seq:
1518 * rat.round([ndigits] [, half: mode]) -> integer or rational
1519 *
1520 * Returns +rat+ rounded to the nearest value with
1521 * a precision of +ndigits+ decimal digits (default: 0).
1522 *
1523 * When the precision is negative, the returned value is an integer
1524 * with at least <code>ndigits.abs</code> trailing zeros.
1525 *
1526 * Returns a rational when +ndigits+ is positive,
1527 * otherwise returns an integer.
1528 *
1529 * Rational(3).round #=> 3
1530 * Rational(2, 3).round #=> 1
1531 * Rational(-3, 2).round #=> -2
1532 *
1533 * # decimal - 1 2 3 . 4 5 6
1534 * # ^ ^ ^ ^ ^ ^
1535 * # precision -3 -2 -1 0 +1 +2
1536 *
1537 * Rational('-123.456').round(+1).to_f #=> -123.5
1538 * Rational('-123.456').round(-1) #=> -120
1539 *
1540 * The optional +half+ keyword argument is available
1541 * similar to Float#round.
1542 *
1543 * Rational(25, 100).round(1, half: :up) #=> (3/10)
1544 * Rational(25, 100).round(1, half: :down) #=> (1/5)
1545 * Rational(25, 100).round(1, half: :even) #=> (1/5)
1546 * Rational(35, 100).round(1, half: :up) #=> (2/5)
1547 * Rational(35, 100).round(1, half: :down) #=> (3/10)
1548 * Rational(35, 100).round(1, half: :even) #=> (2/5)
1549 * Rational(-25, 100).round(1, half: :up) #=> (-3/10)
1550 * Rational(-25, 100).round(1, half: :down) #=> (-1/5)
1551 * Rational(-25, 100).round(1, half: :even) #=> (-1/5)
1552 */
1553static VALUE
1554nurat_round_n(int argc, VALUE *argv, VALUE self)
1555{
1556 VALUE opt;
1557 enum ruby_num_rounding_mode mode = (
1558 argc = rb_scan_args(argc, argv, "*:", NULL, &opt),
1560 VALUE (*round_func)(VALUE) = ROUND_FUNC(mode, nurat_round);
1561 return f_round_common(argc, argv, self, round_func);
1562}
1563
1564static double
1565nurat_to_double(VALUE self)
1566{
1567 get_dat1(self);
1568 if (!RB_INTEGER_TYPE_P(dat->num) || !RB_INTEGER_TYPE_P(dat->den)) {
1569 return NUM2DBL(dat->num) / NUM2DBL(dat->den);
1570 }
1571 return rb_int_fdiv_double(dat->num, dat->den);
1572}
1573
1574/*
1575 * call-seq:
1576 * rat.to_f -> float
1577 *
1578 * Returns the value as a Float.
1579 *
1580 * Rational(2).to_f #=> 2.0
1581 * Rational(9, 4).to_f #=> 2.25
1582 * Rational(-3, 4).to_f #=> -0.75
1583 * Rational(20, 3).to_f #=> 6.666666666666667
1584 */
1585static VALUE
1586nurat_to_f(VALUE self)
1587{
1588 return DBL2NUM(nurat_to_double(self));
1589}
1590
1591/*
1592 * call-seq:
1593 * rat.to_r -> self
1594 *
1595 * Returns self.
1596 *
1597 * Rational(2).to_r #=> (2/1)
1598 * Rational(-8, 6).to_r #=> (-4/3)
1599 */
1600static VALUE
1601nurat_to_r(VALUE self)
1602{
1603 return self;
1604}
1605
1606#define id_ceil rb_intern("ceil")
1607static VALUE
1608f_ceil(VALUE x)
1609{
1610 if (RB_INTEGER_TYPE_P(x))
1611 return x;
1612 if (RB_FLOAT_TYPE_P(x))
1613 return rb_float_ceil(x, 0);
1614
1615 return rb_funcall(x, id_ceil, 0);
1616}
1617
1618#define id_quo idQuo
1619static VALUE
1620f_quo(VALUE x, VALUE y)
1621{
1622 if (RB_INTEGER_TYPE_P(x))
1623 return rb_int_div(x, y);
1624 if (RB_FLOAT_TYPE_P(x))
1625 return DBL2NUM(RFLOAT_VALUE(x) / RFLOAT_VALUE(y));
1626
1627 return rb_funcallv(x, id_quo, 1, &y);
1628}
1629
1630#define f_reciprocal(x) f_quo(ONE, (x))
1631
1632/*
1633 The algorithm here is the method described in CLISP. Bruno Haible has
1634 graciously given permission to use this algorithm. He says, "You can use
1635 it, if you present the following explanation of the algorithm."
1636
1637 Algorithm (recursively presented):
1638 If x is a rational number, return x.
1639 If x = 0.0, return 0.
1640 If x < 0.0, return (- (rationalize (- x))).
1641 If x > 0.0:
1642 Call (integer-decode-float x). It returns a m,e,s=1 (mantissa,
1643 exponent, sign).
1644 If m = 0 or e >= 0: return x = m*2^e.
1645 Search a rational number between a = (m-1/2)*2^e and b = (m+1/2)*2^e
1646 with smallest possible numerator and denominator.
1647 Note 1: If m is a power of 2, we ought to take a = (m-1/4)*2^e.
1648 But in this case the result will be x itself anyway, regardless of
1649 the choice of a. Therefore we can simply ignore this case.
1650 Note 2: At first, we need to consider the closed interval [a,b].
1651 but since a and b have the denominator 2^(|e|+1) whereas x itself
1652 has a denominator <= 2^|e|, we can restrict the search to the open
1653 interval (a,b).
1654 So, for given a and b (0 < a < b) we are searching a rational number
1655 y with a <= y <= b.
1656 Recursive algorithm fraction_between(a,b):
1657 c := (ceiling a)
1658 if c < b
1659 then return c ; because a <= c < b, c integer
1660 else
1661 ; a is not integer (otherwise we would have had c = a < b)
1662 k := c-1 ; k = floor(a), k < a < b <= k+1
1663 return y = k + 1/fraction_between(1/(b-k), 1/(a-k))
1664 ; note 1 <= 1/(b-k) < 1/(a-k)
1665
1666 You can see that we are actually computing a continued fraction expansion.
1667
1668 Algorithm (iterative):
1669 If x is rational, return x.
1670 Call (integer-decode-float x). It returns a m,e,s (mantissa,
1671 exponent, sign).
1672 If m = 0 or e >= 0, return m*2^e*s. (This includes the case x = 0.0.)
1673 Create rational numbers a := (2*m-1)*2^(e-1) and b := (2*m+1)*2^(e-1)
1674 (positive and already in lowest terms because the denominator is a
1675 power of two and the numerator is odd).
1676 Start a continued fraction expansion
1677 p[-1] := 0, p[0] := 1, q[-1] := 1, q[0] := 0, i := 0.
1678 Loop
1679 c := (ceiling a)
1680 if c >= b
1681 then k := c-1, partial_quotient(k), (a,b) := (1/(b-k),1/(a-k)),
1682 goto Loop
1683 finally partial_quotient(c).
1684 Here partial_quotient(c) denotes the iteration
1685 i := i+1, p[i] := c*p[i-1]+p[i-2], q[i] := c*q[i-1]+q[i-2].
1686 At the end, return s * (p[i]/q[i]).
1687 This rational number is already in lowest terms because
1688 p[i]*q[i-1]-p[i-1]*q[i] = (-1)^i.
1689*/
1690
1691static void
1692nurat_rationalize_internal(VALUE a, VALUE b, VALUE *p, VALUE *q)
1693{
1694 VALUE c, k, t, p0, p1, p2, q0, q1, q2;
1695
1696 p0 = ZERO;
1697 p1 = ONE;
1698 q0 = ONE;
1699 q1 = ZERO;
1700
1701 while (1) {
1702 c = f_ceil(a);
1703 if (f_lt_p(c, b))
1704 break;
1705 k = f_sub(c, ONE);
1706 p2 = f_add(f_mul(k, p1), p0);
1707 q2 = f_add(f_mul(k, q1), q0);
1708 t = f_reciprocal(f_sub(b, k));
1709 b = f_reciprocal(f_sub(a, k));
1710 a = t;
1711 p0 = p1;
1712 q0 = q1;
1713 p1 = p2;
1714 q1 = q2;
1715 }
1716 *p = f_add(f_mul(c, p1), p0);
1717 *q = f_add(f_mul(c, q1), q0);
1718}
1719
1720/*
1721 * call-seq:
1722 * rat.rationalize -> self
1723 * rat.rationalize(eps) -> rational
1724 *
1725 * Returns a simpler approximation of the value if the optional
1726 * argument +eps+ is given (rat-|eps| <= result <= rat+|eps|),
1727 * self otherwise.
1728 *
1729 * r = Rational(5033165, 16777216)
1730 * r.rationalize #=> (5033165/16777216)
1731 * r.rationalize(Rational('0.01')) #=> (3/10)
1732 * r.rationalize(Rational('0.1')) #=> (1/3)
1733 */
1734static VALUE
1735nurat_rationalize(int argc, VALUE *argv, VALUE self)
1736{
1737 VALUE e, a, b, p, q;
1738
1739 if (rb_check_arity(argc, 0, 1) == 0)
1740 return self;
1741
1742 if (nurat_negative_p(self))
1743 return rb_rational_uminus(nurat_rationalize(argc, argv, rb_rational_uminus(self)));
1744
1745 e = f_abs(argv[0]);
1746 a = f_sub(self, e);
1747 b = f_add(self, e);
1748
1749 if (f_eqeq_p(a, b))
1750 return self;
1751
1752 nurat_rationalize_internal(a, b, &p, &q);
1753 return f_rational_new2(CLASS_OF(self), p, q);
1754}
1755
1756/* :nodoc: */
1757static VALUE
1758nurat_hash(VALUE self)
1759{
1760 st_index_t v, h[2];
1761 VALUE n;
1762
1763 get_dat1(self);
1764 n = rb_hash(dat->num);
1765 h[0] = NUM2LONG(n);
1766 n = rb_hash(dat->den);
1767 h[1] = NUM2LONG(n);
1768 v = rb_memhash(h, sizeof(h));
1769 return ST2FIX(v);
1770}
1771
1772static VALUE
1773f_format(VALUE self, VALUE (*func)(VALUE))
1774{
1775 VALUE s;
1776 get_dat1(self);
1777
1778 s = (*func)(dat->num);
1779 rb_str_cat2(s, "/");
1780 rb_str_concat(s, (*func)(dat->den));
1781
1782 return s;
1783}
1784
1785/*
1786 * call-seq:
1787 * rat.to_s -> string
1788 *
1789 * Returns the value as a string.
1790 *
1791 * Rational(2).to_s #=> "2/1"
1792 * Rational(-8, 6).to_s #=> "-4/3"
1793 * Rational('1/2').to_s #=> "1/2"
1794 */
1795static VALUE
1796nurat_to_s(VALUE self)
1797{
1798 return f_format(self, f_to_s);
1799}
1800
1801/*
1802 * call-seq:
1803 * rat.inspect -> string
1804 *
1805 * Returns the value as a string for inspection.
1806 *
1807 * Rational(2).inspect #=> "(2/1)"
1808 * Rational(-8, 6).inspect #=> "(-4/3)"
1809 * Rational('1/2').inspect #=> "(1/2)"
1810 */
1811static VALUE
1812nurat_inspect(VALUE self)
1813{
1814 VALUE s;
1815
1816 s = rb_usascii_str_new2("(");
1817 rb_str_concat(s, f_format(self, f_inspect));
1818 rb_str_cat2(s, ")");
1819
1820 return s;
1821}
1822
1823/* :nodoc: */
1824static VALUE
1825nurat_dumper(VALUE self)
1826{
1827 return self;
1828}
1829
1830/* :nodoc: */
1831static VALUE
1832nurat_loader(VALUE self, VALUE a)
1833{
1834 VALUE num, den;
1835
1836 get_dat1(self);
1837 num = rb_ivar_get(a, id_i_num);
1838 den = rb_ivar_get(a, id_i_den);
1839 nurat_int_check(num);
1840 nurat_int_check(den);
1841 nurat_canonicalize(&num, &den);
1842 RRATIONAL_SET_NUM(dat, num);
1843 RRATIONAL_SET_DEN(dat, den);
1844 OBJ_FREEZE_RAW(self);
1845
1846 return self;
1847}
1848
1849/* :nodoc: */
1850static VALUE
1851nurat_marshal_dump(VALUE self)
1852{
1853 VALUE a;
1854 get_dat1(self);
1855
1856 a = rb_assoc_new(dat->num, dat->den);
1857 rb_copy_generic_ivar(a, self);
1858 return a;
1859}
1860
1861/* :nodoc: */
1862static VALUE
1863nurat_marshal_load(VALUE self, VALUE a)
1864{
1865 VALUE num, den;
1866
1867 rb_check_frozen(self);
1868
1869 Check_Type(a, T_ARRAY);
1870 if (RARRAY_LEN(a) != 2)
1871 rb_raise(rb_eArgError, "marshaled rational must have an array whose length is 2 but %ld", RARRAY_LEN(a));
1872
1873 num = RARRAY_AREF(a, 0);
1874 den = RARRAY_AREF(a, 1);
1875 nurat_int_check(num);
1876 nurat_int_check(den);
1877 nurat_canonicalize(&num, &den);
1878 rb_ivar_set(self, id_i_num, num);
1879 rb_ivar_set(self, id_i_den, den);
1880
1881 return self;
1882}
1883
1884/* --- */
1885
1886VALUE
1888{
1889 get_dat1(x);
1890 return nurat_convert(CLASS_OF(x), dat->den, dat->num, FALSE);
1891}
1892
1893/*
1894 * call-seq:
1895 * int.gcd(other_int) -> integer
1896 *
1897 * Returns the greatest common divisor of the two integers.
1898 * The result is always positive. 0.gcd(x) and x.gcd(0) return x.abs.
1899 *
1900 * 36.gcd(60) #=> 12
1901 * 2.gcd(2) #=> 2
1902 * 3.gcd(-7) #=> 1
1903 * ((1<<31)-1).gcd((1<<61)-1) #=> 1
1904 */
1905VALUE
1906rb_gcd(VALUE self, VALUE other)
1907{
1908 other = nurat_int_value(other);
1909 return f_gcd(self, other);
1910}
1911
1912/*
1913 * call-seq:
1914 * int.lcm(other_int) -> integer
1915 *
1916 * Returns the least common multiple of the two integers.
1917 * The result is always positive. 0.lcm(x) and x.lcm(0) return zero.
1918 *
1919 * 36.lcm(60) #=> 180
1920 * 2.lcm(2) #=> 2
1921 * 3.lcm(-7) #=> 21
1922 * ((1<<31)-1).lcm((1<<61)-1) #=> 4951760154835678088235319297
1923 */
1924VALUE
1925rb_lcm(VALUE self, VALUE other)
1926{
1927 other = nurat_int_value(other);
1928 return f_lcm(self, other);
1929}
1930
1931/*
1932 * call-seq:
1933 * int.gcdlcm(other_int) -> array
1934 *
1935 * Returns an array with the greatest common divisor and
1936 * the least common multiple of the two integers, [gcd, lcm].
1937 *
1938 * 36.gcdlcm(60) #=> [12, 180]
1939 * 2.gcdlcm(2) #=> [2, 2]
1940 * 3.gcdlcm(-7) #=> [1, 21]
1941 * ((1<<31)-1).gcdlcm((1<<61)-1) #=> [1, 4951760154835678088235319297]
1942 */
1943VALUE
1945{
1946 other = nurat_int_value(other);
1947 return rb_assoc_new(f_gcd(self, other), f_lcm(self, other));
1948}
1949
1950VALUE
1952{
1953 return nurat_s_new_internal(rb_cRational, x, y);
1954}
1955
1956VALUE
1958{
1959 return nurat_s_canonicalize_internal(rb_cRational, x, y);
1960}
1961
1962VALUE
1964{
1965 VALUE a[2];
1966 a[0] = x;
1967 a[1] = y;
1968 return nurat_s_convert(2, a, rb_cRational);
1969}
1970
1971VALUE
1973{
1974 return nurat_numerator(rat);
1975}
1976
1977VALUE
1979{
1980 return nurat_denominator(rat);
1981}
1982
1983#define id_numerator rb_intern("numerator")
1984#define f_numerator(x) rb_funcall((x), id_numerator, 0)
1985
1986#define id_denominator rb_intern("denominator")
1987#define f_denominator(x) rb_funcall((x), id_denominator, 0)
1988
1989#define id_to_r idTo_r
1990#define f_to_r(x) rb_funcall((x), id_to_r, 0)
1991
1992/*
1993 * call-seq:
1994 * num.numerator -> integer
1995 *
1996 * Returns the numerator.
1997 */
1998static VALUE
1999numeric_numerator(VALUE self)
2000{
2001 return f_numerator(f_to_r(self));
2002}
2003
2004/*
2005 * call-seq:
2006 * num.denominator -> integer
2007 *
2008 * Returns the denominator (always positive).
2009 */
2010static VALUE
2011numeric_denominator(VALUE self)
2012{
2013 return f_denominator(f_to_r(self));
2014}
2015
2016
2017/*
2018 * call-seq:
2019 * num.quo(int_or_rat) -> rat
2020 * num.quo(flo) -> flo
2021 *
2022 * Returns the most exact division (rational for integers, float for floats).
2023 */
2024
2025VALUE
2027{
2028 if (RB_TYPE_P(x, T_COMPLEX)) {
2029 return rb_complex_div(x, y);
2030 }
2031
2032 if (RB_FLOAT_TYPE_P(y)) {
2033 return rb_funcallv(x, idFdiv, 1, &y);
2034 }
2035
2036 if (canonicalization) {
2037 x = rb_rational_raw1(x);
2038 }
2039 else {
2040 x = rb_convert_type(x, T_RATIONAL, "Rational", "to_r");
2041 }
2042 return rb_rational_div(x, y);
2043}
2044
2045VALUE
2047{
2048 if (RB_TYPE_P(x, T_RATIONAL)) {
2049 get_dat1(x);
2050 if (f_one_p(dat->den)) return dat->num;
2051 }
2052 return x;
2053}
2054
2055/*
2056 * call-seq:
2057 * int.numerator -> self
2058 *
2059 * Returns self.
2060 */
2061static VALUE
2062integer_numerator(VALUE self)
2063{
2064 return self;
2065}
2066
2067/*
2068 * call-seq:
2069 * int.denominator -> 1
2070 *
2071 * Returns 1.
2072 */
2073static VALUE
2074integer_denominator(VALUE self)
2075{
2076 return INT2FIX(1);
2077}
2078
2079static VALUE float_to_r(VALUE self);
2080/*
2081 * call-seq:
2082 * flo.numerator -> integer
2083 *
2084 * Returns the numerator. The result is machine dependent.
2085 *
2086 * n = 0.3.numerator #=> 5404319552844595
2087 * d = 0.3.denominator #=> 18014398509481984
2088 * n.fdiv(d) #=> 0.3
2089 *
2090 * See also Float#denominator.
2091 */
2092VALUE
2094{
2095 double d = RFLOAT_VALUE(self);
2096 VALUE r;
2097 if (isinf(d) || isnan(d))
2098 return self;
2099 r = float_to_r(self);
2100 if (canonicalization && k_integer_p(r)) {
2101 return r;
2102 }
2103 return nurat_numerator(r);
2104}
2105
2106/*
2107 * call-seq:
2108 * flo.denominator -> integer
2109 *
2110 * Returns the denominator (always positive). The result is machine
2111 * dependent.
2112 *
2113 * See also Float#numerator.
2114 */
2115VALUE
2117{
2118 double d = RFLOAT_VALUE(self);
2119 VALUE r;
2120 if (isinf(d) || isnan(d))
2121 return INT2FIX(1);
2122 r = float_to_r(self);
2123 if (canonicalization && k_integer_p(r)) {
2124 return ONE;
2125 }
2126 return nurat_denominator(r);
2127}
2128
2129/*
2130 * call-seq:
2131 * nil.to_r -> (0/1)
2132 *
2133 * Returns zero as a rational.
2134 */
2135static VALUE
2136nilclass_to_r(VALUE self)
2137{
2138 return rb_rational_new1(INT2FIX(0));
2139}
2140
2141/*
2142 * call-seq:
2143 * nil.rationalize([eps]) -> (0/1)
2144 *
2145 * Returns zero as a rational. The optional argument +eps+ is always
2146 * ignored.
2147 */
2148static VALUE
2149nilclass_rationalize(int argc, VALUE *argv, VALUE self)
2150{
2151 rb_check_arity(argc, 0, 1);
2152 return nilclass_to_r(self);
2153}
2154
2155/*
2156 * call-seq:
2157 * int.to_r -> rational
2158 *
2159 * Returns the value as a rational.
2160 *
2161 * 1.to_r #=> (1/1)
2162 * (1<<64).to_r #=> (18446744073709551616/1)
2163 */
2164static VALUE
2165integer_to_r(VALUE self)
2166{
2167 return rb_rational_new1(self);
2168}
2169
2170/*
2171 * call-seq:
2172 * int.rationalize([eps]) -> rational
2173 *
2174 * Returns the value as a rational. The optional argument +eps+ is
2175 * always ignored.
2176 */
2177static VALUE
2178integer_rationalize(int argc, VALUE *argv, VALUE self)
2179{
2180 rb_check_arity(argc, 0, 1);
2181 return integer_to_r(self);
2182}
2183
2184static void
2185float_decode_internal(VALUE self, VALUE *rf, int *n)
2186{
2187 double f;
2188
2189 f = frexp(RFLOAT_VALUE(self), n);
2190 f = ldexp(f, DBL_MANT_DIG);
2191 *n -= DBL_MANT_DIG;
2192 *rf = rb_dbl2big(f);
2193}
2194
2195/*
2196 * call-seq:
2197 * flt.to_r -> rational
2198 *
2199 * Returns the value as a rational.
2200 *
2201 * 2.0.to_r #=> (2/1)
2202 * 2.5.to_r #=> (5/2)
2203 * -0.75.to_r #=> (-3/4)
2204 * 0.0.to_r #=> (0/1)
2205 * 0.3.to_r #=> (5404319552844595/18014398509481984)
2206 *
2207 * NOTE: 0.3.to_r isn't the same as "0.3".to_r. The latter is
2208 * equivalent to "3/10".to_r, but the former isn't so.
2209 *
2210 * 0.3.to_r == 3/10r #=> false
2211 * "0.3".to_r == 3/10r #=> true
2212 *
2213 * See also Float#rationalize.
2214 */
2215static VALUE
2216float_to_r(VALUE self)
2217{
2218 VALUE f;
2219 int n;
2220
2221 float_decode_internal(self, &f, &n);
2222#if FLT_RADIX == 2
2223 if (n == 0)
2224 return rb_rational_new1(f);
2225 if (n > 0)
2227 n = -n;
2229#else
2231 if (RB_TYPE_P(f, T_RATIONAL))
2232 return f;
2233 return rb_rational_new1(f);
2234#endif
2235}
2236
2237VALUE
2239{
2240 VALUE e, a, b, p, q;
2241
2242 e = f_abs(prec);
2243 a = f_sub(flt, e);
2244 b = f_add(flt, e);
2245
2246 if (f_eqeq_p(a, b))
2247 return float_to_r(flt);
2248
2249 nurat_rationalize_internal(a, b, &p, &q);
2250 return rb_rational_new2(p, q);
2251}
2252
2253VALUE
2255{
2256 VALUE a, b, f, p, q;
2257 int n;
2258
2259 float_decode_internal(flt, &f, &n);
2260 if (INT_ZERO_P(f) || n >= 0)
2262
2263 {
2264 VALUE radix_times_f, den;
2265
2266 radix_times_f = rb_int_mul(INT2FIX(FLT_RADIX), f);
2267#if FLT_RADIX == 2 && 0
2268 den = rb_int_lshift(ONE, INT2FIX(1-n));
2269#else
2271#endif
2272
2273 a = rb_rational_new2(rb_int_minus(radix_times_f, INT2FIX(FLT_RADIX - 1)), den);
2274 b = rb_rational_new2(rb_int_plus(radix_times_f, INT2FIX(FLT_RADIX - 1)), den);
2275 }
2276
2277 if (nurat_eqeq_p(a, b))
2278 return float_to_r(flt);
2279
2280 nurat_rationalize_internal(a, b, &p, &q);
2281 return rb_rational_new2(p, q);
2282}
2283
2284/*
2285 * call-seq:
2286 * flt.rationalize([eps]) -> rational
2287 *
2288 * Returns a simpler approximation of the value (flt-|eps| <= result
2289 * <= flt+|eps|). If the optional argument +eps+ is not given,
2290 * it will be chosen automatically.
2291 *
2292 * 0.3.rationalize #=> (3/10)
2293 * 1.333.rationalize #=> (1333/1000)
2294 * 1.333.rationalize(0.01) #=> (4/3)
2295 *
2296 * See also Float#to_r.
2297 */
2298static VALUE
2299float_rationalize(int argc, VALUE *argv, VALUE self)
2300{
2301 double d = RFLOAT_VALUE(self);
2302
2303 if (d < 0.0)
2304 return rb_rational_uminus(float_rationalize(argc, argv, DBL2NUM(-d)));
2305
2306 if (rb_check_arity(argc, 0, 1)) {
2307 return rb_flt_rationalize_with_prec(self, argv[0]);
2308 }
2309 else {
2310 return rb_flt_rationalize(self);
2311 }
2312}
2313
2314#include <ctype.h>
2315
2316inline static int
2317issign(int c)
2318{
2319 return (c == '-' || c == '+');
2320}
2321
2322static int
2323read_sign(const char **s, const char *const e)
2324{
2325 int sign = '?';
2326
2327 if (*s < e && issign(**s)) {
2328 sign = **s;
2329 (*s)++;
2330 }
2331 return sign;
2332}
2333
2334inline static int
2335islettere(int c)
2336{
2337 return (c == 'e' || c == 'E');
2338}
2339
2340static VALUE
2341negate_num(VALUE num)
2342{
2343 if (FIXNUM_P(num)) {
2344 return rb_int_uminus(num);
2345 }
2346 else {
2347 BIGNUM_NEGATE(num);
2348 return rb_big_norm(num);
2349 }
2350}
2351
2352static int
2353read_num(const char **s, const char *const end, VALUE *num, VALUE *nexp)
2354{
2355 VALUE fp = ONE, exp, fn = ZERO, n = ZERO;
2356 int expsign = 0, ok = 0;
2357 char *e;
2358
2359 *nexp = ZERO;
2360 *num = ZERO;
2361 if (*s < end && **s != '.') {
2362 n = rb_int_parse_cstr(*s, end-*s, &e, NULL,
2364 if (NIL_P(n))
2365 return 0;
2366 *s = e;
2367 *num = n;
2368 ok = 1;
2369 }
2370
2371 if (*s < end && **s == '.') {
2372 size_t count = 0;
2373
2374 (*s)++;
2375 fp = rb_int_parse_cstr(*s, end-*s, &e, &count,
2377 if (NIL_P(fp))
2378 return 1;
2379 *s = e;
2380 {
2381 VALUE l = f_expt10(*nexp = SIZET2NUM(count));
2382 n = n == ZERO ? fp : rb_int_plus(rb_int_mul(*num, l), fp);
2383 *num = n;
2384 fn = SIZET2NUM(count);
2385 }
2386 ok = 1;
2387 }
2388
2389 if (ok && *s + 1 < end && islettere(**s)) {
2390 (*s)++;
2391 expsign = read_sign(s, end);
2392 exp = rb_int_parse_cstr(*s, end-*s, &e, NULL,
2394 if (NIL_P(exp))
2395 return 1;
2396 *s = e;
2397 if (exp != ZERO) {
2398 if (expsign == '-') {
2399 if (fn != ZERO) exp = rb_int_plus(exp, fn);
2400 }
2401 else {
2402 if (fn != ZERO) exp = rb_int_minus(exp, fn);
2403 exp = negate_num(exp);
2404 }
2405 *nexp = exp;
2406 }
2407 }
2408
2409 return ok;
2410}
2411
2412inline static const char *
2413skip_ws(const char *s, const char *e)
2414{
2415 while (s < e && isspace((unsigned char)*s))
2416 ++s;
2417 return s;
2418}
2419
2420static VALUE
2421parse_rat(const char *s, const char *const e, int strict, int raise)
2422{
2423 int sign;
2424 VALUE num, den, nexp, dexp;
2425
2426 s = skip_ws(s, e);
2427 sign = read_sign(&s, e);
2428
2429 if (!read_num(&s, e, &num, &nexp)) {
2430 if (strict) return Qnil;
2431 return canonicalization ? ZERO : nurat_s_alloc(rb_cRational);
2432 }
2433 den = ONE;
2434 if (s < e && *s == '/') {
2435 s++;
2436 if (!read_num(&s, e, &den, &dexp)) {
2437 if (strict) return Qnil;
2438 den = ONE;
2439 }
2440 else if (den == ZERO) {
2441 if (!raise) return Qnil;
2443 }
2444 else if (strict && skip_ws(s, e) != e) {
2445 return Qnil;
2446 }
2447 else {
2448 nexp = rb_int_minus(nexp, dexp);
2449 nurat_reduce(&num, &den);
2450 }
2451 }
2452 else if (strict && skip_ws(s, e) != e) {
2453 return Qnil;
2454 }
2455
2456 if (nexp != ZERO) {
2457 if (INT_NEGATIVE_P(nexp)) {
2458 VALUE mul;
2459 if (!FIXNUM_P(nexp)) {
2460 overflow:
2461 return sign == '-' ? DBL2NUM(-HUGE_VAL) : DBL2NUM(HUGE_VAL);
2462 }
2463 mul = f_expt10(LONG2NUM(-FIX2LONG(nexp)));
2464 if (RB_FLOAT_TYPE_P(mul)) goto overflow;
2465 num = rb_int_mul(num, mul);
2466 }
2467 else {
2468 VALUE div;
2469 if (!FIXNUM_P(nexp)) {
2470 underflow:
2471 return sign == '-' ? DBL2NUM(-0.0) : DBL2NUM(+0.0);
2472 }
2473 div = f_expt10(nexp);
2474 if (RB_FLOAT_TYPE_P(div)) goto underflow;
2475 den = rb_int_mul(den, div);
2476 }
2477 nurat_reduce(&num, &den);
2478 }
2479
2480 if (sign == '-') {
2481 num = negate_num(num);
2482 }
2483
2484 if (!canonicalization || den != ONE)
2485 num = rb_rational_raw(num, den);
2486 return num;
2487}
2488
2489static VALUE
2490string_to_r_strict(VALUE self, int raise)
2491{
2492 VALUE num;
2493
2494 rb_must_asciicompat(self);
2495
2496 num = parse_rat(RSTRING_PTR(self), RSTRING_END(self), 1, raise);
2497 if (NIL_P(num)) {
2498 if (!raise) return Qnil;
2499 rb_raise(rb_eArgError, "invalid value for convert(): %+"PRIsVALUE,
2500 self);
2501 }
2502
2503 if (RB_FLOAT_TYPE_P(num) && !FLOAT_ZERO_P(num)) {
2504 if (!raise) return Qnil;
2505 rb_raise(rb_eFloatDomainError, "Infinity");
2506 }
2507 return num;
2508}
2509
2510/*
2511 * call-seq:
2512 * str.to_r -> rational
2513 *
2514 * Returns the result of interpreting leading characters in +str+
2515 * as a rational. Leading whitespace and extraneous characters
2516 * past the end of a valid number are ignored.
2517 * Digit sequences can be separated by an underscore.
2518 * If there is not a valid number at the start of +str+,
2519 * zero is returned. This method never raises an exception.
2520 *
2521 * ' 2 '.to_r #=> (2/1)
2522 * '300/2'.to_r #=> (150/1)
2523 * '-9.2'.to_r #=> (-46/5)
2524 * '-9.2e2'.to_r #=> (-920/1)
2525 * '1_234_567'.to_r #=> (1234567/1)
2526 * '21 June 09'.to_r #=> (21/1)
2527 * '21/06/09'.to_r #=> (7/2)
2528 * 'BWV 1079'.to_r #=> (0/1)
2529 *
2530 * NOTE: "0.3".to_r isn't the same as 0.3.to_r. The former is
2531 * equivalent to "3/10".to_r, but the latter isn't so.
2532 *
2533 * "0.3".to_r == 3/10r #=> true
2534 * 0.3.to_r == 3/10r #=> false
2535 *
2536 * See also Kernel#Rational.
2537 */
2538static VALUE
2539string_to_r(VALUE self)
2540{
2541 VALUE num;
2542
2543 rb_must_asciicompat(self);
2544
2545 num = parse_rat(RSTRING_PTR(self), RSTRING_END(self), 0, TRUE);
2546
2547 if (RB_FLOAT_TYPE_P(num) && !FLOAT_ZERO_P(num))
2548 rb_raise(rb_eFloatDomainError, "Infinity");
2549 return num;
2550}
2551
2552VALUE
2553rb_cstr_to_rat(const char *s, int strict) /* for complex's internal */
2554{
2555 VALUE num;
2556
2557 num = parse_rat(s, s + strlen(s), strict, TRUE);
2558
2559 if (RB_FLOAT_TYPE_P(num) && !FLOAT_ZERO_P(num))
2560 rb_raise(rb_eFloatDomainError, "Infinity");
2561 return num;
2562}
2563
2564static VALUE
2565to_rational(VALUE val)
2566{
2567 return rb_convert_type_with_id(val, T_RATIONAL, "Rational", idTo_r);
2568}
2569
2570static VALUE
2571nurat_convert(VALUE klass, VALUE numv, VALUE denv, int raise)
2572{
2573 VALUE a1 = numv, a2 = denv;
2574 int state;
2575
2576 if (NIL_P(a1) || NIL_P(a2)) {
2577 if (!raise) return Qnil;
2578 rb_raise(rb_eTypeError, "can't convert nil into Rational");
2579 }
2580
2581 if (RB_TYPE_P(a1, T_COMPLEX)) {
2582 if (k_exact_zero_p(RCOMPLEX(a1)->imag))
2583 a1 = RCOMPLEX(a1)->real;
2584 }
2585
2586 if (RB_TYPE_P(a2, T_COMPLEX)) {
2587 if (k_exact_zero_p(RCOMPLEX(a2)->imag))
2588 a2 = RCOMPLEX(a2)->real;
2589 }
2590
2591 if (RB_FLOAT_TYPE_P(a1)) {
2592 a1 = float_to_r(a1);
2593 }
2594 else if (RB_TYPE_P(a1, T_STRING)) {
2595 a1 = string_to_r_strict(a1, raise);
2596 if (!raise && NIL_P(a1)) return Qnil;
2597 }
2598
2599 if (RB_FLOAT_TYPE_P(a2)) {
2600 a2 = float_to_r(a2);
2601 }
2602 else if (RB_TYPE_P(a2, T_STRING)) {
2603 a2 = string_to_r_strict(a2, raise);
2604 if (!raise && NIL_P(a2)) return Qnil;
2605 }
2606
2607 if (RB_TYPE_P(a1, T_RATIONAL)) {
2608 if (a2 == Qundef || (k_exact_one_p(a2)))
2609 return a1;
2610 }
2611
2612 if (a2 == Qundef) {
2613 if (!k_integer_p(a1)) {
2614 if (!raise) {
2615 VALUE result = rb_protect(to_rational, a1, NULL);
2617 return result;
2618 }
2619 return to_rational(a1);
2620 }
2621 }
2622 else {
2623 if (!k_numeric_p(a1)) {
2624 if (!raise) {
2625 a1 = rb_protect(to_rational, a1, &state);
2626 if (state) {
2628 return Qnil;
2629 }
2630 }
2631 else {
2632 a1 = rb_check_convert_type_with_id(a1, T_RATIONAL, "Rational", idTo_r);
2633 }
2634 }
2635 if (!k_numeric_p(a2)) {
2636 if (!raise) {
2637 a2 = rb_protect(to_rational, a2, &state);
2638 if (state) {
2640 return Qnil;
2641 }
2642 }
2643 else {
2644 a2 = rb_check_convert_type_with_id(a2, T_RATIONAL, "Rational", idTo_r);
2645 }
2646 }
2647 if ((k_numeric_p(a1) && k_numeric_p(a2)) &&
2648 (!f_integer_p(a1) || !f_integer_p(a2)))
2649 return f_div(a1, a2);
2650 }
2651
2652 {
2653 int argc;
2654 VALUE argv2[2];
2655 argv2[0] = a1;
2656 if (a2 == Qundef) {
2657 argv2[1] = Qnil;
2658 argc = 1;
2659 }
2660 else {
2661 if (!k_integer_p(a2) && !raise) return Qnil;
2662 argv2[1] = a2;
2663 argc = 2;
2664 }
2665 return nurat_s_new(argc, argv2, klass);
2666 }
2667}
2668
2669static VALUE
2670nurat_s_convert(int argc, VALUE *argv, VALUE klass)
2671{
2672 VALUE a1, a2;
2673
2674 if (rb_scan_args(argc, argv, "11", &a1, &a2) == 1) {
2675 a2 = Qundef;
2676 }
2677
2678 return nurat_convert(klass, a1, a2, TRUE);
2679}
2680
2681/*
2682 * A rational number can be represented as a pair of integer numbers:
2683 * a/b (b>0), where a is the numerator and b is the denominator.
2684 * Integer a equals rational a/1 mathematically.
2685 *
2686 * In Ruby, you can create rational objects with the Kernel#Rational,
2687 * to_r, or rationalize methods or by suffixing +r+ to a literal.
2688 * The return values will be irreducible fractions.
2689 *
2690 * Rational(1) #=> (1/1)
2691 * Rational(2, 3) #=> (2/3)
2692 * Rational(4, -6) #=> (-2/3)
2693 * 3.to_r #=> (3/1)
2694 * 2/3r #=> (2/3)
2695 *
2696 * You can also create rational objects from floating-point numbers or
2697 * strings.
2698 *
2699 * Rational(0.3) #=> (5404319552844595/18014398509481984)
2700 * Rational('0.3') #=> (3/10)
2701 * Rational('2/3') #=> (2/3)
2702 *
2703 * 0.3.to_r #=> (5404319552844595/18014398509481984)
2704 * '0.3'.to_r #=> (3/10)
2705 * '2/3'.to_r #=> (2/3)
2706 * 0.3.rationalize #=> (3/10)
2707 *
2708 * A rational object is an exact number, which helps you to write
2709 * programs without any rounding errors.
2710 *
2711 * 10.times.inject(0) {|t| t + 0.1 } #=> 0.9999999999999999
2712 * 10.times.inject(0) {|t| t + Rational('0.1') } #=> (1/1)
2713 *
2714 * However, when an expression includes an inexact component (numerical value
2715 * or operation), it will produce an inexact result.
2716 *
2717 * Rational(10) / 3 #=> (10/3)
2718 * Rational(10) / 3.0 #=> 3.3333333333333335
2719 *
2720 * Rational(-8) ** Rational(1, 3)
2721 * #=> (1.0000000000000002+1.7320508075688772i)
2722 */
2723void
2725{
2726 VALUE compat;
2727#undef rb_intern
2728#define rb_intern(str) rb_intern_const(str)
2729
2730 id_abs = rb_intern("abs");
2731 id_integer_p = rb_intern("integer?");
2732 id_i_num = rb_intern("@numerator");
2733 id_i_den = rb_intern("@denominator");
2734
2736
2737 rb_define_alloc_func(rb_cRational, nurat_s_alloc);
2739
2741
2742 rb_define_global_function("Rational", nurat_f_rational, -1);
2743
2744 rb_define_method(rb_cRational, "numerator", nurat_numerator, 0);
2745 rb_define_method(rb_cRational, "denominator", nurat_denominator, 0);
2746
2753 rb_define_method(rb_cRational, "fdiv", nurat_fdiv, 1);
2755
2757 rb_define_method(rb_cRational, "==", nurat_eqeq_p, 1);
2758 rb_define_method(rb_cRational, "coerce", nurat_coerce, 1);
2759
2760 rb_define_method(rb_cRational, "positive?", nurat_positive_p, 0);
2761 rb_define_method(rb_cRational, "negative?", nurat_negative_p, 0);
2764
2765 rb_define_method(rb_cRational, "floor", nurat_floor_n, -1);
2766 rb_define_method(rb_cRational, "ceil", nurat_ceil_n, -1);
2767 rb_define_method(rb_cRational, "truncate", nurat_truncate_n, -1);
2768 rb_define_method(rb_cRational, "round", nurat_round_n, -1);
2769
2770 rb_define_method(rb_cRational, "to_i", nurat_truncate, 0);
2771 rb_define_method(rb_cRational, "to_f", nurat_to_f, 0);
2772 rb_define_method(rb_cRational, "to_r", nurat_to_r, 0);
2773 rb_define_method(rb_cRational, "rationalize", nurat_rationalize, -1);
2774
2775 rb_define_method(rb_cRational, "hash", nurat_hash, 0);
2776
2777 rb_define_method(rb_cRational, "to_s", nurat_to_s, 0);
2778 rb_define_method(rb_cRational, "inspect", nurat_inspect, 0);
2779
2780 rb_define_private_method(rb_cRational, "marshal_dump", nurat_marshal_dump, 0);
2781 /* :nodoc: */
2782 compat = rb_define_class_under(rb_cRational, "compatible", rb_cObject);
2783 rb_define_private_method(compat, "marshal_load", nurat_marshal_load, 1);
2784 rb_marshal_define_compat(rb_cRational, compat, nurat_dumper, nurat_loader);
2785
2786 /* --- */
2787
2790 rb_define_method(rb_cInteger, "gcdlcm", rb_gcdlcm, 1);
2791
2792 rb_define_method(rb_cNumeric, "numerator", numeric_numerator, 0);
2793 rb_define_method(rb_cNumeric, "denominator", numeric_denominator, 0);
2795
2796 rb_define_method(rb_cInteger, "numerator", integer_numerator, 0);
2797 rb_define_method(rb_cInteger, "denominator", integer_denominator, 0);
2798
2801
2802 rb_define_method(rb_cNilClass, "to_r", nilclass_to_r, 0);
2803 rb_define_method(rb_cNilClass, "rationalize", nilclass_rationalize, -1);
2804 rb_define_method(rb_cInteger, "to_r", integer_to_r, 0);
2805 rb_define_method(rb_cInteger, "rationalize", integer_rationalize, -1);
2806 rb_define_method(rb_cFloat, "to_r", float_to_r, 0);
2807 rb_define_method(rb_cFloat, "rationalize", float_rationalize, -1);
2808
2809 rb_define_method(rb_cString, "to_r", string_to_r, 0);
2810
2811 rb_define_private_method(CLASS_OF(rb_cRational), "convert", nurat_s_convert, -1);
2812
2813 rb_provide("rational.so"); /* for backward compatibility */
2814}
#define DBL_MANT_DIG
Definition: acosh.c:19
VALUE rb_int2big(intptr_t n)
Definition: bignum.c:3180
#define f_add(x, y)
Definition: date_core.c:34
#define f_mul(x, y)
Definition: date_core.c:36
#define f_sub(x, y)
Definition: date_core.c:35
#define f_to_i(x)
Definition: date_core.c:48
#define f_div(x, y)
Definition: date_core.c:37
#define f_idiv(x, y)
Definition: date_core.c:39
#define f_ceil(x)
Definition: date_core.c:44
#define f_abs(x)
Definition: date_core.c:32
#define f_mod(x, y)
Definition: date_core.c:40
#define f_quo(x, y)
Definition: date_core.c:38
#define issign(c)
Definition: date_parse.c:60
#define f_lt_p(x, y)
Definition: date_parse.c:26
#define mul(x, y)
Definition: date_strftime.c:25
int count
Definition: encoding.c:57
VALUE rb_define_class(const char *, VALUE)
Defines a top-level class.
Definition: class.c:662
VALUE rb_define_class_under(VALUE, const char *, VALUE)
Defines a class under the namespace of outer.
Definition: class.c:711
void rb_undef_method(VALUE, const char *)
Definition: class.c:1593
VALUE rb_cNilClass
NilClass class.
Definition: ruby.h:2038
VALUE rb_cRational
Definition: rational.c:34
VALUE rb_cObject
Object class.
Definition: ruby.h:2012
VALUE rb_cInteger
Definition: ruby.h:2033
VALUE rb_cNumeric
Definition: ruby.h:2039
VALUE rb_cString
Definition: ruby.h:2046
VALUE rb_eFloatDomainError
Definition: ruby.h:2077
VALUE rb_cFloat
Definition: ruby.h:2030
void rb_raise(VALUE exc, const char *fmt,...)
Definition: error.c:2671
void rb_set_errinfo(VALUE err)
Sets the current exception ($!) to the given value.
Definition: eval.c:1896
VALUE rb_eTypeError
Definition: error.c:924
VALUE rb_protect(VALUE(*)(VALUE), VALUE, int *)
Protects a function call from potential global escapes from the function.
Definition: eval.c:1072
void rb_warn(const char *fmt,...)
Definition: error.c:315
VALUE rb_eArgError
Definition: error.c:925
VALUE rb_convert_type(VALUE, int, const char *, const char *)
Converts an object into another type.
Definition: object.c:2900
int rb_opts_exception_p(VALUE opts, int default_value)
Definition: object.c:3125
VALUE rb_convert_type_with_id(VALUE, int, const char *, ID)
Definition: object.c:2914
VALUE rb_equal(VALUE, VALUE)
Same as Object#===, case equality.
Definition: object.c:124
VALUE rb_obj_is_kind_of(VALUE, VALUE)
Determines if obj is a kind of c.
Definition: object.c:692
VALUE rb_check_convert_type_with_id(VALUE, int, const char *, ID)
Definition: object.c:2957
void rb_num_zerodiv(void)
Definition: numeric.c:194
#define FLT_RADIX
Definition: numeric.c:31
VALUE rb_dbl_cmp(double a, double b)
Definition: numeric.c:1431
#define id_quo
Definition: rational.c:1618
#define id_to_i
Definition: rational.c:40
#define f_to_s
Definition: rational.c:44
#define f_inspect
Definition: rational.c:43
#define k_exact_zero_p(x)
Definition: rational.c:232
VALUE rb_rational_cmp(VALUE self, VALUE other)
Definition: rational.c:1097
VALUE rb_rational_uminus(VALUE self)
Definition: rational.c:624
#define f_boolcast(x)
Definition: rational.c:42
VALUE rb_gcd(VALUE self, VALUE other)
Definition: rational.c:1906
VALUE rb_rational_pow(VALUE self, VALUE other)
Definition: rational.c:1002
VALUE rb_lcm(VALUE self, VALUE other)
Definition: rational.c:1925
#define ONE
Definition: rational.c:26
#define f_expt10(x)
Definition: rational.c:148
VALUE rb_Rational(VALUE x, VALUE y)
Definition: rational.c:1963
#define get_dat2(x, y)
Definition: rational.c:389
VALUE rb_rational_plus(VALUE self, VALUE other)
Definition: rational.c:737
VALUE rb_cstr_to_rat(const char *s, int strict)
Definition: rational.c:2553
VALUE rb_float_denominator(VALUE self)
Definition: rational.c:2116
void Init_Rational(void)
Definition: rational.c:2724
VALUE rb_gcd_normal(VALUE x, VALUE y)
Definition: rational.c:344
#define INT_POSITIVE_P(x)
Definition: rational.c:31
#define id_ceil
Definition: rational.c:1606
VALUE rb_rational_new(VALUE x, VALUE y)
Definition: rational.c:1957
VALUE rb_float_numerator(VALUE self)
Definition: rational.c:2093
VALUE rb_rational_num(VALUE rat)
Definition: rational.c:1972
VALUE rb_rational_floor(VALUE self, int ndigits)
Definition: rational.c:1415
VALUE rb_rational_reciprocal(VALUE x)
Definition: rational.c:1887
#define f_reciprocal(x)
Definition: rational.c:1630
VALUE rb_rational_abs(VALUE self)
Definition: rational.c:1255
VALUE rb_rational_div(VALUE self, VALUE other)
Definition: rational.c:916
#define TWO
Definition: rational.c:27
VALUE rb_flt_rationalize(VALUE flt)
Definition: rational.c:2254
#define f_denominator(x)
Definition: rational.c:1987
#define GMP_GCD_DIGITS
Definition: rational.c:29
#define rb_intern(str)
#define k_exact_p(x)
Definition: rational.c:229
#define f_to_r(x)
Definition: rational.c:1990
#define f_nonzero_p(x)
Definition: rational.c:164
VALUE rb_rational_raw(VALUE x, VALUE y)
Definition: rational.c:1951
#define id_idiv
Definition: rational.c:39
#define nurat_expt
Definition: rational.c:1077
VALUE rb_rational_minus(VALUE self, VALUE other)
Definition: rational.c:778
#define ZERO
Definition: rational.c:25
#define get_dat1(x)
Definition: rational.c:386
VALUE rb_flt_rationalize_with_prec(VALUE flt, VALUE prec)
Definition: rational.c:2238
#define INT_ZERO_P(x)
Definition: rational.c:32
#define canonicalization
Definition: rational.c:425
VALUE rb_rational_canonicalize(VALUE x)
Definition: rational.c:2046
VALUE rb_gcdlcm(VALUE self, VALUE other)
Definition: rational.c:1944
VALUE rb_rational_den(VALUE rat)
Definition: rational.c:1978
VALUE rb_rational_mul(VALUE self, VALUE other)
Definition: rational.c:874
VALUE rb_numeric_quo(VALUE x, VALUE y)
Definition: rational.c:2026
#define k_exact_one_p(x)
Definition: rational.c:233
#define f_numerator(x)
Definition: rational.c:1984
#define RARRAY_LEN(a)
#define T_COMPLEX
#define NULL
#define rb_funcallv(recv, mid, argc, argv)
#define NUM2DBL(x)
void rb_provide(const char *)
Definition: load.c:607
VALUE rb_hash(VALUE)
Definition: hash.c:129
void div_t div(int __numer, int __denom)
VALUE rb_complex_div(VALUE x, VALUE y)
Definition: complex.c:948
#define NEWOBJ_OF(obj, type, klass, flags)
#define RTEST(v)
void rb_copy_generic_ivar(VALUE, VALUE)
Definition: variable.c:1447
void rb_must_asciicompat(VALUE)
Definition: string.c:2166
VALUE rb_int_modulo(VALUE x, VALUE y)
Definition: numeric.c:3891
size_t strlen(const char *)
void rb_define_private_method(VALUE, const char *, VALUE(*)(), int)
#define T_STRING
VALUE rb_assoc_new(VALUE, VALUE)
Definition: array.c:896
void rb_define_global_function(const char *, VALUE(*)(), int)
#define LONG2FIX(i)
#define Qundef
VALUE rb_str_concat(VALUE, VALUE)
Definition: string.c:3065
VALUE rb_num_coerce_bin(VALUE, VALUE, ID)
Definition: numeric.c:446
#define CHAR_BIT
#define rb_str_cat2
VALUE rb_big_norm(VALUE)
Definition: bignum.c:3152
VALUE rb_int_abs(VALUE num)
Definition: numeric.c:4862
VALUE rb_dbl2big(double)
Definition: bignum.c:5249
VALUE rb_ivar_get(VALUE, ID)
Definition: variable.c:1070
#define RSTRING_END(str)
const VALUE VALUE obj
VALUE rb_int_div(VALUE x, VALUE y)
Definition: numeric.c:3821
#define rb_check_frozen(obj)
double yn(int, double)
double frexp(double, int *)
#define RSTRING_PTR(str)
@ RB_INT_PARSE_UNDERSCORE
#define T_BIGNUM
VALUE rb_float_pow(VALUE x, VALUE y)
Definition: numeric.c:1298
st_index_t rb_memhash(const void *ptr, long len)
Definition: random.c:1444
#define NIL_P(v)
VALUE rb_int_pow(VALUE x, VALUE y)
Definition: numeric.c:4111
#define DBL2NUM(dbl)
const char size_t n
unsigned long VALUE
VALUE rb_int_uminus(VALUE num)
Definition: numeric.c:3484
#define BIGNUM_NEGATE(b)
#define SIZEOF_BDIGIT
#define ROUND_FUNC(mode, name)
VALUE rb_int_equal(VALUE x, VALUE y)
Definition: numeric.c:4168
VALUE rb_big_mul(VALUE, VALUE)
Definition: bignum.c:5933
#define rb_rational_raw1(x)
VALUE rb_int_positive_pow(long x, unsigned long y)
Definition: numeric.c:4038
#define rb_float_new(d)
#define isinf(__x)
void rb_define_alloc_func(VALUE, rb_alloc_func_t)
VALUE rb_flo_div_flo(VALUE x, VALUE y)
Definition: numeric.c:1110
#define RB_FLOAT_TYPE_P(obj)
#define isnan(__x)
VALUE rb_int_cmp(VALUE x, VALUE y)
Definition: numeric.c:4217
const char * rb_obj_classname(VALUE)
Definition: variable.c:289
#define INT2NUM(x)
VALUE rb_int_and(VALUE x, VALUE y)
Definition: numeric.c:4472
#define T_RATIONAL
#define LONG2NUM(x)
#define long
VALUE rb_gcd_gmp(VALUE x, VALUE y)
VALUE rb_str_to_inum(VALUE, int, int)
Definition: bignum.c:4268
double nan(const char *)
Definition: nan.c:7
VALUE rb_int_lshift(VALUE x, VALUE y)
Definition: numeric.c:4589
#define PRIsVALUE
VALUE rb_Complex(VALUE, VALUE)
Definition: complex.c:1545
#define rb_funcall(recv, mid, argc,...)
#define FIX2INT(x)
int VALUE v
#define BIGNUM_LEN(b)
#define rb_scan_args(argc, argvp, fmt,...)
#define rb_usascii_str_new2
int rb_num_negative_p(VALUE)
Definition: numeric.c:313
VALUE rb_float_ceil(VALUE num, int ndigits)
Definition: numeric.c:2022
double rb_int_fdiv_double(VALUE x, VALUE y)
Definition: numeric.c:3733
#define RRATIONAL(obj)
#define RFLOAT_VALUE(v)
double ldexp(double, int)
#define TRUE
#define FALSE
VALUE rb_num_coerce_cmp(VALUE, VALUE, ID)
Definition: numeric.c:453
VALUE rb_big_new(size_t, int)
Definition: bignum.c:3014
enum ruby_num_rounding_mode rb_num_get_rounding_option(VALUE opts)
Definition: numeric.c:200
#define RRATIONAL_SET_NUM(rat, n)
#define Qtrue
#define INT_NEGATIVE_P(x)
#define BDIGIT
#define MUL_OVERFLOW_LONG_P(a, b)
#define Qnil
#define Qfalse
#define T_ARRAY
#define OBJ_FREEZE_RAW(x)
#define SIGNED_VALUE
st_data_t st_index_t
VALUE rb_int_minus(VALUE x, VALUE y)
Definition: numeric.c:3654
#define FIXNUM_ZERO_P(num)
#define RB_TYPE_P(obj, type)
#define FL_WB_PROTECTED
#define INT2FIX(i)
const VALUE * argv
VALUE rb_ivar_set(VALUE, ID, VALUE)
Definition: variable.c:1300
#define FIXNUM_P(f)
VALUE rb_int_divmod(VALUE x, VALUE y)
Definition: numeric.c:3968
#define CLASS_OF(v)
#define RRATIONAL_SET_DEN(rat, d)
#define Check_Type(v, t)
#define RB_INTEGER_TYPE_P(obj)
#define assert
#define rb_check_arity
VALUE rb_int_idiv(VALUE x, VALUE y)
Definition: numeric.c:3848
#define FLOAT_ZERO_P(x)
#define rb_rational_new2(x, y)
unsigned long ID
#define RGENGC_WB_PROTECTED_RATIONAL
#define BIGNUM_DIGITS(b)
VALUE rb_int_parse_cstr(const char *str, ssize_t len, char **endp, size_t *ndigits, int base, int flags)
Definition: bignum.c:4041
void rb_marshal_define_compat(VALUE newclass, VALUE oldclass, VALUE(*dumper)(VALUE), VALUE(*loader)(VALUE, VALUE))
Definition: marshal.c:134
double exp(double)
size_t st_index_t h
#define RUBY_FUNC_EXPORTED
#define FIX2LONG(x)
#define NUM2LONG(x)
void rb_define_method(VALUE, const char *, VALUE(*)(), int)
#define RARRAY_AREF(a, i)
#define rb_rational_new1(x)
#define HUGE_VAL
#define ST2FIX(h)
VALUE rb_int_plus(VALUE x, VALUE y)
Definition: numeric.c:3615
#define SIZET2NUM(v)
#define RCOMPLEX(obj)
VALUE rb_int_mul(VALUE x, VALUE y)
Definition: numeric.c:3704
#define f
#define neg(x)
Definition: time.c:141