Ruby 2.1.5p273(2014-11-13revision48405)

- Main Page
- Modules
- Data Structures
- Files

- File List
- Globals

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