20 #if defined(HAVE_LIBGMP) && defined(HAVE_GMP_H) 25 #define ZERO INT2FIX(0) 26 #define ONE INT2FIX(1) 27 #define TWO INT2FIX(2) 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)) 36 static ID id_abs, id_idiv, id_integer_p,
id_to_i,
39 #define f_boolcast(x) ((x) ? Qtrue : Qfalse) 40 #define f_inspect rb_inspect 41 #define f_to_s rb_obj_as_string 45 f_##n(VALUE x, VALUE y)\ 47 return rb_funcall(x, (op), 1, y);\ 54 return rb_funcall(x, id_##n, 0);\ 159 #define f_expt10(x) rb_int_pow(INT2FIX(10), x) 175 #define f_nonzero_p(x) (!f_zero_p(x)) 193 f_minus_one_p(
VALUE x)
235 k_rational_p(
VALUE x)
240 #define k_exact_p(x) (!k_float_p(x)) 241 #define k_inexact_p(x) k_float_p(x) 243 #define k_exact_zero_p(x) (k_exact_p(x) && f_zero_p(x)) 244 #define k_exact_one_p(x) (k_exact_p(x) && f_one_p(x)) 278 #define f_gcd f_gcd_orig 282 i_gcd(
long x,
long y)
284 unsigned long u, v, t;
297 u = (
unsigned long)x;
298 v = (
unsigned long)y;
299 for (shift = 0; ((u | v) & 1) == 0; ++shift) {
319 return (
long)(u << shift);
357 return f_gcd_normal(x, y);
368 return rb_gcd_gmp(x, y);
371 return f_gcd_normal(x, y);
380 VALUE r = f_gcd_orig(x, y);
397 #define get_dat1(x) \ 398 struct RRational *dat = RRATIONAL(x) 400 #define get_dat2(x,y) \ 401 struct RRational *adat = RRATIONAL(x), *bdat = RRATIONAL(y) 403 #define RRATIONAL_SET_NUM(rat, n) RB_OBJ_WRITE((rat), &((struct RRational *)(rat))->num,(n)) 404 #define RRATIONAL_SET_DEN(rat, d) RB_OBJ_WRITE((rat), &((struct RRational *)(rat))->den,(d)) 419 nurat_s_alloc(
VALUE klass)
421 return nurat_s_new_internal(klass,
ZERO,
ONE);
432 if (!k_integer_p(num))
437 if (!k_integer_p(num))
439 if (!k_integer_p(den))
452 return nurat_s_new_internal(klass, num, den);
459 return nurat_s_new_internal(klass, x,
ONE);
462 #ifdef CANONICALIZATION_FOR_MATHN 470 nurat_canonicalization(
int f)
475 # define canonicalization 0 479 nurat_int_check(
VALUE num)
482 if (!k_numeric_p(num) || !f_integer_p(num))
488 nurat_int_value(
VALUE num)
490 nurat_int_check(num);
491 if (!k_integer_p(num))
514 if (*x ==
ONE || *y ==
ONE)
return;
523 nurat_canonicalize(&num, &den);
524 nurat_reduce(&num, &den);
528 return nurat_s_new_internal(klass, num, den);
532 nurat_s_canonicalize_internal_no_reduce(
VALUE klass,
VALUE num,
VALUE den)
534 nurat_canonicalize(&num, &den);
538 return nurat_s_new_internal(klass, num, den);
548 num = nurat_int_value(num);
552 num = nurat_int_value(num);
553 den = nurat_int_value(den);
557 return nurat_s_canonicalize_internal(klass, num, den);
565 return nurat_s_canonicalize_internal(klass, x, y);
573 return nurat_s_canonicalize_internal_no_reduce(klass, x, y);
630 nurat_numerator(
VALUE self)
648 nurat_denominator(
VALUE self)
670 #define f_imul f_imul_orig 674 f_imul(
long a,
long b)
678 if (a == 0 || b == 0)
696 f_imul(
long x,
long y)
698 VALUE r = f_imul_orig(x, y);
715 long ig = i_gcd(ad, bd);
718 VALUE a = f_imul(an, bd / ig);
719 VALUE b = f_imul(bn, ad / ig);
734 VALUE g = f_gcd(aden, bden);
750 return f_rational_new_no_reduce2(
CLASS_OF(
self), num, den);
753 static double nurat_to_double(
VALUE self);
773 return f_rational_new_no_reduce2(
CLASS_OF(
self),
785 return f_addsub(
self,
786 adat->num, adat->den,
787 bdat->num, bdat->den,
'+');
814 return f_rational_new_no_reduce2(
CLASS_OF(
self),
826 return f_addsub(
self,
827 adat->num, adat->den,
828 bdat->num, bdat->den,
'-');
865 long g1 = i_gcd(an, bd);
866 long g2 = i_gcd(ad, bn);
868 num = f_imul(an / g1, bn / g2);
869 den = f_imul(ad / g2, bd / g1);
872 VALUE g1 = f_gcd(anum, bden);
873 VALUE g2 = f_gcd(aden, bnum);
878 return f_rational_new_no_reduce2(
CLASS_OF(
self), num, den);
900 return f_muldiv(
self,
912 return f_muldiv(
self,
913 adat->num, adat->den,
914 bdat->num, bdat->den,
'*');
944 return f_muldiv(
self,
958 return f_rational_new_no_reduce2(
CLASS_OF(
self),
959 bdat->den, bdat->num);
961 return f_muldiv(
self,
962 adat->num, adat->den,
963 bdat->num, bdat->den,
'/');
988 return DBL2NUM(nurat_to_double(
self) / 0.0);
990 return nurat_to_f(
self);
991 div = nurat_div(
self, other);
993 return nurat_to_f(div);
1000 f_odd_p(
VALUE integer)
1027 if (k_rational_p(other)) {
1030 if (f_one_p(dat->den))
1035 if (k_numeric_p(other) &&
k_exact_p(other)) {
1037 if (f_one_p(dat->den)) {
1038 if (f_one_p(dat->num)) {
1042 return f_rational_new_bang1(
CLASS_OF(
self),
INT2FIX(f_odd_p(other) ? -1 : 1));
1082 return f_rational_new2(
CLASS_OF(
self), num, den);
1086 rb_warn(
"in a**b, b may be too big");
1123 other = f_rational_new_bang1(
CLASS_OF(
self), other);
1124 goto other_is_rational;
1184 const double d = nurat_to_double(
self);
1234 return f_idiv(
self, other);
1256 nurat_true(
VALUE self)
1269 nurat_positive_p(
VALUE self)
1282 nurat_negative_p(
VALUE self)
1307 return nurat_s_canonicalize_internal_no_reduce(
CLASS_OF(
self), num, dat->den);
1313 nurat_floor(
VALUE self)
1320 nurat_ceil(
VALUE self)
1341 nurat_truncate(
VALUE self)
1350 nurat_round_half_up(
VALUE self)
1374 nurat_round_half_down(
VALUE self)
1399 nurat_round_half_even(
VALUE self)
1431 return (*func)(
self);
1435 if (!k_integer_p(n))
1439 s = nurat_mul(
self, b);
1447 if (!k_rational_p(s)) {
1448 s = f_rational_new_bang1(
CLASS_OF(
self), s);
1453 s = nurat_div(f_rational_new_bang1(
CLASS_OF(
self), s), b);
1456 s = nurat_truncate(s);
1488 return f_round_common(
argc,
argv,
self, nurat_floor);
1518 return f_round_common(
argc,
argv,
self, nurat_ceil);
1548 return f_round_common(
argc,
argv,
self, nurat_truncate);
1596 return f_round_common(
argc,
argv,
self, round_func);
1600 nurat_to_double(
VALUE self)
1618 nurat_to_f(
VALUE self)
1620 return DBL2NUM(nurat_to_double(
self));
1633 nurat_to_r(
VALUE self)
1638 #define id_ceil rb_intern("ceil") 1639 #define f_ceil(x) rb_funcall((x), id_ceil, 0) 1641 #define id_quo rb_intern("quo") 1642 #define f_quo(x,y) rb_funcall((x), id_quo, 1, (y)) 1644 #define f_reciprocal(x) f_quo(ONE, (x)) 1708 VALUE c, k, t, p0, p1, p2, q0, q1, q2;
1751 VALUE e, a, b, p, q;
1756 if (nurat_negative_p(
self))
1767 nurat_rationalize_internal(a, b, &p, &q);
1768 return f_rational_new2(
CLASS_OF(
self), p, q);
1773 nurat_hash(
VALUE self)
1793 s = (*func)(dat->num);
1811 nurat_to_s(
VALUE self)
1813 return f_format(
self,
f_to_s);
1827 nurat_inspect(
VALUE self)
1840 nurat_dumper(
VALUE self)
1854 nurat_int_check(num);
1855 nurat_int_check(den);
1856 nurat_canonicalize(&num, &den);
1866 nurat_marshal_dump(
VALUE self)
1891 nurat_int_check(num);
1892 nurat_int_check(den);
1893 nurat_canonicalize(&num, &den);
1906 return f_rational_new_no_reduce2(
CLASS_OF(x), dat->den, dat->num);
1924 other = nurat_int_value(other);
1925 return f_gcd(
self, other);
1943 other = nurat_int_value(other);
1944 return f_lcm(
self, other);
1962 other = nurat_int_value(other);
1963 return rb_assoc_new(f_gcd(
self, other), f_lcm(
self, other));
1975 return nurat_s_canonicalize_internal(
rb_cRational, x, y);
1990 return nurat_numerator(rat);
1996 return nurat_denominator(rat);
1999 #define id_numerator rb_intern("numerator") 2000 #define f_numerator(x) rb_funcall((x), id_numerator, 0) 2002 #define id_denominator rb_intern("denominator") 2003 #define f_denominator(x) rb_funcall((x), id_denominator, 0) 2005 #define id_to_r rb_intern("to_r") 2006 #define f_to_r(x) rb_funcall((x), id_to_r, 0) 2015 numeric_numerator(
VALUE self)
2027 numeric_denominator(
VALUE self)
2054 return nurat_div(x, y);
2065 integer_numerator(
VALUE self)
2077 integer_denominator(
VALUE self)
2096 float_numerator(
VALUE self)
2102 r = float_to_r(
self);
2106 return nurat_numerator(r);
2119 float_denominator(
VALUE self)
2125 r = float_to_r(
self);
2129 return nurat_denominator(r);
2139 nilclass_to_r(
VALUE self)
2155 return nilclass_to_r(
self);
2168 integer_to_r(
VALUE self)
2184 return integer_to_r(
self);
2202 float_decode(
VALUE self)
2206 float_decode_internal(
self, &f, &n);
2232 float_to_r(
VALUE self)
2236 float_decode_internal(
self, &f, &n);
2259 VALUE e, a, b, p, q;
2266 return float_to_r(flt);
2268 nurat_rationalize_internal(a, b, &p, &q);
2277 float_decode_internal(flt, &f, &n);
2283 VALUE two_times_f, den;
2293 VALUE radix_times_f, den;
2303 if (nurat_eqeq_p(a, b))
2304 return float_to_r(flt);
2306 nurat_rationalize_internal(a, b, &p, &q);
2348 return (c ==
'-' || c ==
'+');
2352 read_sign(
const char **s,
const char *
const e)
2356 if (*s < e &&
issign(**s)) {
2366 return (c ==
'e' || c ==
'E');
2370 read_num(
const char **s,
const char *
const end,
VALUE *num,
VALUE *
div)
2373 int expsign = 0, ok = 0;
2378 if (*s < end && **s !=
'.') {
2388 if (*s < end && **s ==
'.') {
2407 if (ok && *s + 1 < end && islettere(**s)) {
2409 expsign = read_sign(s, end);
2416 if (expsign ==
'-') {
2436 inline static const char *
2437 skip_ws(
const char *s,
const char *e)
2439 while (s < e && isspace((
unsigned char)*s))
2445 parse_rat(
const char *s,
const char *
const e,
int strict)
2448 VALUE num, den, ndiv, ddiv;
2451 sign = read_sign(&s, e);
2453 if (!read_num(&s, e, &num, &ndiv)) {
2454 if (strict)
return Qnil;
2457 nurat_reduce(&num, &ndiv);
2459 if (s < e && *s ==
'/') {
2461 if (!read_num(&s, e, &den, &ddiv)) {
2462 if (strict)
return Qnil;
2465 else if (den ==
ZERO) {
2468 else if (strict && skip_ws(s, e) != e) {
2472 nurat_reduce(&den, &ddiv);
2473 nurat_reduce(&num, &den);
2474 nurat_reduce(&ndiv, &ddiv);
2479 else if (strict && skip_ws(s, e) != e) {
2499 string_to_r_strict(
VALUE self)
2545 string_to_r(
VALUE self)
2563 num = parse_rat(s, s +
strlen(s), strict);
2573 VALUE a1, a2, backref;
2594 a1 = float_to_r(a1);
2597 a1 = string_to_r_strict(a1);
2601 a2 = float_to_r(a2);
2604 a2 = string_to_r_strict(a2);
2615 if (!(k_numeric_p(a1) && k_integer_p(a1)))
2619 if ((k_numeric_p(a1) && k_numeric_p(a2)) &&
2620 (!f_integer_p(a1) || !f_integer_p(a2)))
2621 return f_div(a1, a2);
2628 return nurat_s_new(
argc, argv2, klass);
2679 #define rb_intern(str) rb_intern_const(str) 2681 assert(fprintf(stderr,
"assert() is now active\n"));
RUBY_EXTERN VALUE rb_cString
VALUE rb_int_plus(VALUE x, VALUE y)
VALUE rb_int_cmp(VALUE x, VALUE y)
VALUE rb_rational_plus(VALUE self, VALUE other)
VALUE rb_int_uminus(VALUE num)
#define rb_rational_new2(x, y)
void rb_warn(const char *fmt,...)
RUBY_EXTERN VALUE rb_cFloat
VALUE rb_num_coerce_bin(VALUE, VALUE, ID)
size_t strlen(const char *)
void rb_backref_set(VALUE)
VALUE rb_lcm(VALUE self, VALUE other)
#define RGENGC_WB_PROTECTED_RATIONAL
#define rb_usascii_str_new2
void rb_raise(VALUE exc, const char *fmt,...)
VALUE rb_gcd(VALUE self, VALUE other)
VALUE rb_int_equal(VALUE x, VALUE y)
void rb_define_private_method(VALUE klass, const char *name, VALUE(*func)(ANYARGS), int argc)
#define RRATIONAL_SET_NUM(rat, n)
void rb_check_trusted(VALUE obj)
void rb_must_asciicompat(VALUE)
VALUE rb_dbl_cmp(double a, double b)
#define k_exact_zero_p(x)
VALUE rb_str_concat(VALUE, VALUE)
st_index_t rb_memhash(const void *ptr, long len)
VALUE rb_rational_uminus(VALUE self)
VALUE rb_funcall(VALUE, ID, int,...)
Calls a method.
VALUE rb_int_minus(VALUE x, VALUE y)
VALUE rb_backref_get(void)
VALUE rb_int_mul(VALUE x, VALUE y)
VALUE rb_define_class_under(VALUE outer, const char *name, VALUE super)
Defines a class under the namespace of outer.
VALUE rb_ivar_get(VALUE, ID)
#define MUL_OVERFLOW_LONG_P(a, b)
void rb_define_alloc_func(VALUE, rb_alloc_func_t)
VALUE rb_int_divmod(VALUE x, VALUE y)
void rb_define_global_function(const char *name, VALUE(*func)(ANYARGS), int argc)
Defines a global function.
double rb_int_fdiv_double(VALUE x, VALUE y)
void rb_undef_method(VALUE klass, const char *name)
const char * rb_obj_classname(VALUE)
enum ruby_num_rounding_mode rb_num_get_rounding_option(VALUE opts)
#define NEWOBJ_OF(obj, type, klass, flags)
VALUE rb_numeric_quo(VALUE x, VALUE y)
#define RB_TYPE_P(obj, type)
VALUE rb_obj_is_kind_of(VALUE, VALUE)
call-seq: obj.is_a?(class) -> true or false obj.kind_of?(class) -> true or false
VALUE rb_rational_raw(VALUE x, VALUE y)
VALUE rb_int_idiv(VALUE x, VALUE y)
VALUE rb_equal(VALUE, VALUE)
call-seq: obj === other -> true or false
#define rb_rational_raw1(x)
VALUE rb_dbl2big(double d)
VALUE rb_convert_type_with_id(VALUE, int, const char *, ID)
RUBY_EXTERN VALUE rb_cObject
VALUE rb_str_to_inum(VALUE str, int base, int badcheck)
VALUE rb_int_parse_cstr(const char *str, ssize_t len, char **endp, size_t *ndigits, int base, int flags)
VALUE rb_str_cat2(VALUE, const char *)
#define INT_NEGATIVE_P(x)
int rb_num_negative_p(VALUE)
VALUE rb_define_class(const char *name, VALUE super)
Defines a top-level class.
VALUE rb_big_new(size_t len, int sign)
VALUE rb_int_and(VALUE x, VALUE y)
VALUE rb_gcdlcm(VALUE self, VALUE other)
VALUE rb_cstr_to_rat(const char *s, int strict)
#define ROUND_FUNC(mode, name)
VALUE rb_int_lshift(VALUE x, VALUE y)
#define RUBY_FUNC_EXPORTED
RUBY_EXTERN int isinf(double)
#define OBJ_FREEZE_RAW(x)
void rb_num_zerodiv(void)
VALUE rb_int_abs(VALUE num)
#define rb_rational_new1(x)
VALUE rb_int_modulo(VALUE x, VALUE y)
int rb_scan_args(int argc, const VALUE *argv, const char *fmt,...)
VALUE rb_ivar_set(VALUE, ID, VALUE)
VALUE rb_assoc_new(VALUE car, VALUE cdr)
VALUE rb_big_mul(VALUE x, VALUE y)
RUBY_EXTERN VALUE rb_cInteger
VALUE rb_int_div(VALUE x, VALUE y)
void rb_match_busy(VALUE)
VALUE rb_Complex(VALUE x, VALUE y)
VALUE rb_rational_num(VALUE rat)
RUBY_EXTERN VALUE rb_cNumeric
#define RB_FLOAT_TYPE_P(obj)
#define RARRAY_AREF(a, i)
VALUE rb_float_pow(VALUE x, VALUE y)
VALUE rb_rational_abs(VALUE self)
VALUE rb_rational_new(VALUE x, VALUE y)
#define FIXNUM_ZERO_P(num)
VALUE rb_convert_type(VALUE, int, const char *, const char *)
Converts an object into another type.
VALUE rb_big_norm(VALUE x)
void rb_marshal_define_compat(VALUE newclass, VALUE oldclass, VALUE(*dumper)(VALUE), VALUE(*loader)(VALUE, VALUE))
VALUE rb_rational_cmp(VALUE self, VALUE other)
VALUE rb_int_pow(VALUE x, VALUE y)
VALUE rb_Rational(VALUE x, VALUE y)
VALUE rb_int2big(SIGNED_VALUE n)
RUBY_EXTERN VALUE rb_eFloatDomainError
VALUE rb_rational_den(VALUE rat)
#define rb_check_frozen(obj)
void rb_copy_generic_ivar(VALUE, VALUE)
#define RB_INTEGER_TYPE_P(obj)
#define RRATIONAL_SET_DEN(rat, d)
void rb_define_method(VALUE klass, const char *name, VALUE(*func)(ANYARGS), int argc)
void rb_provide(const char *)
RUBY_EXTERN VALUE rb_cNilClass
VALUE rb_rational_reciprocal(VALUE x)
VALUE rb_flt_rationalize_with_prec(VALUE flt, VALUE prec)
VALUE rb_num_coerce_cmp(VALUE, VALUE, ID)
#define INT_POSITIVE_P(x)
VALUE rb_gcd_normal(VALUE x, VALUE y)
VALUE rb_flt_rationalize(VALUE flt)