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