Ruby 2.0.0p247(2013-06-27revision41674)

- 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 s = (*func)(s);
1283
1284 s = f_div(f_rational_new_bang1(CLASS_OF(self), s), b);
1285
1286 if (f_lt_p(n, ONE))
1287 s = f_to_i(s);
1288
1289 return s;
1290 }
1291
1292 /*
1293 * call-seq:
1294 * rat.floor -> integer
1295 * rat.floor(precision=0) -> rational
1296 *
1297 * Returns the truncated value (toward negative infinity).
1298 *
1299 * Rational(3).floor #=> 3
1300 * Rational(2, 3).floor #=> 0
1301 * Rational(-3, 2).floor #=> -1
1302 *
1303 * decimal - 1 2 3 . 4 5 6
1304 * ^ ^ ^ ^ ^ ^
1305 * precision -3 -2 -1 0 +1 +2
1306 *
1307 * '%f' % Rational('-123.456').floor(+1) #=> "-123.500000"
1308 * '%f' % Rational('-123.456').floor(-1) #=> "-130.000000"
1309 */
1310 static VALUE
1311 nurat_floor_n(int argc, VALUE *argv, VALUE self)
1312 {
1313 return f_round_common(argc, argv, self, nurat_floor);
1314 }
1315
1316 /*
1317 * call-seq:
1318 * rat.ceil -> integer
1319 * rat.ceil(precision=0) -> rational
1320 *
1321 * Returns the truncated value (toward positive infinity).
1322 *
1323 * Rational(3).ceil #=> 3
1324 * Rational(2, 3).ceil #=> 1
1325 * Rational(-3, 2).ceil #=> -1
1326 *
1327 * decimal - 1 2 3 . 4 5 6
1328 * ^ ^ ^ ^ ^ ^
1329 * precision -3 -2 -1 0 +1 +2
1330 *
1331 * '%f' % Rational('-123.456').ceil(+1) #=> "-123.400000"
1332 * '%f' % Rational('-123.456').ceil(-1) #=> "-120.000000"
1333 */
1334 static VALUE
1335 nurat_ceil_n(int argc, VALUE *argv, VALUE self)
1336 {
1337 return f_round_common(argc, argv, self, nurat_ceil);
1338 }
1339
1340 /*
1341 * call-seq:
1342 * rat.truncate -> integer
1343 * rat.truncate(precision=0) -> rational
1344 *
1345 * Returns the truncated value (toward zero).
1346 *
1347 * Rational(3).truncate #=> 3
1348 * Rational(2, 3).truncate #=> 0
1349 * Rational(-3, 2).truncate #=> -1
1350 *
1351 * decimal - 1 2 3 . 4 5 6
1352 * ^ ^ ^ ^ ^ ^
1353 * precision -3 -2 -1 0 +1 +2
1354 *
1355 * '%f' % Rational('-123.456').truncate(+1) #=> "-123.400000"
1356 * '%f' % Rational('-123.456').truncate(-1) #=> "-120.000000"
1357 */
1358 static VALUE
1359 nurat_truncate_n(int argc, VALUE *argv, VALUE self)
1360 {
1361 return f_round_common(argc, argv, self, nurat_truncate);
1362 }
1363
1364 /*
1365 * call-seq:
1366 * rat.round -> integer
1367 * rat.round(precision=0) -> rational
1368 *
1369 * Returns the truncated value (toward the nearest integer;
1370 * 0.5 => 1; -0.5 => -1).
1371 *
1372 * Rational(3).round #=> 3
1373 * Rational(2, 3).round #=> 1
1374 * Rational(-3, 2).round #=> -2
1375 *
1376 * decimal - 1 2 3 . 4 5 6
1377 * ^ ^ ^ ^ ^ ^
1378 * precision -3 -2 -1 0 +1 +2
1379 *
1380 * '%f' % Rational('-123.456').round(+1) #=> "-123.500000"
1381 * '%f' % Rational('-123.456').round(-1) #=> "-120.000000"
1382 */
1383 static VALUE
1384 nurat_round_n(int argc, VALUE *argv, VALUE self)
1385 {
1386 return f_round_common(argc, argv, self, nurat_round);
1387 }
1388
1389 /*
1390 * call-seq:
1391 * rat.to_f -> float
1392 *
1393 * Return the value as a float.
1394 *
1395 * Rational(2).to_f #=> 2.0
1396 * Rational(9, 4).to_f #=> 2.25
1397 * Rational(-3, 4).to_f #=> -0.75
1398 * Rational(20, 3).to_f #=> 6.666666666666667
1399 */
1400 static VALUE
1401 nurat_to_f(VALUE self)
1402 {
1403 get_dat1(self);
1404 return f_fdiv(dat->num, dat->den);
1405 }
1406
1407 /*
1408 * call-seq:
1409 * rat.to_r -> self
1410 *
1411 * Returns self.
1412 *
1413 * Rational(2).to_r #=> (2/1)
1414 * Rational(-8, 6).to_r #=> (-4/3)
1415 */
1416 static VALUE
1417 nurat_to_r(VALUE self)
1418 {
1419 return self;
1420 }
1421
1422 #define id_ceil rb_intern("ceil")
1423 #define f_ceil(x) rb_funcall((x), id_ceil, 0)
1424
1425 #define id_quo rb_intern("quo")
1426 #define f_quo(x,y) rb_funcall((x), id_quo, 1, (y))
1427
1428 #define f_reciprocal(x) f_quo(ONE, (x))
1429
1430 /*
1431 The algorithm here is the method described in CLISP. Bruno Haible has
1432 graciously given permission to use this algorithm. He says, "You can use
1433 it, if you present the following explanation of the algorithm."
1434
1435 Algorithm (recursively presented):
1436 If x is a rational number, return x.
1437 If x = 0.0, return 0.
1438 If x < 0.0, return (- (rationalize (- x))).
1439 If x > 0.0:
1440 Call (integer-decode-float x). It returns a m,e,s=1 (mantissa,
1441 exponent, sign).
1442 If m = 0 or e >= 0: return x = m*2^e.
1443 Search a rational number between a = (m-1/2)*2^e and b = (m+1/2)*2^e
1444 with smallest possible numerator and denominator.
1445 Note 1: If m is a power of 2, we ought to take a = (m-1/4)*2^e.
1446 But in this case the result will be x itself anyway, regardless of
1447 the choice of a. Therefore we can simply ignore this case.
1448 Note 2: At first, we need to consider the closed interval [a,b].
1449 but since a and b have the denominator 2^(|e|+1) whereas x itself
1450 has a denominator <= 2^|e|, we can restrict the search to the open
1451 interval (a,b).
1452 So, for given a and b (0 < a < b) we are searching a rational number
1453 y with a <= y <= b.
1454 Recursive algorithm fraction_between(a,b):
1455 c := (ceiling a)
1456 if c < b
1457 then return c ; because a <= c < b, c integer
1458 else
1459 ; a is not integer (otherwise we would have had c = a < b)
1460 k := c-1 ; k = floor(a), k < a < b <= k+1
1461 return y = k + 1/fraction_between(1/(b-k), 1/(a-k))
1462 ; note 1 <= 1/(b-k) < 1/(a-k)
1463
1464 You can see that we are actually computing a continued fraction expansion.
1465
1466 Algorithm (iterative):
1467 If x is rational, return x.
1468 Call (integer-decode-float x). It returns a m,e,s (mantissa,
1469 exponent, sign).
1470 If m = 0 or e >= 0, return m*2^e*s. (This includes the case x = 0.0.)
1471 Create rational numbers a := (2*m-1)*2^(e-1) and b := (2*m+1)*2^(e-1)
1472 (positive and already in lowest terms because the denominator is a
1473 power of two and the numerator is odd).
1474 Start a continued fraction expansion
1475 p[-1] := 0, p[0] := 1, q[-1] := 1, q[0] := 0, i := 0.
1476 Loop
1477 c := (ceiling a)
1478 if c >= b
1479 then k := c-1, partial_quotient(k), (a,b) := (1/(b-k),1/(a-k)),
1480 goto Loop
1481 finally partial_quotient(c).
1482 Here partial_quotient(c) denotes the iteration
1483 i := i+1, p[i] := c*p[i-1]+p[i-2], q[i] := c*q[i-1]+q[i-2].
1484 At the end, return s * (p[i]/q[i]).
1485 This rational number is already in lowest terms because
1486 p[i]*q[i-1]-p[i-1]*q[i] = (-1)^i.
1487 */
1488
1489 static void
1490 nurat_rationalize_internal(VALUE a, VALUE b, VALUE *p, VALUE *q)
1491 {
1492 VALUE c, k, t, p0, p1, p2, q0, q1, q2;
1493
1494 p0 = ZERO;
1495 p1 = ONE;
1496 q0 = ONE;
1497 q1 = ZERO;
1498
1499 while (1) {
1500 c = f_ceil(a);
1501 if (f_lt_p(c, b))
1502 break;
1503 k = f_sub(c, ONE);
1504 p2 = f_add(f_mul(k, p1), p0);
1505 q2 = f_add(f_mul(k, q1), q0);
1506 t = f_reciprocal(f_sub(b, k));
1507 b = f_reciprocal(f_sub(a, k));
1508 a = t;
1509 p0 = p1;
1510 q0 = q1;
1511 p1 = p2;
1512 q1 = q2;
1513 }
1514 *p = f_add(f_mul(c, p1), p0);
1515 *q = f_add(f_mul(c, q1), q0);
1516 }
1517
1518 /*
1519 * call-seq:
1520 * rat.rationalize -> self
1521 * rat.rationalize(eps) -> rational
1522 *
1523 * Returns a simpler approximation of the value if the optional
1524 * argument eps is given (rat-|eps| <= result <= rat+|eps|), self
1525 * otherwise.
1526 *
1527 * r = Rational(5033165, 16777216)
1528 * r.rationalize #=> (5033165/16777216)
1529 * r.rationalize(Rational('0.01')) #=> (3/10)
1530 * r.rationalize(Rational('0.1')) #=> (1/3)
1531 */
1532 static VALUE
1533 nurat_rationalize(int argc, VALUE *argv, VALUE self)
1534 {
1535 VALUE e, a, b, p, q;
1536
1537 if (argc == 0)
1538 return self;
1539
1540 if (f_negative_p(self))
1541 return f_negate(nurat_rationalize(argc, argv, f_abs(self)));
1542
1543 rb_scan_args(argc, argv, "01", &e);
1544 e = f_abs(e);
1545 a = f_sub(self, e);
1546 b = f_add(self, e);
1547
1548 if (f_eqeq_p(a, b))
1549 return self;
1550
1551 nurat_rationalize_internal(a, b, &p, &q);
1552 return f_rational_new2(CLASS_OF(self), p, q);
1553 }
1554
1555 /* :nodoc: */
1556 static VALUE
1557 nurat_hash(VALUE self)
1558 {
1559 st_index_t v, h[2];
1560 VALUE n;
1561
1562 get_dat1(self);
1563 n = rb_hash(dat->num);
1564 h[0] = NUM2LONG(n);
1565 n = rb_hash(dat->den);
1566 h[1] = NUM2LONG(n);
1567 v = rb_memhash(h, sizeof(h));
1568 return LONG2FIX(v);
1569 }
1570
1571 static VALUE
1572 f_format(VALUE self, VALUE (*func)(VALUE))
1573 {
1574 VALUE s;
1575 get_dat1(self);
1576
1577 s = (*func)(dat->num);
1578 rb_str_cat2(s, "/");
1579 rb_str_concat(s, (*func)(dat->den));
1580
1581 return s;
1582 }
1583
1584 /*
1585 * call-seq:
1586 * rat.to_s -> string
1587 *
1588 * Returns the value as a string.
1589 *
1590 * Rational(2).to_s #=> "2/1"
1591 * Rational(-8, 6).to_s #=> "-4/3"
1592 * Rational('1/2').to_s #=> "1/2"
1593 */
1594 static VALUE
1595 nurat_to_s(VALUE self)
1596 {
1597 return f_format(self, f_to_s);
1598 }
1599
1600 /*
1601 * call-seq:
1602 * rat.inspect -> string
1603 *
1604 * Returns the value as a string for inspection.
1605 *
1606 * Rational(2).inspect #=> "(2/1)"
1607 * Rational(-8, 6).inspect #=> "(-4/3)"
1608 * Rational('1/2').inspect #=> "(1/2)"
1609 */
1610 static VALUE
1611 nurat_inspect(VALUE self)
1612 {
1613 VALUE s;
1614
1615 s = rb_usascii_str_new2("(");
1616 rb_str_concat(s, f_format(self, f_inspect));
1617 rb_str_cat2(s, ")");
1618
1619 return s;
1620 }
1621
1622 /* :nodoc: */
1623 static VALUE
1624 nurat_dumper(VALUE self)
1625 {
1626 return self;
1627 }
1628
1629 /* :nodoc: */
1630 static VALUE
1631 nurat_loader(VALUE self, VALUE a)
1632 {
1633 get_dat1(self);
1634
1635 dat->num = rb_ivar_get(a, id_i_num);
1636 dat->den = rb_ivar_get(a, id_i_den);
1637
1638 return self;
1639 }
1640
1641 /* :nodoc: */
1642 static VALUE
1643 nurat_marshal_dump(VALUE self)
1644 {
1645 VALUE a;
1646 get_dat1(self);
1647
1648 a = rb_assoc_new(dat->num, dat->den);
1649 rb_copy_generic_ivar(a, self);
1650 return a;
1651 }
1652
1653 /* :nodoc: */
1654 static VALUE
1655 nurat_marshal_load(VALUE self, VALUE a)
1656 {
1657 rb_check_frozen(self);
1658 rb_check_trusted(self);
1659
1660 Check_Type(a, T_ARRAY);
1661 if (RARRAY_LEN(a) != 2)
1662 rb_raise(rb_eArgError, "marshaled rational must have an array whose length is 2 but %ld", RARRAY_LEN(a));
1663 if (f_zero_p(RARRAY_PTR(a)[1]))
1664 rb_raise_zerodiv();
1665
1666 rb_ivar_set(self, id_i_num, RARRAY_PTR(a)[0]);
1667 rb_ivar_set(self, id_i_den, RARRAY_PTR(a)[1]);
1668
1669 return self;
1670 }
1671
1672 /* --- */
1673
1674 VALUE
1675 rb_rational_reciprocal(VALUE x)
1676 {
1677 get_dat1(x);
1678 return f_rational_new_no_reduce2(CLASS_OF(x), dat->den, dat->num);
1679 }
1680
1681 /*
1682 * call-seq:
1683 * int.gcd(int2) -> integer
1684 *
1685 * Returns the greatest common divisor (always positive). 0.gcd(x)
1686 * and x.gcd(0) return abs(x).
1687 *
1688 * 2.gcd(2) #=> 2
1689 * 3.gcd(-7) #=> 1
1690 * ((1<<31)-1).gcd((1<<61)-1) #=> 1
1691 */
1692 VALUE
1693 rb_gcd(VALUE self, VALUE other)
1694 {
1695 other = nurat_int_value(other);
1696 return f_gcd(self, other);
1697 }
1698
1699 /*
1700 * call-seq:
1701 * int.lcm(int2) -> integer
1702 *
1703 * Returns the least common multiple (always positive). 0.lcm(x) and
1704 * x.lcm(0) return zero.
1705 *
1706 * 2.lcm(2) #=> 2
1707 * 3.lcm(-7) #=> 21
1708 * ((1<<31)-1).lcm((1<<61)-1) #=> 4951760154835678088235319297
1709 */
1710 VALUE
1711 rb_lcm(VALUE self, VALUE other)
1712 {
1713 other = nurat_int_value(other);
1714 return f_lcm(self, other);
1715 }
1716
1717 /*
1718 * call-seq:
1719 * int.gcdlcm(int2) -> array
1720 *
1721 * Returns an array; [int.gcd(int2), int.lcm(int2)].
1722 *
1723 * 2.gcdlcm(2) #=> [2, 2]
1724 * 3.gcdlcm(-7) #=> [1, 21]
1725 * ((1<<31)-1).gcdlcm((1<<61)-1) #=> [1, 4951760154835678088235319297]
1726 */
1727 VALUE
1728 rb_gcdlcm(VALUE self, VALUE other)
1729 {
1730 other = nurat_int_value(other);
1731 return rb_assoc_new(f_gcd(self, other), f_lcm(self, other));
1732 }
1733
1734 VALUE
1735 rb_rational_raw(VALUE x, VALUE y)
1736 {
1737 return nurat_s_new_internal(rb_cRational, x, y);
1738 }
1739
1740 VALUE
1741 rb_rational_new(VALUE x, VALUE y)
1742 {
1743 return nurat_s_canonicalize_internal(rb_cRational, x, y);
1744 }
1745
1746 static VALUE nurat_s_convert(int argc, VALUE *argv, VALUE klass);
1747
1748 VALUE
1749 rb_Rational(VALUE x, VALUE y)
1750 {
1751 VALUE a[2];
1752 a[0] = x;
1753 a[1] = y;
1754 return nurat_s_convert(2, a, rb_cRational);
1755 }
1756
1757 #define id_numerator rb_intern("numerator")
1758 #define f_numerator(x) rb_funcall((x), id_numerator, 0)
1759
1760 #define id_denominator rb_intern("denominator")
1761 #define f_denominator(x) rb_funcall((x), id_denominator, 0)
1762
1763 #define id_to_r rb_intern("to_r")
1764 #define f_to_r(x) rb_funcall((x), id_to_r, 0)
1765
1766 /*
1767 * call-seq:
1768 * num.numerator -> integer
1769 *
1770 * Returns the numerator.
1771 */
1772 static VALUE
1773 numeric_numerator(VALUE self)
1774 {
1775 return f_numerator(f_to_r(self));
1776 }
1777
1778 /*
1779 * call-seq:
1780 * num.denominator -> integer
1781 *
1782 * Returns the denominator (always positive).
1783 */
1784 static VALUE
1785 numeric_denominator(VALUE self)
1786 {
1787 return f_denominator(f_to_r(self));
1788 }
1789
1790 /*
1791 * call-seq:
1792 * int.numerator -> self
1793 *
1794 * Returns self.
1795 */
1796 static VALUE
1797 integer_numerator(VALUE self)
1798 {
1799 return self;
1800 }
1801
1802 /*
1803 * call-seq:
1804 * int.denominator -> 1
1805 *
1806 * Returns 1.
1807 */
1808 static VALUE
1809 integer_denominator(VALUE self)
1810 {
1811 return INT2FIX(1);
1812 }
1813
1814 /*
1815 * call-seq:
1816 * flo.numerator -> integer
1817 *
1818 * Returns the numerator. The result is machine dependent.
1819 *
1820 * n = 0.3.numerator #=> 5404319552844595
1821 * d = 0.3.denominator #=> 18014398509481984
1822 * n.fdiv(d) #=> 0.3
1823 */
1824 static VALUE
1825 float_numerator(VALUE self)
1826 {
1827 double d = RFLOAT_VALUE(self);
1828 if (isinf(d) || isnan(d))
1829 return self;
1830 return rb_call_super(0, 0);
1831 }
1832
1833 /*
1834 * call-seq:
1835 * flo.denominator -> integer
1836 *
1837 * Returns the denominator (always positive). The result is machine
1838 * dependent.
1839 *
1840 * See numerator.
1841 */
1842 static VALUE
1843 float_denominator(VALUE self)
1844 {
1845 double d = RFLOAT_VALUE(self);
1846 if (isinf(d) || isnan(d))
1847 return INT2FIX(1);
1848 return rb_call_super(0, 0);
1849 }
1850
1851 /*
1852 * call-seq:
1853 * nil.to_r -> (0/1)
1854 *
1855 * Returns zero as a rational.
1856 */
1857 static VALUE
1858 nilclass_to_r(VALUE self)
1859 {
1860 return rb_rational_new1(INT2FIX(0));
1861 }
1862
1863 /*
1864 * call-seq:
1865 * nil.rationalize([eps]) -> (0/1)
1866 *
1867 * Returns zero as a rational. The optional argument eps is always
1868 * ignored.
1869 */
1870 static VALUE
1871 nilclass_rationalize(int argc, VALUE *argv, VALUE self)
1872 {
1873 rb_scan_args(argc, argv, "01", NULL);
1874 return nilclass_to_r(self);
1875 }
1876
1877 /*
1878 * call-seq:
1879 * int.to_r -> rational
1880 *
1881 * Returns the value as a rational.
1882 *
1883 * 1.to_r #=> (1/1)
1884 * (1<<64).to_r #=> (18446744073709551616/1)
1885 */
1886 static VALUE
1887 integer_to_r(VALUE self)
1888 {
1889 return rb_rational_new1(self);
1890 }
1891
1892 /*
1893 * call-seq:
1894 * int.rationalize([eps]) -> rational
1895 *
1896 * Returns the value as a rational. The optional argument eps is
1897 * always ignored.
1898 */
1899 static VALUE
1900 integer_rationalize(int argc, VALUE *argv, VALUE self)
1901 {
1902 rb_scan_args(argc, argv, "01", NULL);
1903 return integer_to_r(self);
1904 }
1905
1906 static void
1907 float_decode_internal(VALUE self, VALUE *rf, VALUE *rn)
1908 {
1909 double f;
1910 int n;
1911
1912 f = frexp(RFLOAT_VALUE(self), &n);
1913 f = ldexp(f, DBL_MANT_DIG);
1914 n -= DBL_MANT_DIG;
1915 *rf = rb_dbl2big(f);
1916 *rn = INT2FIX(n);
1917 }
1918
1919 #if 0
1920 static VALUE
1921 float_decode(VALUE self)
1922 {
1923 VALUE f, n;
1924
1925 float_decode_internal(self, &f, &n);
1926 return rb_assoc_new(f, n);
1927 }
1928 #endif
1929
1930 #define id_lshift rb_intern("<<")
1931 #define f_lshift(x,n) rb_funcall((x), id_lshift, 1, (n))
1932
1933 /*
1934 * call-seq:
1935 * flt.to_r -> rational
1936 *
1937 * Returns the value as a rational.
1938 *
1939 * NOTE: 0.3.to_r isn't the same as '0.3'.to_r. The latter is
1940 * equivalent to '3/10'.to_r, but the former isn't so.
1941 *
1942 * 2.0.to_r #=> (2/1)
1943 * 2.5.to_r #=> (5/2)
1944 * -0.75.to_r #=> (-3/4)
1945 * 0.0.to_r #=> (0/1)
1946 *
1947 * See rationalize.
1948 */
1949 static VALUE
1950 float_to_r(VALUE self)
1951 {
1952 VALUE f, n;
1953
1954 float_decode_internal(self, &f, &n);
1955 #if FLT_RADIX == 2
1956 {
1957 long ln = FIX2LONG(n);
1958
1959 if (ln == 0)
1960 return f_to_r(f);
1961 if (ln > 0)
1962 return f_to_r(f_lshift(f, n));
1963 ln = -ln;
1964 return rb_rational_new2(f, f_lshift(ONE, INT2FIX(ln)));
1965 }
1966 #else
1967 return f_to_r(f_mul(f, f_expt(INT2FIX(FLT_RADIX), n)));
1968 #endif
1969 }
1970
1971 /*
1972 * call-seq:
1973 * flt.rationalize([eps]) -> rational
1974 *
1975 * Returns a simpler approximation of the value (flt-|eps| <= result
1976 * <= flt+|eps|). if the optional eps is not given, it will be chosen
1977 * automatically.
1978 *
1979 * 0.3.rationalize #=> (3/10)
1980 * 1.333.rationalize #=> (1333/1000)
1981 * 1.333.rationalize(0.01) #=> (4/3)
1982 *
1983 * See to_r.
1984 */
1985 static VALUE
1986 float_rationalize(int argc, VALUE *argv, VALUE self)
1987 {
1988 VALUE e, a, b, p, q;
1989
1990 if (f_negative_p(self))
1991 return f_negate(float_rationalize(argc, argv, f_abs(self)));
1992
1993 rb_scan_args(argc, argv, "01", &e);
1994
1995 if (argc != 0) {
1996 e = f_abs(e);
1997 a = f_sub(self, e);
1998 b = f_add(self, e);
1999 }
2000 else {
2001 VALUE f, n;
2002
2003 float_decode_internal(self, &f, &n);
2004 if (f_zero_p(f) || f_positive_p(n))
2005 return rb_rational_new1(f_lshift(f, n));
2006
2007 #if FLT_RADIX == 2
2008 {
2009 VALUE two_times_f, den;
2010
2011 two_times_f = f_mul(TWO, f);
2012 den = f_lshift(ONE, f_sub(ONE, n));
2013
2014 a = rb_rational_new2(f_sub(two_times_f, ONE), den);
2015 b = rb_rational_new2(f_add(two_times_f, ONE), den);
2016 }
2017 #else
2018 {
2019 VALUE radix_times_f, den;
2020
2021 radix_times_f = f_mul(INT2FIX(FLT_RADIX), f);
2022 den = f_expt(INT2FIX(FLT_RADIX), f_sub(ONE, n));
2023
2024 a = rb_rational_new2(f_sub(radix_times_f, INT2FIX(FLT_RADIX - 1)), den);
2025 b = rb_rational_new2(f_add(radix_times_f, INT2FIX(FLT_RADIX - 1)), den);
2026 }
2027 #endif
2028 }
2029
2030 if (f_eqeq_p(a, b))
2031 return f_to_r(self);
2032
2033 nurat_rationalize_internal(a, b, &p, &q);
2034 return rb_rational_new2(p, q);
2035 }
2036
2037 #include <ctype.h>
2038
2039 inline static int
2040 issign(int c)
2041 {
2042 return (c == '-' || c == '+');
2043 }
2044
2045 static int
2046 read_sign(const char **s)
2047 {
2048 int sign = '?';
2049
2050 if (issign(**s)) {
2051 sign = **s;
2052 (*s)++;
2053 }
2054 return sign;
2055 }
2056
2057 inline static int
2058 isdecimal(int c)
2059 {
2060 return isdigit((unsigned char)c);
2061 }
2062
2063 static int
2064 read_digits(const char **s, int strict,
2065 VALUE *num, int *count)
2066 {
2067 char *b, *bb;
2068 int us = 1, ret = 1;
2069
2070 if (!isdecimal(**s)) {
2071 *num = ZERO;
2072 return 0;
2073 }
2074
2075 bb = b = ALLOCA_N(char, strlen(*s) + 1);
2076
2077 while (isdecimal(**s) || **s == '_') {
2078 if (**s == '_') {
2079 if (strict) {
2080 if (us) {
2081 ret = 0;
2082 goto conv;
2083 }
2084 }
2085 us = 1;
2086 }
2087 else {
2088 if (count)
2089 (*count)++;
2090 *b++ = **s;
2091 us = 0;
2092 }
2093 (*s)++;
2094 }
2095 if (us)
2096 do {
2097 (*s)--;
2098 } while (**s == '_');
2099 conv:
2100 *b = '\0';
2101 *num = rb_cstr_to_inum(bb, 10, 0);
2102 return ret;
2103 }
2104
2105 inline static int
2106 islettere(int c)
2107 {
2108 return (c == 'e' || c == 'E');
2109 }
2110
2111 static int
2112 read_num(const char **s, int numsign, int strict,
2113 VALUE *num)
2114 {
2115 VALUE ip, fp, exp;
2116
2117 *num = rb_rational_new2(ZERO, ONE);
2118 exp = Qnil;
2119
2120 if (**s != '.') {
2121 if (!read_digits(s, strict, &ip, NULL))
2122 return 0;
2123 *num = rb_rational_new2(ip, ONE);
2124 }
2125
2126 if (**s == '.') {
2127 int count = 0;
2128
2129 (*s)++;
2130 if (!read_digits(s, strict, &fp, &count))
2131 return 0;
2132 {
2133 VALUE l = f_expt10(INT2NUM(count));
2134 *num = f_mul(*num, l);
2135 *num = f_add(*num, fp);
2136 *num = f_div(*num, l);
2137 }
2138 }
2139
2140 if (islettere(**s)) {
2141 int expsign;
2142
2143 (*s)++;
2144 expsign = read_sign(s);
2145 if (!read_digits(s, strict, &exp, NULL))
2146 return 0;
2147 if (expsign == '-')
2148 exp = f_negate(exp);
2149 }
2150
2151 if (numsign == '-')
2152 *num = f_negate(*num);
2153 if (!NIL_P(exp)) {
2154 VALUE l = f_expt10(exp);
2155 *num = f_mul(*num, l);
2156 }
2157 return 1;
2158 }
2159
2160 inline static int
2161 read_den(const char **s, int strict,
2162 VALUE *num)
2163 {
2164 if (!read_digits(s, strict, num, NULL))
2165 return 0;
2166 return 1;
2167 }
2168
2169 static int
2170 read_rat_nos(const char **s, int sign, int strict,
2171 VALUE *num)
2172 {
2173 VALUE den;
2174
2175 if (!read_num(s, sign, strict, num))
2176 return 0;
2177 if (**s == '/') {
2178 (*s)++;
2179 if (!read_den(s, strict, &den))
2180 return 0;
2181 if (!(FIXNUM_P(den) && FIX2LONG(den) == 1))
2182 *num = f_div(*num, den);
2183 }
2184 return 1;
2185 }
2186
2187 static int
2188 read_rat(const char **s, int strict,
2189 VALUE *num)
2190 {
2191 int sign;
2192
2193 sign = read_sign(s);
2194 if (!read_rat_nos(s, sign, strict, num))
2195 return 0;
2196 return 1;
2197 }
2198
2199 inline static void
2200 skip_ws(const char **s)
2201 {
2202 while (isspace((unsigned char)**s))
2203 (*s)++;
2204 }
2205
2206 static int
2207 parse_rat(const char *s, int strict,
2208 VALUE *num)
2209 {
2210 skip_ws(&s);
2211 if (!read_rat(&s, strict, num))
2212 return 0;
2213 skip_ws(&s);
2214
2215 if (strict)
2216 if (*s != '\0')
2217 return 0;
2218 return 1;
2219 }
2220
2221 static VALUE
2222 string_to_r_strict(VALUE self)
2223 {
2224 char *s;
2225 VALUE num;
2226
2227 rb_must_asciicompat(self);
2228
2229 s = RSTRING_PTR(self);
2230
2231 if (!s || memchr(s, '\0', RSTRING_LEN(self)))
2232 rb_raise(rb_eArgError, "string contains null byte");
2233
2234 if (s && s[RSTRING_LEN(self)]) {
2235 rb_str_modify(self);
2236 s = RSTRING_PTR(self);
2237 s[RSTRING_LEN(self)] = '\0';
2238 }
2239
2240 if (!s)
2241 s = (char *)"";
2242
2243 if (!parse_rat(s, 1, &num)) {
2244 VALUE ins = f_inspect(self);
2245 rb_raise(rb_eArgError, "invalid value for convert(): %s",
2246 StringValuePtr(ins));
2247 }
2248
2249 if (RB_TYPE_P(num, T_FLOAT))
2250 rb_raise(rb_eFloatDomainError, "Infinity");
2251 return num;
2252 }
2253
2254 /*
2255 * call-seq:
2256 * str.to_r -> rational
2257 *
2258 * Returns a rational which denotes the string form. The parser
2259 * ignores leading whitespaces and trailing garbage. Any digit
2260 * sequences can be separated by an underscore. Returns zero for null
2261 * or garbage string.
2262 *
2263 * NOTE: '0.3'.to_r isn't the same as 0.3.to_r. The former is
2264 * equivalent to '3/10'.to_r, but the latter isn't so.
2265 *
2266 * ' 2 '.to_r #=> (2/1)
2267 * '300/2'.to_r #=> (150/1)
2268 * '-9.2'.to_r #=> (-46/5)
2269 * '-9.2e2'.to_r #=> (-920/1)
2270 * '1_234_567'.to_r #=> (1234567/1)
2271 * '21 june 09'.to_r #=> (21/1)
2272 * '21/06/09'.to_r #=> (7/2)
2273 * 'bwv 1079'.to_r #=> (0/1)
2274 *
2275 * See Kernel.Rational.
2276 */
2277 static VALUE
2278 string_to_r(VALUE self)
2279 {
2280 char *s;
2281 VALUE num;
2282
2283 rb_must_asciicompat(self);
2284
2285 s = RSTRING_PTR(self);
2286
2287 if (s && s[RSTRING_LEN(self)]) {
2288 rb_str_modify(self);
2289 s = RSTRING_PTR(self);
2290 s[RSTRING_LEN(self)] = '\0';
2291 }
2292
2293 if (!s)
2294 s = (char *)"";
2295
2296 (void)parse_rat(s, 0, &num);
2297
2298 if (RB_TYPE_P(num, T_FLOAT))
2299 rb_raise(rb_eFloatDomainError, "Infinity");
2300 return num;
2301 }
2302
2303 VALUE
2304 rb_cstr_to_rat(const char *s, int strict) /* for complex's internal */
2305 {
2306 VALUE num;
2307
2308 (void)parse_rat(s, strict, &num);
2309
2310 if (RB_TYPE_P(num, T_FLOAT))
2311 rb_raise(rb_eFloatDomainError, "Infinity");
2312 return num;
2313 }
2314
2315 static VALUE
2316 nurat_s_convert(int argc, VALUE *argv, VALUE klass)
2317 {
2318 VALUE a1, a2, backref;
2319
2320 rb_scan_args(argc, argv, "11", &a1, &a2);
2321
2322 if (NIL_P(a1) || (argc == 2 && NIL_P(a2)))
2323 rb_raise(rb_eTypeError, "can't convert nil into Rational");
2324
2325 switch (TYPE(a1)) {
2326 case T_COMPLEX:
2327 if (k_exact_zero_p(RCOMPLEX(a1)->imag))
2328 a1 = RCOMPLEX(a1)->real;
2329 }
2330
2331 switch (TYPE(a2)) {
2332 case T_COMPLEX:
2333 if (k_exact_zero_p(RCOMPLEX(a2)->imag))
2334 a2 = RCOMPLEX(a2)->real;
2335 }
2336
2337 backref = rb_backref_get();
2338 rb_match_busy(backref);
2339
2340 switch (TYPE(a1)) {
2341 case T_FIXNUM:
2342 case T_BIGNUM:
2343 break;
2344 case T_FLOAT:
2345 a1 = f_to_r(a1);
2346 break;
2347 case T_STRING:
2348 a1 = string_to_r_strict(a1);
2349 break;
2350 }
2351
2352 switch (TYPE(a2)) {
2353 case T_FIXNUM:
2354 case T_BIGNUM:
2355 break;
2356 case T_FLOAT:
2357 a2 = f_to_r(a2);
2358 break;
2359 case T_STRING:
2360 a2 = string_to_r_strict(a2);
2361 break;
2362 }
2363
2364 rb_backref_set(backref);
2365
2366 switch (TYPE(a1)) {
2367 case T_RATIONAL:
2368 if (argc == 1 || (k_exact_one_p(a2)))
2369 return a1;
2370 }
2371
2372 if (argc == 1) {
2373 if (!(k_numeric_p(a1) && k_integer_p(a1)))
2374 return rb_convert_type(a1, T_RATIONAL, "Rational", "to_r");
2375 }
2376 else {
2377 if ((k_numeric_p(a1) && k_numeric_p(a2)) &&
2378 (!f_integer_p(a1) || !f_integer_p(a2)))
2379 return f_div(a1, a2);
2380 }
2381
2382 {
2383 VALUE argv2[2];
2384 argv2[0] = a1;
2385 argv2[1] = a2;
2386 return nurat_s_new(argc, argv2, klass);
2387 }
2388 }
2389
2390 /*
2391 * A rational number can be represented as a paired integer number;
2392 * a/b (b>0). Where a is numerator and b is denominator. Integer a
2393 * equals rational a/1 mathematically.
2394 *
2395 * In ruby, you can create rational object with Rational, to_r or
2396 * rationalize method. The return values will be irreducible.
2397 *
2398 * Rational(1) #=> (1/1)
2399 * Rational(2, 3) #=> (2/3)
2400 * Rational(4, -6) #=> (-2/3)
2401 * 3.to_r #=> (3/1)
2402 *
2403 * You can also create rational object from floating-point numbers or
2404 * strings.
2405 *
2406 * Rational(0.3) #=> (5404319552844595/18014398509481984)
2407 * Rational('0.3') #=> (3/10)
2408 * Rational('2/3') #=> (2/3)
2409 *
2410 * 0.3.to_r #=> (5404319552844595/18014398509481984)
2411 * '0.3'.to_r #=> (3/10)
2412 * '2/3'.to_r #=> (2/3)
2413 * 0.3.rationalize #=> (3/10)
2414 *
2415 * A rational object is an exact number, which helps you to write
2416 * program without any rounding errors.
2417 *
2418 * 10.times.inject(0){|t,| t + 0.1} #=> 0.9999999999999999
2419 * 10.times.inject(0){|t,| t + Rational('0.1')} #=> (1/1)
2420 *
2421 * However, when an expression has inexact factor (numerical value or
2422 * operation), will produce an inexact result.
2423 *
2424 * Rational(10) / 3 #=> (10/3)
2425 * Rational(10) / 3.0 #=> 3.3333333333333335
2426 *
2427 * Rational(-8) ** Rational(1, 3)
2428 * #=> (1.0000000000000002+1.7320508075688772i)
2429 */
2430 void
2431 Init_Rational(void)
2432 {
2433 VALUE compat;
2434 #undef rb_intern
2435 #define rb_intern(str) rb_intern_const(str)
2436
2437 assert(fprintf(stderr, "assert() is now active\n"));
2438
2439 id_abs = rb_intern("abs");
2440 id_cmp = rb_intern("<=>");
2441 id_convert = rb_intern("convert");
2442 id_eqeq_p = rb_intern("==");
2443 id_expt = rb_intern("**");
2444 id_fdiv = rb_intern("fdiv");
2445 id_floor = rb_intern("floor");
2446 id_idiv = rb_intern("div");
2447 id_inspect = rb_intern("inspect");
2448 id_integer_p = rb_intern("integer?");
2449 id_negate = rb_intern("-@");
2450 id_to_f = rb_intern("to_f");
2451 id_to_i = rb_intern("to_i");
2452 id_to_s = rb_intern("to_s");
2453 id_truncate = rb_intern("truncate");
2454 id_i_num = rb_intern("@numerator");
2455 id_i_den = rb_intern("@denominator");
2456
2457 rb_cRational = rb_define_class("Rational", rb_cNumeric);
2458
2459 rb_define_alloc_func(rb_cRational, nurat_s_alloc);
2460 rb_undef_method(CLASS_OF(rb_cRational), "allocate");
2461
2462 #if 0
2463 rb_define_private_method(CLASS_OF(rb_cRational), "new!", nurat_s_new_bang, -1);
2464 rb_define_private_method(CLASS_OF(rb_cRational), "new", nurat_s_new, -1);
2465 #else
2466 rb_undef_method(CLASS_OF(rb_cRational), "new");
2467 #endif
2468
2469 rb_define_global_function("Rational", nurat_f_rational, -1);
2470
2471 rb_define_method(rb_cRational, "numerator", nurat_numerator, 0);
2472 rb_define_method(rb_cRational, "denominator", nurat_denominator, 0);
2473
2474 rb_define_method(rb_cRational, "+", nurat_add, 1);
2475 rb_define_method(rb_cRational, "-", nurat_sub, 1);
2476 rb_define_method(rb_cRational, "*", nurat_mul, 1);
2477 rb_define_method(rb_cRational, "/", nurat_div, 1);
2478 rb_define_method(rb_cRational, "quo", nurat_div, 1);
2479 rb_define_method(rb_cRational, "fdiv", nurat_fdiv, 1);
2480 rb_define_method(rb_cRational, "**", nurat_expt, 1);
2481
2482 rb_define_method(rb_cRational, "<=>", nurat_cmp, 1);
2483 rb_define_method(rb_cRational, "==", nurat_eqeq_p, 1);
2484 rb_define_method(rb_cRational, "coerce", nurat_coerce, 1);
2485
2486 #if 0 /* NUBY */
2487 rb_define_method(rb_cRational, "//", nurat_idiv, 1);
2488 #endif
2489
2490 #if 0
2491 rb_define_method(rb_cRational, "quot", nurat_quot, 1);
2492 rb_define_method(rb_cRational, "quotrem", nurat_quotrem, 1);
2493 #endif
2494
2495 #if 0
2496 rb_define_method(rb_cRational, "rational?", nurat_true, 0);
2497 rb_define_method(rb_cRational, "exact?", nurat_true, 0);
2498 #endif
2499
2500 rb_define_method(rb_cRational, "floor", nurat_floor_n, -1);
2501 rb_define_method(rb_cRational, "ceil", nurat_ceil_n, -1);
2502 rb_define_method(rb_cRational, "truncate", nurat_truncate_n, -1);
2503 rb_define_method(rb_cRational, "round", nurat_round_n, -1);
2504
2505 rb_define_method(rb_cRational, "to_i", nurat_truncate, 0);
2506 rb_define_method(rb_cRational, "to_f", nurat_to_f, 0);
2507 rb_define_method(rb_cRational, "to_r", nurat_to_r, 0);
2508 rb_define_method(rb_cRational, "rationalize", nurat_rationalize, -1);
2509
2510 rb_define_method(rb_cRational, "hash", nurat_hash, 0);
2511
2512 rb_define_method(rb_cRational, "to_s", nurat_to_s, 0);
2513 rb_define_method(rb_cRational, "inspect", nurat_inspect, 0);
2514
2515 rb_define_private_method(rb_cRational, "marshal_dump", nurat_marshal_dump, 0);
2516 compat = rb_define_class_under(rb_cRational, "compatible", rb_cObject);
2517 rb_define_private_method(compat, "marshal_load", nurat_marshal_load, 1);
2518 rb_marshal_define_compat(rb_cRational, compat, nurat_dumper, nurat_loader);
2519
2520 /* --- */
2521
2522 rb_define_method(rb_cInteger, "gcd", rb_gcd, 1);
2523 rb_define_method(rb_cInteger, "lcm", rb_lcm, 1);
2524 rb_define_method(rb_cInteger, "gcdlcm", rb_gcdlcm, 1);
2525
2526 rb_define_method(rb_cNumeric, "numerator", numeric_numerator, 0);
2527 rb_define_method(rb_cNumeric, "denominator", numeric_denominator, 0);
2528
2529 rb_define_method(rb_cInteger, "numerator", integer_numerator, 0);
2530 rb_define_method(rb_cInteger, "denominator", integer_denominator, 0);
2531
2532 rb_define_method(rb_cFloat, "numerator", float_numerator, 0);
2533 rb_define_method(rb_cFloat, "denominator", float_denominator, 0);
2534
2535 rb_define_method(rb_cNilClass, "to_r", nilclass_to_r, 0);
2536 rb_define_method(rb_cNilClass, "rationalize", nilclass_rationalize, -1);
2537 rb_define_method(rb_cInteger, "to_r", integer_to_r, 0);
2538 rb_define_method(rb_cInteger, "rationalize", integer_rationalize, -1);
2539 rb_define_method(rb_cFloat, "to_r", float_to_r, 0);
2540 rb_define_method(rb_cFloat, "rationalize", float_rationalize, -1);
2541
2542 rb_define_method(rb_cString, "to_r", string_to_r, 0);
2543
2544 rb_define_private_method(CLASS_OF(rb_cRational), "convert", nurat_s_convert, -1);
2545 }
2546
2547 /*
2548 Local variables:
2549 c-file-style: "ruby"
2550 End:
2551 */
2552