mirror of
https://github.com/mruby/mruby
synced 2026-06-08 16:11:16 +00:00
Extract div code in VM and make them shared by div methods.
This commit is contained in:
+54
-12
@@ -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:
|
||||
|
||||
Reference in New Issue
Block a user