20#if defined(HAVE_LIBGMP) && defined(HAVE_GMP_H)
25#define ZERO INT2FIX(0)
29#define GMP_GCD_DIGITS 1
31#define INT_POSITIVE_P(x) (FIXNUM_P(x) ? FIXNUM_POSITIVE_P(x) : BIGNUM_POSITIVE_P(x))
32#define INT_ZERO_P(x) (FIXNUM_P(x) ? FIXNUM_ZERO_P(x) : rb_bigzero_p(x))
36static ID id_abs, id_integer_p,
42#define f_boolcast(x) ((x) ? Qtrue : Qfalse)
43#define f_inspect rb_inspect
44#define f_to_s rb_obj_as_string
92 if (y ==
ONE)
return x;
95 if (x ==
ONE)
return y;
148#define f_expt10(x) rb_int_pow(INT2FIX(10), x)
164#define f_nonzero_p(x) (!f_zero_p(x))
182f_minus_one_p(
VALUE x)
229#define k_exact_p(x) (!k_float_p(x))
230#define k_inexact_p(x) k_float_p(x)
232#define k_exact_zero_p(x) (k_exact_p(x) && f_zero_p(x))
233#define k_exact_one_p(x) (k_exact_p(x) && f_one_p(x))
267#define f_gcd f_gcd_orig
273 unsigned long u,
v, t;
286 u = (
unsigned long)x;
287 v = (
unsigned long)y;
288 for (shift = 0; ((u |
v) & 1) == 0; ++shift) {
308 return (
long)(u << shift);
346 return f_gcd_normal(x, y);
360 return f_gcd_normal(x, y);
369 VALUE r = f_gcd_orig(x, y);
387 struct RRational *dat = RRATIONAL(x)
389#define get_dat2(x,y) \
390 struct RRational *adat = RRATIONAL(x), *bdat = RRATIONAL(y)
413 return nurat_s_new_internal(
klass, x,
ONE);
416#ifdef CANONICALIZATION_FOR_MATHN
420nurat_canonicalization(
int f)
425# define canonicalization 0
429nurat_int_check(
VALUE num)
432 if (!k_numeric_p(num) || !f_integer_p(num))
438nurat_int_value(
VALUE num)
440 nurat_int_check(num);
441 if (!k_integer_p(num))
464 if (*x ==
ONE || *y ==
ONE)
return;
473 nurat_canonicalize(&num, &den);
474 nurat_reduce(&num, &den);
478 return nurat_s_new_internal(
klass, num, den);
484 nurat_canonicalize(&num, &den);
488 return nurat_s_new_internal(
klass, num, den);
498 num = nurat_int_value(num);
502 num = nurat_int_value(num);
503 den = nurat_int_value(den);
507 return nurat_s_canonicalize_internal(
klass, num, den);
515 return nurat_s_canonicalize_internal(
klass, x, y);
523 return nurat_s_canonicalize_internal_no_reduce(
klass, x, y);
593nurat_numerator(
VALUE self)
611nurat_denominator(
VALUE self)
633#define f_imul f_imul_orig
637f_imul(
long a,
long b)
641 if (a == 0 || b == 0)
659f_imul(
long x,
long y)
661 VALUE r = f_imul_orig(x, y);
678 long ig = i_gcd(ad, bd);
681 VALUE a = f_imul(an, bd / ig);
682 VALUE b = f_imul(bn, ad / ig);
698 VALUE g = f_gcd(aden, bden);
717 double c = k ==
'+' ? a + b : a - b;
720 return f_rational_new_no_reduce2(
CLASS_OF(
self), num, den);
723static double nurat_to_double(
VALUE self);
743 return f_rational_new_no_reduce2(
CLASS_OF(
self),
755 return f_addsub(
self,
756 adat->num, adat->den,
757 bdat->num, bdat->den,
'+');
784 return f_rational_new_no_reduce2(
CLASS_OF(
self),
796 return f_addsub(
self,
797 adat->num, adat->den,
798 bdat->num, bdat->den,
'-');
818 double x = (an * bn) / (ad * bd);
845 long g1 = i_gcd(an, bd);
846 long g2 = i_gcd(ad, bn);
848 num = f_imul(an / g1, bn / g2);
849 den = f_imul(ad / g2, bd / g1);
852 VALUE g1 = f_gcd(anum, bden);
853 VALUE g2 = f_gcd(aden, bnum);
858 return f_rational_new_no_reduce2(
CLASS_OF(
self), num, den);
880 return f_muldiv(
self,
892 return f_muldiv(
self,
893 adat->num, adat->den,
894 bdat->num, bdat->den,
'*');
924 return f_muldiv(
self,
930 VALUE v = nurat_to_f(
self);
940 return f_rational_new_no_reduce2(
CLASS_OF(
self),
941 bdat->den, bdat->num);
943 return f_muldiv(
self,
944 adat->num, adat->den,
945 bdat->num, bdat->den,
'/');
970 return nurat_to_f(
self);
973 return nurat_to_f(
div);
980f_odd_p(
VALUE integer)
1007 if (k_rational_p(other)) {
1010 if (f_one_p(dat->den))
1015 if (k_numeric_p(other) &&
k_exact_p(other)) {
1017 if (f_one_p(dat->den)) {
1018 if (f_one_p(dat->num)) {
1022 return f_rational_new_bang1(
CLASS_OF(
self),
INT2FIX(f_odd_p(other) ? -1 : 1));
1063 return f_rational_new2(
CLASS_OF(
self), num, den);
1067 rb_warn(
"in a**b, b may be too big");
1077#define nurat_expt rb_rational_pow
1105 other = f_rational_new_bang1(
CLASS_OF(
self), other);
1106 goto other_is_rational;
1165 const double d = nurat_to_double(
self);
1170 const double d = nurat_to_double(
self);
1222nurat_positive_p(
VALUE self)
1235nurat_negative_p(
VALUE self)
1260 return nurat_s_canonicalize_internal_no_reduce(
CLASS_OF(
self), num, dat->den);
1266nurat_floor(
VALUE self)
1273nurat_ceil(
VALUE self)
1294nurat_truncate(
VALUE self)
1303nurat_round_half_up(
VALUE self)
1327nurat_round_half_down(
VALUE self)
1352nurat_round_half_even(
VALUE self)
1384 return (*func)(
self);
1388 if (!k_integer_p(
n))
1400 if (!k_rational_p(s)) {
1401 s = f_rational_new_bang1(
CLASS_OF(
self), s);
1409 s = nurat_truncate(s);
1418 return nurat_floor(
self);
1422 return f_round_common(1, &
n,
self, nurat_floor);
1453 return f_round_common(
argc,
argv,
self, nurat_floor);
1483 return f_round_common(
argc,
argv,
self, nurat_ceil);
1513 return f_round_common(
argc,
argv,
self, nurat_truncate);
1561 return f_round_common(
argc,
argv,
self, round_func);
1565nurat_to_double(
VALUE self)
1586nurat_to_f(
VALUE self)
1588 return DBL2NUM(nurat_to_double(
self));
1601nurat_to_r(
VALUE self)
1606#define id_ceil rb_intern("ceil")
1630#define f_reciprocal(x) f_quo(ONE, (x))
1694 VALUE c, k, t, p0, p1, p2, q0, q1, q2;
1737 VALUE e, a, b, p, q;
1742 if (nurat_negative_p(
self))
1752 nurat_rationalize_internal(a, b, &p, &q);
1753 return f_rational_new2(
CLASS_OF(
self), p, q);
1758nurat_hash(
VALUE self)
1778 s = (*func)(dat->num);
1796nurat_to_s(
VALUE self)
1798 return f_format(
self,
f_to_s);
1812nurat_inspect(
VALUE self)
1825nurat_dumper(
VALUE self)
1839 nurat_int_check(num);
1840 nurat_int_check(den);
1841 nurat_canonicalize(&num, &den);
1851nurat_marshal_dump(
VALUE self)
1875 nurat_int_check(num);
1876 nurat_int_check(den);
1877 nurat_canonicalize(&num, &den);
1890 return nurat_convert(
CLASS_OF(x), dat->den, dat->num,
FALSE);
1908 other = nurat_int_value(other);
1909 return f_gcd(
self, other);
1927 other = nurat_int_value(other);
1928 return f_lcm(
self, other);
1946 other = nurat_int_value(other);
1947 return rb_assoc_new(f_gcd(
self, other), f_lcm(
self, other));
1959 return nurat_s_canonicalize_internal(
rb_cRational, x, y);
1974 return nurat_numerator(rat);
1980 return nurat_denominator(rat);
1983#define id_numerator rb_intern("numerator")
1984#define f_numerator(x) rb_funcall((x), id_numerator, 0)
1986#define id_denominator rb_intern("denominator")
1987#define f_denominator(x) rb_funcall((x), id_denominator, 0)
1989#define id_to_r idTo_r
1990#define f_to_r(x) rb_funcall((x), id_to_r, 0)
1999numeric_numerator(
VALUE self)
2011numeric_denominator(
VALUE self)
2050 if (f_one_p(dat->den))
return dat->num;
2062integer_numerator(
VALUE self)
2074integer_denominator(
VALUE self)
2099 r = float_to_r(
self);
2103 return nurat_numerator(r);
2122 r = float_to_r(
self);
2126 return nurat_denominator(r);
2136nilclass_to_r(
VALUE self)
2152 return nilclass_to_r(
self);
2165integer_to_r(
VALUE self)
2181 return integer_to_r(
self);
2185float_decode_internal(
VALUE self,
VALUE *rf,
int *
n)
2216float_to_r(
VALUE self)
2221 float_decode_internal(
self, &
f, &
n);
2240 VALUE e, a, b, p, q;
2247 return float_to_r(flt);
2249 nurat_rationalize_internal(a, b, &p, &q);
2259 float_decode_internal(flt, &
f, &
n);
2264 VALUE radix_times_f, den;
2267#if FLT_RADIX == 2 && 0
2277 if (nurat_eqeq_p(a, b))
2278 return float_to_r(flt);
2280 nurat_rationalize_internal(a, b, &p, &q);
2319 return (c ==
'-' || c ==
'+');
2323read_sign(
const char **s,
const char *
const e)
2327 if (*s < e &&
issign(**s)) {
2337 return (c ==
'e' || c ==
'E');
2341negate_num(
VALUE num)
2353read_num(
const char **s,
const char *
const end,
VALUE *num,
VALUE *nexp)
2356 int expsign = 0, ok = 0;
2361 if (*s < end && **s !=
'.') {
2371 if (*s < end && **s ==
'.') {
2389 if (ok && *s + 1 < end && islettere(**s)) {
2391 expsign = read_sign(s, end);
2398 if (expsign ==
'-') {
2412inline static const char *
2413skip_ws(
const char *s,
const char *e)
2415 while (s < e && isspace((
unsigned char)*s))
2421parse_rat(
const char *s,
const char *
const e,
int strict,
int raise)
2424 VALUE num, den, nexp, dexp;
2427 sign = read_sign(&s, e);
2429 if (!read_num(&s, e, &num, &nexp)) {
2430 if (strict)
return Qnil;
2434 if (s < e && *s ==
'/') {
2436 if (!read_num(&s, e, &den, &dexp)) {
2437 if (strict)
return Qnil;
2440 else if (den ==
ZERO) {
2441 if (!
raise)
return Qnil;
2444 else if (strict && skip_ws(s, e) != e) {
2449 nurat_reduce(&num, &den);
2452 else if (strict && skip_ws(s, e) != e) {
2477 nurat_reduce(&num, &den);
2481 num = negate_num(num);
2490string_to_r_strict(
VALUE self,
int raise)
2498 if (!
raise)
return Qnil;
2504 if (!
raise)
return Qnil;
2539string_to_r(
VALUE self)
2557 num = parse_rat(s, s +
strlen(s), strict,
TRUE);
2565to_rational(
VALUE val)
2573 VALUE a1 = numv, a2 = denv;
2577 if (!
raise)
return Qnil;
2592 a1 = float_to_r(a1);
2595 a1 = string_to_r_strict(a1,
raise);
2600 a2 = float_to_r(a2);
2603 a2 = string_to_r_strict(a2,
raise);
2613 if (!k_integer_p(a1)) {
2619 return to_rational(a1);
2623 if (!k_numeric_p(a1)) {
2635 if (!k_numeric_p(a2)) {
2647 if ((k_numeric_p(a1) && k_numeric_p(a2)) &&
2648 (!f_integer_p(a1) || !f_integer_p(a2)))
2649 return f_div(a1, a2);
2661 if (!k_integer_p(a2) && !
raise)
return Qnil;
2678 return nurat_convert(
klass, a1, a2,
TRUE);
2728#define rb_intern(str) rb_intern_const(str)
VALUE rb_int2big(intptr_t n)
VALUE rb_define_class(const char *, VALUE)
Defines a top-level class.
VALUE rb_define_class_under(VALUE, const char *, VALUE)
Defines a class under the namespace of outer.
void rb_undef_method(VALUE, const char *)
VALUE rb_cNilClass
NilClass class.
VALUE rb_cObject
Object class.
VALUE rb_eFloatDomainError
void rb_raise(VALUE exc, const char *fmt,...)
void rb_set_errinfo(VALUE err)
Sets the current exception ($!) to the given value.
VALUE rb_protect(VALUE(*)(VALUE), VALUE, int *)
Protects a function call from potential global escapes from the function.
void rb_warn(const char *fmt,...)
VALUE rb_convert_type(VALUE, int, const char *, const char *)
Converts an object into another type.
int rb_opts_exception_p(VALUE opts, int default_value)
VALUE rb_convert_type_with_id(VALUE, int, const char *, ID)
VALUE rb_equal(VALUE, VALUE)
Same as Object#===, case equality.
VALUE rb_obj_is_kind_of(VALUE, VALUE)
Determines if obj is a kind of c.
VALUE rb_check_convert_type_with_id(VALUE, int, const char *, ID)
void rb_num_zerodiv(void)
VALUE rb_dbl_cmp(double a, double b)
#define k_exact_zero_p(x)
VALUE rb_rational_cmp(VALUE self, VALUE other)
VALUE rb_rational_uminus(VALUE self)
VALUE rb_gcd(VALUE self, VALUE other)
VALUE rb_rational_pow(VALUE self, VALUE other)
VALUE rb_lcm(VALUE self, VALUE other)
VALUE rb_Rational(VALUE x, VALUE y)
VALUE rb_rational_plus(VALUE self, VALUE other)
VALUE rb_cstr_to_rat(const char *s, int strict)
VALUE rb_float_denominator(VALUE self)
VALUE rb_gcd_normal(VALUE x, VALUE y)
#define INT_POSITIVE_P(x)
VALUE rb_rational_new(VALUE x, VALUE y)
VALUE rb_float_numerator(VALUE self)
VALUE rb_rational_num(VALUE rat)
VALUE rb_rational_floor(VALUE self, int ndigits)
VALUE rb_rational_reciprocal(VALUE x)
VALUE rb_rational_abs(VALUE self)
VALUE rb_rational_div(VALUE self, VALUE other)
VALUE rb_flt_rationalize(VALUE flt)
VALUE rb_rational_raw(VALUE x, VALUE y)
VALUE rb_rational_minus(VALUE self, VALUE other)
VALUE rb_flt_rationalize_with_prec(VALUE flt, VALUE prec)
VALUE rb_rational_canonicalize(VALUE x)
VALUE rb_gcdlcm(VALUE self, VALUE other)
VALUE rb_rational_den(VALUE rat)
VALUE rb_rational_mul(VALUE self, VALUE other)
VALUE rb_numeric_quo(VALUE x, VALUE y)