diff options
| author | Yukihiro "Matz" Matsumoto <[email protected]> | 2021-08-02 08:53:14 +0900 |
|---|---|---|
| committer | Yukihiro "Matz" Matsumoto <[email protected]> | 2021-08-02 08:53:14 +0900 |
| commit | a9d721ea8fcb8c725e26a1ac0884ba3227ea5a08 (patch) | |
| tree | e79516b0410ecaeb98bffa83e22c31e83bd8eb7c /src | |
| parent | 907df715ef751ad1e1dedc5bbbde4881944db1d7 (diff) | |
| download | mruby-a9d721ea8fcb8c725e26a1ac0884ba3227ea5a08.tar.gz mruby-a9d721ea8fcb8c725e26a1ac0884ba3227ea5a08.zip | |
numeric.c: refactor integer bit shift operations.
Diffstat (limited to 'src')
| -rw-r--r-- | src/numeric.c | 57 |
1 files changed, 28 insertions, 29 deletions
diff --git a/src/numeric.c b/src/numeric.c index 17f5ac1bc..ab6632e52 100644 --- a/src/numeric.c +++ b/src/numeric.c @@ -1306,37 +1306,37 @@ int_xor(mrb_state *mrb, mrb_value x) #define NUMERIC_SHIFT_WIDTH_MAX (MRB_INT_BIT-1) -static mrb_value -lshift(mrb_state *mrb, mrb_int val, mrb_int width) +mrb_bool +mrb_num_shift(mrb_state *mrb, mrb_int val, mrb_int width, mrb_int *num) { - mrb_assert(width >= 0); - if (val > 0) { + if (width < 0) { /* rshift */ + if (width == MRB_INT_MIN || -width >= NUMERIC_SHIFT_WIDTH_MAX) { + if (val < 0) { + *num = -1; + } + else { + *num = 0; + } + } + else { + *num = val >> -width; + } + } + else if (val > 0) { if ((width > NUMERIC_SHIFT_WIDTH_MAX) || (val > (MRB_INT_MAX >> width))) { - int_overflow(mrb, "bit shift"); + return FALSE; } - return mrb_int_value(mrb, val << width); + *num = val << width; } else { if ((width > NUMERIC_SHIFT_WIDTH_MAX) || (val <= (MRB_INT_MIN >> width))) { - int_overflow(mrb, "bit shift"); + return FALSE; } - return mrb_int_value(mrb, (val * ((mrb_int)1 << width))); + *num = val * ((mrb_int)1 << width); } -} - -static mrb_value -rshift(mrb_state *mrb, mrb_int val, mrb_int width) -{ - mrb_assert(width >= 0); - if (width >= NUMERIC_SHIFT_WIDTH_MAX) { - if (val < 0) { - return mrb_fixnum_value(-1); - } - return mrb_fixnum_value(0); - } - return mrb_int_value(mrb, val >> width); + return TRUE; } /* 15.2.8.3.12 */ @@ -1358,11 +1358,10 @@ int_lshift(mrb_state *mrb, mrb_value x) } val = mrb_integer(x); if (val == 0) return x; - if (width < 0) { - if (width == MRB_INT_MIN) return rshift(mrb, val, MRB_INT_BIT); - return rshift(mrb, val, -width); + if (!mrb_num_shift(mrb, val, width, &val)) { + int_overflow(mrb, "bit shift"); } - return lshift(mrb, val, width); + return mrb_int_value(mrb, val); } /* 15.2.8.3.13 */ @@ -1384,11 +1383,11 @@ int_rshift(mrb_state *mrb, mrb_value x) } val = mrb_integer(x); if (val == 0) return x; - if (width < 0) { - if (width == MRB_INT_MIN) int_overflow(mrb, "bit shift"); - return lshift(mrb, val, -width); + if (width == MRB_INT_MIN) int_overflow(mrb, "bit shift"); + if (!mrb_num_shift(mrb, val, -width, &val)) { + int_overflow(mrb, "bit shift"); } - return rshift(mrb, val, width); + return mrb_int_value(mrb, val); } /* 15.2.8.3.23 */ |
