Ruby 2.0.0p353(2013-11-22revision43784)

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