Coverage Report

Created: 2026-03-31 07:30

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