vm_insnhelper.c: avoid division by zero

same as r65642.


git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@65678 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
shyouhei 2018-11-12 03:26:39 +00:00
Родитель 21e1260fb9
Коммит 00b8b11858
3 изменённых файлов: 34 добавлений и 36 удалений

Просмотреть файл

@ -1755,6 +1755,7 @@ rb_num_negative_int_p(VALUE num)
VALUE rb_float_abs(VALUE flt);
VALUE rb_float_equal(VALUE x, VALUE y);
VALUE rb_float_eql(VALUE x, VALUE y);
VALUE rb_flo_div_flo(VALUE x, VALUE y);
#if USE_FLONUM
#define RUBY_BIT_ROTL(v, n) (((v) << (n)) | ((v) >> ((sizeof(v) * 8) - n)))

Просмотреть файл

@ -1089,6 +1089,30 @@ flo_iszero(VALUE f)
return RFLOAT_VALUE(f) == 0.0;
}
static double
double_div_double(double x, double y)
{
if (LIKELY(y != 0.0)) {
return x / y;
}
else if (x == 0.0) {
return nan("");
}
else {
double z = signbit(y) ? -1.0 : 1.0;
return x * z * HUGE_VAL;
}
}
VALUE
rb_flo_div_flo(VALUE x, VALUE y)
{
double num = RFLOAT_VALUE(x);
double den = RFLOAT_VALUE(y);
double ret = double_div_double(x, y);
return DBL2NUM(ret);
}
/*
* call-seq:
* float / other -> float
@ -1099,52 +1123,25 @@ flo_iszero(VALUE f)
static VALUE
flo_div(VALUE x, VALUE y)
{
double den;
double num = RFLOAT_VALUE(x);
double sign = 1.0;
double den;
double ret;
if (RB_TYPE_P(y, T_FIXNUM)) {
if (FIXNUM_ZERO_P(y)) {
goto zerodiv;
}
else {
den = FIX2LONG(y);
goto nonzero;
}
den = FIX2LONG(y);
}
else if (RB_TYPE_P(y, T_BIGNUM)) {
if (rb_bigzero_p(y)) {
goto zerodiv;
}
else {
den = rb_big2dbl(y);
goto nonzero;
}
den = rb_big2dbl(y);
}
else if (RB_TYPE_P(y, T_FLOAT)) {
if (flo_iszero(y)) {
sign = signbit(RFLOAT_VALUE(y)) ? -1.0 : 1.0;
goto zerodiv;
}
else {
den = RFLOAT_VALUE(y);
goto nonzero;
}
den = RFLOAT_VALUE(y);
}
else {
return rb_num_coerce_bin(x, y, '/');
}
nonzero:
return DBL2NUM(num / den);
zerodiv:
if (num == 0.0) {
return DBL2NUM(nan(""));
}
else {
return DBL2NUM(num * sign * HUGE_VAL);
}
ret = double_div_double(num, den);
return DBL2NUM(ret);
}
/*

Просмотреть файл

@ -3450,7 +3450,7 @@ vm_opt_div(VALUE recv, VALUE obj)
}
else if (FLONUM_2_P(recv, obj) &&
BASIC_OP_UNREDEFINED_P(BOP_DIV, FLOAT_REDEFINED_OP_FLAG)) {
return DBL2NUM(RFLOAT_VALUE(recv) / RFLOAT_VALUE(obj));
return rb_flo_div_flo(recv, obj);
}
else if (SPECIAL_CONST_P(recv) || SPECIAL_CONST_P(obj)) {
return Qundef;
@ -3458,7 +3458,7 @@ vm_opt_div(VALUE recv, VALUE obj)
else if (RBASIC_CLASS(recv) == rb_cFloat &&
RBASIC_CLASS(obj) == rb_cFloat &&
BASIC_OP_UNREDEFINED_P(BOP_DIV, FLOAT_REDEFINED_OP_FLAG)) {
return DBL2NUM(RFLOAT_VALUE(recv) / RFLOAT_VALUE(obj));
return rb_flo_div_flo(recv, obj);
}
else {
return Qundef;