1
0
Fork 0
mirror of https://github.com/ruby/ruby.git synced 2022-11-09 12:17:21 -05:00

Fix Rational of Float

[ruby-core:89239] [Bug #15189]

git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@64897 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
nobu 2018-10-02 16:42:21 +00:00
parent 25ea4dc623
commit 603f95a0ed
5 changed files with 66 additions and 12 deletions

View file

@ -6207,6 +6207,7 @@ rb_big_pow(VALUE x, VALUE y)
again: again:
if (y == INT2FIX(0)) return INT2FIX(1); if (y == INT2FIX(0)) return INT2FIX(1);
if (y == INT2FIX(1)) return x;
if (RB_FLOAT_TYPE_P(y)) { if (RB_FLOAT_TYPE_P(y)) {
d = RFLOAT_VALUE(y); d = RFLOAT_VALUE(y);
if ((BIGNUM_NEGATIVE_P(x) && !BIGZEROP(x))) { if ((BIGNUM_NEGATIVE_P(x) && !BIGZEROP(x))) {
@ -6223,8 +6224,13 @@ rb_big_pow(VALUE x, VALUE y)
else if (FIXNUM_P(y)) { else if (FIXNUM_P(y)) {
yy = FIX2LONG(y); yy = FIX2LONG(y);
if (yy < 0) if (yy < 0) {
return rb_rational_raw(INT2FIX(1), rb_big_pow(x, INT2NUM(-yy))); x = rb_big_pow(x, INT2NUM(-yy));
if (RB_INTEGER_TYPE_P(x))
return rb_rational_raw(INT2FIX(1), x);
else
return DBL2NUM(1.0 / NUM2DBL(x));
}
else { else {
VALUE z = 0; VALUE z = 0;
SIGNED_VALUE mask; SIGNED_VALUE mask;

View file

@ -4015,7 +4015,8 @@ fix_pow(VALUE x, VALUE y)
} }
if (b < 0) { if (b < 0) {
if (a == 0) rb_num_zerodiv(); if (a == 0) rb_num_zerodiv();
return rb_rational_raw(INT2FIX(1), rb_int_pow(x, LONG2NUM(-b))); y = rb_int_pow(x, LONG2NUM(-b));
goto inverted;
} }
if (b == 0) return INT2FIX(1); if (b == 0) return INT2FIX(1);
@ -4035,10 +4036,10 @@ fix_pow(VALUE x, VALUE y)
if (BIGNUM_NEGATIVE_P(y)) { if (BIGNUM_NEGATIVE_P(y)) {
if (a == 0) rb_num_zerodiv(); if (a == 0) rb_num_zerodiv();
y = rb_int_pow(x, rb_big_uminus(y)); y = rb_int_pow(x, rb_big_uminus(y));
if (0 && RB_FLOAT_TYPE_P(y)) { inverted:
/* Maybe should return a Float */ if (RB_FLOAT_TYPE_P(y)) {
double d = pow((double)a, RFLOAT_VALUE(y)); double d = pow((double)a, RFLOAT_VALUE(y));
return DBL2NUM(d); return DBL2NUM(1.0 / d);
} }
return rb_rational_raw(INT2FIX(1), y); return rb_rational_raw(INT2FIX(1), y);
} }

View file

@ -3421,9 +3421,18 @@ rb_str_to_dbl(VALUE str, int badcheck)
#define big2dbl_without_to_f(x) rb_big2dbl(x) #define big2dbl_without_to_f(x) rb_big2dbl(x)
#define int2dbl_without_to_f(x) \ #define int2dbl_without_to_f(x) \
(FIXNUM_P(x) ? fix2dbl_without_to_f(x) : big2dbl_without_to_f(x)) (FIXNUM_P(x) ? fix2dbl_without_to_f(x) : big2dbl_without_to_f(x))
#define rat2dbl_without_to_f(x) \ static inline double
(int2dbl_without_to_f(rb_rational_num(x)) / \ rat2dbl_without_to_f(VALUE x)
int2dbl_without_to_f(rb_rational_den(x))) {
VALUE num = rb_rational_num(x);
VALUE den = rb_rational_den(x);
if (RB_INTEGER_TYPE_P(num) && RB_INTEGER_TYPE_P(den)) {
return int2dbl_without_to_f(num) / int2dbl_without_to_f(den);
}
else {
return NUM2DBL(num) / NUM2DBL(den);
}
}
#define special_const_to_float(val, pre, post) \ #define special_const_to_float(val, pre, post) \
switch (val) { \ switch (val) { \

View file

@ -696,7 +696,8 @@ f_addsub(VALUE self, VALUE anum, VALUE aden, VALUE bnum, VALUE bden, int k)
a = rb_int_idiv(bden, g); a = rb_int_idiv(bden, g);
den = rb_int_mul(a, b); den = rb_int_mul(a, b);
} }
else { else if (RB_INTEGER_TYPE_P(anum) && RB_INTEGER_TYPE_P(aden) &&
RB_INTEGER_TYPE_P(bnum) && RB_INTEGER_TYPE_P(bden)) {
VALUE g = f_gcd(aden, bden); VALUE g = f_gcd(aden, bden);
VALUE a = rb_int_mul(anum, rb_int_idiv(bden, g)); VALUE a = rb_int_mul(anum, rb_int_idiv(bden, g));
VALUE b = rb_int_mul(bnum, rb_int_idiv(aden, g)); VALUE b = rb_int_mul(bnum, rb_int_idiv(aden, g));
@ -713,6 +714,12 @@ f_addsub(VALUE self, VALUE anum, VALUE aden, VALUE bnum, VALUE bden, int k)
a = rb_int_idiv(bden, g); a = rb_int_idiv(bden, g);
den = rb_int_mul(a, b); den = rb_int_mul(a, b);
} }
else {
double a = NUM2DBL(anum) / NUM2DBL(aden);
double b = NUM2DBL(bnum) / NUM2DBL(bden);
double c = k == '+' ? a + b : a - b;
return DBL2NUM(c);
}
return f_rational_new_no_reduce2(CLASS_OF(self), num, den); return f_rational_new_no_reduce2(CLASS_OF(self), num, den);
} }
@ -1144,9 +1151,9 @@ static VALUE
nurat_eqeq_p(VALUE self, VALUE other) nurat_eqeq_p(VALUE self, VALUE other)
{ {
if (RB_INTEGER_TYPE_P(other)) { if (RB_INTEGER_TYPE_P(other)) {
{ get_dat1(self);
get_dat1(self);
if (RB_INTEGER_TYPE_P(dat->num) && RB_INTEGER_TYPE_P(dat->den)) {
if (INT_ZERO_P(dat->num) && INT_ZERO_P(other)) if (INT_ZERO_P(dat->num) && INT_ZERO_P(other))
return Qtrue; return Qtrue;
@ -1156,6 +1163,10 @@ nurat_eqeq_p(VALUE self, VALUE other)
return Qfalse; return Qfalse;
return rb_int_equal(dat->num, other); return rb_int_equal(dat->num, other);
} }
else {
const double d = nurat_to_double(self);
return f_boolcast(FIXNUM_ZERO_P(rb_dbl_cmp(d, NUM2DBL(other))));
}
} }
else if (RB_FLOAT_TYPE_P(other)) { else if (RB_FLOAT_TYPE_P(other)) {
const double d = nurat_to_double(self); const double d = nurat_to_double(self);
@ -1544,6 +1555,10 @@ static double
nurat_to_double(VALUE self) nurat_to_double(VALUE self)
{ {
get_dat1(self); get_dat1(self);
if (!RB_INTEGER_TYPE_P(dat->num) || !RB_INTEGER_TYPE_P(dat->den)) {
double d = NUM2DBL(dat->num) / NUM2DBL(dat->den);
return DBL2NUM(d);
}
return rb_int_fdiv_double(dat->num, dat->den); return rb_int_fdiv_double(dat->num, dat->den);
} }

View file

@ -27,6 +27,29 @@ class TestInteger < Test::Unit::TestCase
x = EnvUtil.suppress_warning {2 ** -0x4000000000000000} x = EnvUtil.suppress_warning {2 ** -0x4000000000000000}
assert_in_delta(0.0, (x / 2), Float::EPSILON) assert_in_delta(0.0, (x / 2), Float::EPSILON)
<<~EXPRS.each_line.with_index(__LINE__+1) do |expr, line|
crash01: 111r+11**-11111161111111
crash02: 1118111111111**-1111111111111111**1+1==11111
crash03: -1111111**-1111*11 - -1111111** -111111111
crash04: 1118111111111** -1111111111111111**1+11111111111**1 ===111
crash05: 11** -111155555555555555 -55 !=5-555
crash07: 1 + 111111111**-1111811111
crash08: 18111111111**-1111111111111111**1 + 1111111111**-1111**1
crash10: -7 - -1111111** -1111**11
crash12: 1118111111111** -1111111111111111**1 + 1111 - -1111111** -1111*111111111119
crash13: 1.0i - -1111111** -111111111
crash14: 11111**111111111**111111 * -11111111111111111111**-111111111111
crash15: ~1**1111 + -~1**~1**111
crash17: 11** -1111111**1111 /11i
crash18: 5555i**-5155 - -9111111**-1111**11
crash19: 111111*-11111111111111111111**-1111111111111111
crash20: 1111**111-11**-11111**11
crash21: 11**-10111111119-1i -1r
EXPRS
name, expr = expr.split(':', 2)
assert_ruby_status(%w"-W0", expr, name)
end
end end
def test_lshift def test_lshift