зеркало из https://github.com/github/ruby.git
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:
Родитель
25ea4dc623
Коммит
603f95a0ed
10
bignum.c
10
bignum.c
|
@ -6207,6 +6207,7 @@ rb_big_pow(VALUE x, VALUE y)
|
|||
|
||||
again:
|
||||
if (y == INT2FIX(0)) return INT2FIX(1);
|
||||
if (y == INT2FIX(1)) return x;
|
||||
if (RB_FLOAT_TYPE_P(y)) {
|
||||
d = RFLOAT_VALUE(y);
|
||||
if ((BIGNUM_NEGATIVE_P(x) && !BIGZEROP(x))) {
|
||||
|
@ -6223,8 +6224,13 @@ rb_big_pow(VALUE x, VALUE y)
|
|||
else if (FIXNUM_P(y)) {
|
||||
yy = FIX2LONG(y);
|
||||
|
||||
if (yy < 0)
|
||||
return rb_rational_raw(INT2FIX(1), rb_big_pow(x, INT2NUM(-yy)));
|
||||
if (yy < 0) {
|
||||
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 {
|
||||
VALUE z = 0;
|
||||
SIGNED_VALUE mask;
|
||||
|
|
|
@ -4015,7 +4015,8 @@ fix_pow(VALUE x, VALUE y)
|
|||
}
|
||||
if (b < 0) {
|
||||
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);
|
||||
|
@ -4035,10 +4036,10 @@ fix_pow(VALUE x, VALUE y)
|
|||
if (BIGNUM_NEGATIVE_P(y)) {
|
||||
if (a == 0) rb_num_zerodiv();
|
||||
y = rb_int_pow(x, rb_big_uminus(y));
|
||||
if (0 && RB_FLOAT_TYPE_P(y)) {
|
||||
/* Maybe should return a Float */
|
||||
inverted:
|
||||
if (RB_FLOAT_TYPE_P(y)) {
|
||||
double d = pow((double)a, RFLOAT_VALUE(y));
|
||||
return DBL2NUM(d);
|
||||
return DBL2NUM(1.0 / d);
|
||||
}
|
||||
return rb_rational_raw(INT2FIX(1), y);
|
||||
}
|
||||
|
|
15
object.c
15
object.c
|
@ -3421,9 +3421,18 @@ rb_str_to_dbl(VALUE str, int badcheck)
|
|||
#define big2dbl_without_to_f(x) rb_big2dbl(x)
|
||||
#define int2dbl_without_to_f(x) \
|
||||
(FIXNUM_P(x) ? fix2dbl_without_to_f(x) : big2dbl_without_to_f(x))
|
||||
#define rat2dbl_without_to_f(x) \
|
||||
(int2dbl_without_to_f(rb_rational_num(x)) / \
|
||||
int2dbl_without_to_f(rb_rational_den(x)))
|
||||
static inline double
|
||||
rat2dbl_without_to_f(VALUE 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) \
|
||||
switch (val) { \
|
||||
|
|
21
rational.c
21
rational.c
|
@ -696,7 +696,8 @@ f_addsub(VALUE self, VALUE anum, VALUE aden, VALUE bnum, VALUE bden, int k)
|
|||
a = rb_int_idiv(bden, g);
|
||||
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 a = rb_int_mul(anum, rb_int_idiv(bden, 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);
|
||||
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);
|
||||
}
|
||||
|
||||
|
@ -1144,9 +1151,9 @@ static VALUE
|
|||
nurat_eqeq_p(VALUE self, VALUE 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))
|
||||
return Qtrue;
|
||||
|
||||
|
@ -1156,6 +1163,10 @@ nurat_eqeq_p(VALUE self, VALUE other)
|
|||
return Qfalse;
|
||||
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)) {
|
||||
const double d = nurat_to_double(self);
|
||||
|
@ -1544,6 +1555,10 @@ static double
|
|||
nurat_to_double(VALUE 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);
|
||||
}
|
||||
|
||||
|
|
|
@ -27,6 +27,29 @@ class TestInteger < Test::Unit::TestCase
|
|||
|
||||
x = EnvUtil.suppress_warning {2 ** -0x4000000000000000}
|
||||
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
|
||||
|
||||
def test_lshift
|
||||
|
|
Загрузка…
Ссылка в новой задаче