Ruby: rational.c Source File

Ruby 3.0.5p211 (2022-11-24 revision ba5cf0f7c52d4d35cc6a173c89eda98ceffa2dcf)

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