Ruby
2.7.2p137(2020-10-01revision5445e0435260b449decf2ac16f9d09bae3cafe72)
|
Go to the documentation of this file.
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_integer_p,
40 #define id_to_i idTo_i
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))
182 f_minus_one_p(
VALUE x)
224 k_rational_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
271 i_gcd(
long x,
long y)
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);
386 #define get_dat1(x) \
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
420 nurat_canonicalization(
int f)
425 # define canonicalization 0
429 nurat_int_check(
VALUE num)
432 if (!k_numeric_p(num) || !f_integer_p(num))
438 nurat_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);
593 nurat_numerator(
VALUE self)
611 nurat_denominator(
VALUE self)
633 #define f_imul f_imul_orig
637 f_imul(
long a,
long b)
641 if (a == 0 || b == 0)
659 f_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);
723 static 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);
971 div = nurat_div(
self, other);
973 return nurat_to_f(
div);
980 f_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);
1222 nurat_positive_p(
VALUE self)
1235 nurat_negative_p(
VALUE self)
1260 return nurat_s_canonicalize_internal_no_reduce(
CLASS_OF(
self), num, dat->den);
1266 nurat_floor(
VALUE self)
1273 nurat_ceil(
VALUE self)
1294 nurat_truncate(
VALUE self)
1303 nurat_round_half_up(
VALUE self)
1327 nurat_round_half_down(
VALUE self)
1352 nurat_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);
1406 s = nurat_div(f_rational_new_bang1(
CLASS_OF(
self), s), b);
1409 s = nurat_truncate(s);
1441 return f_round_common(
argc,
argv,
self, nurat_floor);
1471 return f_round_common(
argc,
argv,
self, nurat_ceil);
1501 return f_round_common(
argc,
argv,
self, nurat_truncate);
1549 return f_round_common(
argc,
argv,
self, round_func);
1553 nurat_to_double(
VALUE self)
1574 nurat_to_f(
VALUE self)
1576 return DBL2NUM(nurat_to_double(
self));
1589 nurat_to_r(
VALUE self)
1594 #define id_ceil rb_intern("ceil")
1606 #define id_quo idQuo
1618 #define f_reciprocal(x) f_quo(ONE, (x))
1682 VALUE c, k, t, p0, p1, p2, q0, q1, q2;
1725 VALUE e, a, b, p, q;
1730 if (nurat_negative_p(
self))
1740 nurat_rationalize_internal(a, b, &p, &q);
1741 return f_rational_new2(
CLASS_OF(
self), p, q);
1746 nurat_hash(
VALUE self)
1766 s = (*func)(dat->num);
1784 nurat_to_s(
VALUE self)
1786 return f_format(
self,
f_to_s);
1800 nurat_inspect(
VALUE self)
1813 nurat_dumper(
VALUE self)
1827 nurat_int_check(num);
1828 nurat_int_check(den);
1829 nurat_canonicalize(&num, &den);
1839 nurat_marshal_dump(
VALUE self)
1863 nurat_int_check(num);
1864 nurat_int_check(den);
1865 nurat_canonicalize(&num, &den);
1878 return f_rational_new_no_reduce2(
CLASS_OF(x), dat->den, dat->num);
1896 other = nurat_int_value(other);
1897 return f_gcd(
self, other);
1915 other = nurat_int_value(other);
1916 return f_lcm(
self, other);
1934 other = nurat_int_value(other);
1935 return rb_assoc_new(f_gcd(
self, other), f_lcm(
self, other));
1947 return nurat_s_canonicalize_internal(
rb_cRational, x, y);
1962 return nurat_numerator(rat);
1968 return nurat_denominator(rat);
1971 #define id_numerator rb_intern("numerator")
1972 #define f_numerator(x) rb_funcall((x), id_numerator, 0)
1974 #define id_denominator rb_intern("denominator")
1975 #define f_denominator(x) rb_funcall((x), id_denominator, 0)
1977 #define id_to_r idTo_r
1978 #define f_to_r(x) rb_funcall((x), id_to_r, 0)
1987 numeric_numerator(
VALUE self)
1999 numeric_denominator(
VALUE self)
2030 return nurat_div(x, y);
2038 if (f_one_p(dat->den))
return dat->num;
2050 integer_numerator(
VALUE self)
2062 integer_denominator(
VALUE self)
2087 r = float_to_r(
self);
2091 return nurat_numerator(r);
2110 r = float_to_r(
self);
2114 return nurat_denominator(r);
2124 nilclass_to_r(
VALUE self)
2140 return nilclass_to_r(
self);
2153 integer_to_r(
VALUE self)
2169 return integer_to_r(
self);
2173 float_decode_internal(
VALUE self,
VALUE *rf,
int *
n)
2204 float_to_r(
VALUE self)
2209 float_decode_internal(
self, &
f, &
n);
2228 VALUE e, a, b, p, q;
2235 return float_to_r(flt);
2237 nurat_rationalize_internal(a, b, &p, &q);
2247 float_decode_internal(flt, &
f, &
n);
2252 VALUE radix_times_f, den;
2255 #if FLT_RADIX == 2 && 0
2265 if (nurat_eqeq_p(a, b))
2266 return float_to_r(flt);
2268 nurat_rationalize_internal(a, b, &p, &q);
2307 return (c ==
'-' || c ==
'+');
2311 read_sign(
const char **s,
const char *
const e)
2315 if (*s < e &&
issign(**s)) {
2325 return (c ==
'e' || c ==
'E');
2329 negate_num(
VALUE num)
2341 read_num(
const char **s,
const char *
const end,
VALUE *num,
VALUE *nexp)
2344 int expsign = 0, ok = 0;
2349 if (*s < end && **s !=
'.') {
2359 if (*s < end && **s ==
'.') {
2377 if (ok && *s + 1 < end && islettere(**s)) {
2379 expsign = read_sign(s, end);
2386 if (expsign ==
'-') {
2400 inline static const char *
2401 skip_ws(
const char *s,
const char *e)
2403 while (s < e && isspace((
unsigned char)*s))
2409 parse_rat(
const char *s,
const char *
const e,
int strict,
int raise)
2412 VALUE num, den, nexp, dexp;
2415 sign = read_sign(&s, e);
2417 if (!read_num(&s, e, &num, &nexp)) {
2418 if (strict)
return Qnil;
2422 if (s < e && *s ==
'/') {
2424 if (!read_num(&s, e, &den, &dexp)) {
2425 if (strict)
return Qnil;
2428 else if (den ==
ZERO) {
2429 if (!
raise)
return Qnil;
2432 else if (strict && skip_ws(s, e) != e) {
2437 nurat_reduce(&num, &den);
2440 else if (strict && skip_ws(s, e) != e) {
2465 nurat_reduce(&num, &den);
2469 num = negate_num(num);
2478 string_to_r_strict(
VALUE self,
int raise)
2486 if (!
raise)
return Qnil;
2492 if (!
raise)
return Qnil;
2527 string_to_r(
VALUE self)
2545 num = parse_rat(s, s +
strlen(s), strict,
TRUE);
2553 to_rational(
VALUE val)
2561 VALUE a1 = numv, a2 = denv;
2565 if (!
raise)
return Qnil;
2580 a1 = float_to_r(a1);
2583 a1 = string_to_r_strict(a1,
raise);
2588 a2 = float_to_r(a2);
2591 a2 = string_to_r_strict(a2,
raise);
2601 if (!k_integer_p(a1)) {
2607 return to_rational(a1);
2611 if (!k_numeric_p(a1)) {
2623 if (!k_numeric_p(a2)) {
2635 if ((k_numeric_p(a1) && k_numeric_p(a2)) &&
2636 (!f_integer_p(a1) || !f_integer_p(a2)))
2637 return f_div(a1, a2);
2649 if (!k_integer_p(a2) && !
raise)
return Qnil;
2666 return nurat_convert(
klass, a1, a2,
TRUE);
2716 #define rb_intern(str) rb_intern_const(str)
VALUE rb_rational_canonicalize(VALUE x)
#define INT_NEGATIVE_P(x)
#define RGENGC_WB_PROTECTED_RATIONAL
VALUE rb_str_concat(VALUE, VALUE)
VALUE rb_define_class(const char *name, VALUE super)
Defines a top-level class.
VALUE rb_check_convert_type_with_id(VALUE, int, const char *, ID)
VALUE rb_assoc_new(VALUE car, VALUE cdr)
int rb_opts_exception_p(VALUE opts, int default_value)
VALUE rb_rational_pow(VALUE self, VALUE other)
void rb_warn(const char *fmt,...)
VALUE rb_int_abs(VALUE num)
RUBY_EXTERN VALUE rb_cNumeric
enum ruby_num_rounding_mode rb_num_get_rounding_option(VALUE opts)
#define ROUND_FUNC(mode, name)
VALUE rb_float_denominator(VALUE self)
VALUE rb_dbl_cmp(double a, double b)
VALUE rb_dbl2big(double d)
void rb_marshal_define_compat(VALUE newclass, VALUE oldclass, VALUE(*dumper)(VALUE), VALUE(*loader)(VALUE, VALUE))
VALUE rb_int2big(intptr_t n)
VALUE rb_complex_div(VALUE self, VALUE other)
VALUE rb_equal(VALUE, VALUE)
Same as Object#===, case equality.
RUBY_EXTERN VALUE rb_int_positive_pow(long x, unsigned long y)
VALUE rb_int_parse_cstr(const char *str, ssize_t len, char **endp, size_t *ndigits, int base, int flags)
#define MUL_OVERFLOW_LONG_P(a, b)
#define RB_TYPE_P(obj, type)
#define k_exact_zero_p(x)
#define FIXNUM_ZERO_P(num)
VALUE rb_rational_uminus(VALUE self)
int rb_num_negative_p(VALUE)
RUBY_EXTERN VALUE rb_cFloat
void rb_define_global_function(const char *name, VALUE(*func)(ANYARGS), int argc)
Defines a global function.
#define rb_rational_raw1(x)
VALUE rb_float_pow(VALUE x, VALUE y)
VALUE rb_int_pow(VALUE x, VALUE y)
VALUE rb_rational_num(VALUE rat)
void rb_define_method(VALUE klass, const char *name, VALUE(*func)(ANYARGS), int argc)
VALUE rb_int_and(VALUE x, VALUE y)
VALUE rb_int_lshift(VALUE x, VALUE y)
RUBY_EXTERN VALUE rb_cInteger
VALUE rb_int_idiv(VALUE x, VALUE y)
size_t strlen(const char *)
VALUE rb_num_coerce_cmp(VALUE, VALUE, ID)
VALUE rb_big_new(size_t len, int sign)
VALUE rb_rational_reciprocal(VALUE x)
VALUE rb_int_uminus(VALUE num)
void rb_undef_method(VALUE klass, const char *name)
VALUE rb_protect(VALUE(*proc)(VALUE), VALUE data, int *pstate)
Protects a function call from potential global escapes from the function.
#define RUBY_FUNC_EXPORTED
st_index_t rb_memhash(const void *ptr, long len)
void rb_raise(VALUE exc, const char *fmt,...)
VALUE rb_ivar_get(VALUE, ID)
VALUE rb_str_to_inum(VALUE str, int base, int badcheck)
double rb_int_fdiv_double(VALUE x, VALUE y)
#define rb_rational_new2(x, y)
#define RRATIONAL_SET_NUM(rat, n)
RUBY_EXTERN VALUE rb_cNilClass
VALUE rb_int_mul(VALUE x, VALUE y)
void rb_must_asciicompat(VALUE)
#define rb_check_frozen(obj)
VALUE rb_int_div(VALUE x, VALUE y)
VALUE rb_convert_type_with_id(VALUE, int, const char *, ID)
VALUE rb_rational_den(VALUE rat)
VALUE rb_cstr_to_rat(const char *s, int strict)
RUBY_EXTERN VALUE rb_eFloatDomainError
VALUE rb_Complex(VALUE x, VALUE y)
#define RARRAY_AREF(a, i)
RUBY_EXTERN double nan(const char *)
void rb_copy_generic_ivar(VALUE, VALUE)
#define RRATIONAL_SET_DEN(rat, d)
VALUE rb_gcd_normal(VALUE x, VALUE y)
VALUE rb_num_coerce_bin(VALUE, VALUE, ID)
VALUE rb_int_modulo(VALUE x, VALUE y)
void rb_num_zerodiv(void)
VALUE rb_int_divmod(VALUE x, VALUE y)
VALUE rb_int_equal(VALUE x, VALUE y)
RUBY_EXTERN VALUE rb_cObject
VALUE rb_rational_plus(VALUE self, VALUE other)
void rb_provide(const char *)
void rb_set_errinfo(VALUE err)
Sets the current exception ($!) to the given value.
VALUE rb_float_numerator(VALUE self)
VALUE rb_lcm(VALUE self, VALUE other)
VALUE rb_rational_raw(VALUE x, VALUE y)
VALUE rb_convert_type(VALUE, int, const char *, const char *)
Converts an object into another type.
VALUE rb_big_mul(VALUE x, VALUE y)
VALUE rb_rational_new(VALUE x, VALUE y)
RUBY_EXTERN VALUE rb_cString
VALUE rb_Rational(VALUE x, VALUE y)
VALUE rb_gcd(VALUE self, VALUE other)
VALUE rb_numeric_quo(VALUE x, VALUE y)
#define OBJ_FREEZE_RAW(x)
VALUE rb_flo_div_flo(VALUE x, VALUE y)
const char * rb_obj_classname(VALUE)
VALUE rb_rational_cmp(VALUE self, VALUE other)
VALUE rb_rational_abs(VALUE self)
VALUE rb_big_norm(VALUE x)
#define rb_usascii_str_new2
VALUE rb_int_cmp(VALUE x, VALUE y)
VALUE rb_ivar_set(VALUE, ID, VALUE)
VALUE rb_define_class_under(VALUE outer, const char *name, VALUE super)
Defines a class under the namespace of outer.
#define rb_rational_new1(x)
VALUE rb_gcdlcm(VALUE self, VALUE other)
#define RB_INTEGER_TYPE_P(obj)
#define NEWOBJ_OF(obj, type, klass, flags)
VALUE rb_float_ceil(VALUE num, int ndigits)
VALUE rb_int_plus(VALUE x, VALUE y)
void rb_define_private_method(VALUE klass, const char *name, VALUE(*func)(ANYARGS), int argc)
VALUE rb_rational_mul(VALUE self, VALUE other)
VALUE rb_obj_is_kind_of(VALUE, VALUE)
Determines if obj is a kind of c.
void rb_define_alloc_func(VALUE, rb_alloc_func_t)
#define RB_FLOAT_TYPE_P(obj)
@ RB_INT_PARSE_UNDERSCORE
VALUE rb_int_minus(VALUE x, VALUE y)
VALUE rb_flt_rationalize_with_prec(VALUE flt, VALUE prec)
#define INT_POSITIVE_P(x)
VALUE rb_flt_rationalize(VALUE flt)