Extract `div` code in VM and make them shared by `div` methods.

parent b81edb00
......@@ -101,6 +101,41 @@ int_pow(mrb_state *mrb, mrb_value x)
#endif
}
mrb_int
mrb_num_div_int(mrb_state *mrb, mrb_int x, mrb_int y)
{
if (y == 0) {
mrb_raise(mrb, E_ZERODIV_ERROR, "divided by 0");
}
else if(x == MRB_INT_MIN && y == -1) {
mrb_raise(mrb, E_RANGE_ERROR, "integer overflow in division");
}
else {
mrb_int div, mod;
if (y < 0) {
if (x < 0)
div = -x / -y;
else
div = - (x / -y);
}
else {
if (x < 0)
div = - (-x / y);
else
div = x / y;
}
mod = x - div * y;
if ((mod < 0 && y > 0) || (mod > 0 && y < 0)) {
div -= 1;
}
return div;
}
/* not reached */
return 0;
}
/* 15.2.8.3.4 */
/* 15.2.9.3.4 */
/*
......@@ -111,7 +146,6 @@ int_pow(mrb_state *mrb, mrb_value x)
* the class of <code>num</code> and on the magnitude of the
* result.
*/
static mrb_value
int_div(mrb_state *mrb, mrb_value xv)
{
......@@ -219,23 +253,31 @@ flo_idiv(mrb_state *mrb, mrb_value x)
#endif
}
mrb_float
mrb_num_div_flo(mrb_state *mrb, mrb_float x, mrb_float y)
{
mrb_float f;
if (y == 0) {
if (x > 0) f = INFINITY;
else if (x < 0) f = -INFINITY;
else /* if (x == 0) */ f = NAN;
}
else {
f = x / y;
}
return f;
}
static mrb_value
flo_div(mrb_state *mrb, mrb_value xv)
{
mrb_float x, y;
mrb_get_args(mrb, "f", &y);
x = mrb_float(xv);
if (y == 0) {
if (x < 0)
y = -INFINITY;
else if (x > 0)
y = INFINITY;
else /* if (x == 0) */
y = NAN;
return mrb_float_value(mrb, y);
}
return mrb_float_value(mrb, x / y);
mrb_get_args(mrb, "f", &y);
x = mrb_num_div_flo(mrb, x, y);
return mrb_float_value(mrb, x);
}
static mrb_value
......
......@@ -2309,8 +2309,10 @@ RETRY_TRY_BLOCK:
}
CASE(OP_DIV, B) {
mrb_int mrb_num_div_int(mrb_state *mrb, mrb_int x, mrb_int y);
#ifndef MRB_NO_FLOAT
double x, y, f;
mrb_float mrb_num_div_flo(mrb_state *mrb, mrb_float x, mrb_float y);
mrb_float x, y, f;
#endif
/* need to check if op is overridden */
......@@ -2319,34 +2321,8 @@ RETRY_TRY_BLOCK:
{
mrb_int x = mrb_integer(regs[a]);
mrb_int y = mrb_integer(regs[a+1]);
if (y == 0) {
mrb_raise(mrb, E_ZERODIV_ERROR, "divided by 0");
}
else if(x == MRB_INT_MIN && y == -1) {
mrb_raise(mrb, E_RANGE_ERROR, "integer overflow in division");
}
else {
mrb_int div, mod;
if (y < 0) {
if (x < 0)
div = -x / -y;
else
div = - (x / -y);
}
else {
if (x < 0)
div = - (-x / y);
else
div = x / y;
}
mod = x - div*y;
if ((mod < 0 && y > 0) || (mod > 0 && y < 0)) {
div -= 1;
}
SET_INT_VALUE(mrb, regs[a], div);
}
mrb_int div = mrb_num_div_int(mrb, x, y);
SET_INT_VALUE(mrb, regs[a], div);
}
goto L_DIV_OUT;
#ifndef MRB_NO_FLOAT
......@@ -2370,14 +2346,7 @@ RETRY_TRY_BLOCK:
}
#ifndef MRB_NO_FLOAT
if (y == 0) {
if (x > 0) f = INFINITY;
else if (x < 0) f = -INFINITY;
else /* if (x == 0) */ f = NAN;
}
else {
f = x / y;
}
f = mrb_num_div_flo(mrb, x, y);
SET_FLOAT_VALUE(mrb, regs[a], f);
#endif
L_DIV_OUT:
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment