fix_pow: do not goto into a branch

I'm not necessarily against every goto in general, but jumping into a
branch is definitely a bad idea.  Better refactor.
This commit is contained in:
卜部昌平 2020-06-16 10:39:07 +09:00
Родитель 250189f54f
Коммит 03354feb6a
1 изменённых файлов: 26 добавлений и 31 удалений

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

@ -4008,6 +4008,25 @@ rb_int_positive_pow(long x, unsigned long y)
return int_pow(x, y); return int_pow(x, y);
} }
static VALUE
fix_pow_inverted(VALUE x, VALUE minusb)
{
if (x == INT2FIX(0)) {
rb_num_zerodiv();
}
else {
VALUE y = rb_int_pow(x, minusb);
if (RB_FLOAT_TYPE_P(y)) {
double d = pow((double)FIX2LONG(x), RFLOAT_VALUE(y));
return DBL2NUM(1.0 / d);
}
else {
return rb_rational_raw(INT2FIX(1), y);
}
}
}
static VALUE static VALUE
fix_pow(VALUE x, VALUE y) fix_pow(VALUE x, VALUE y)
{ {
@ -4017,18 +4036,8 @@ fix_pow(VALUE x, VALUE y)
long b = FIX2LONG(y); long b = FIX2LONG(y);
if (a == 1) return INT2FIX(1); if (a == 1) return INT2FIX(1);
if (a == -1) { if (a == -1) return INT2FIX(b % 2 ? -1 : 1);
if (b % 2 == 0) if (b < 0) return fix_pow_inverted(x, fix_uminus(y));
return INT2FIX(1);
else
return INT2FIX(-1);
}
if (b < 0) {
if (a == 0) rb_num_zerodiv();
y = rb_int_pow(x, LONG2NUM(-b));
goto inverted;
}
if (b == 0) return INT2FIX(1); if (b == 0) return INT2FIX(1);
if (b == 1) return x; if (b == 1) return x;
if (a == 0) return INT2FIX(0); if (a == 0) return INT2FIX(0);
@ -4036,20 +4045,8 @@ fix_pow(VALUE x, VALUE y)
} }
else if (RB_TYPE_P(y, T_BIGNUM)) { else if (RB_TYPE_P(y, T_BIGNUM)) {
if (a == 1) return INT2FIX(1); if (a == 1) return INT2FIX(1);
if (a == -1) { if (a == -1) return INT2FIX(int_even_p(y) ? 1 : -1);
if (int_even_p(y)) return INT2FIX(1); if (BIGNUM_NEGATIVE_P(y)) return fix_pow_inverted(x, rb_big_uminus(y));
else return INT2FIX(-1);
}
if (BIGNUM_NEGATIVE_P(y)) {
if (a == 0) rb_num_zerodiv();
y = rb_int_pow(x, rb_big_uminus(y));
inverted:
if (RB_FLOAT_TYPE_P(y)) {
double d = pow((double)a, RFLOAT_VALUE(y));
return DBL2NUM(1.0 / d);
}
return rb_rational_raw(INT2FIX(1), y);
}
if (a == 0) return INT2FIX(0); if (a == 0) return INT2FIX(0);
x = rb_int2big(FIX2LONG(x)); x = rb_int2big(FIX2LONG(x));
return rb_big_pow(x, y); return rb_big_pow(x, y);
@ -4061,11 +4058,9 @@ fix_pow(VALUE x, VALUE y)
return DBL2NUM(dy < 0 ? HUGE_VAL : 0.0); return DBL2NUM(dy < 0 ? HUGE_VAL : 0.0);
} }
if (a == 1) return DBL2NUM(1.0); if (a == 1) return DBL2NUM(1.0);
{ if (a < 0 && dy != round(dy))
if (a < 0 && dy != round(dy)) return rb_dbl_complex_new_polar_pi(pow(-(double)a, dy), dy);
return rb_dbl_complex_new_polar_pi(pow(-(double)a, dy), dy); return DBL2NUM(pow((double)a, dy));
return DBL2NUM(pow((double)a, dy));
}
} }
else { else {
return rb_num_coerce_bin(x, y, idPow); return rb_num_coerce_bin(x, y, idPow);