summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorMasaki Muranaka <[email protected]>2013-02-22 17:22:00 +0900
committerMasaki Muranaka <[email protected]>2013-02-23 11:42:27 +0900
commit4c968174105c047c5b0cc8c1ef6706a4b0274310 (patch)
tree4268bac83d066c962f30fd835cbe3c54d2455e86
parent9ea0b4b7d16e85c666bc9ce2ed16cc868a196aba (diff)
downloadmruby-4c968174105c047c5b0cc8c1ef6706a4b0274310.tar.gz
mruby-4c968174105c047c5b0cc8c1ef6706a4b0274310.zip
Cleanup shift operations.
-rw-r--r--src/numeric.c96
1 files changed, 67 insertions, 29 deletions
diff --git a/src/numeric.c b/src/numeric.c
index a4f2ed6e0..14be04408 100644
--- a/src/numeric.c
+++ b/src/numeric.c
@@ -25,8 +25,6 @@
#include <ieeefp.h>
#endif
-#define RSHIFT(x,y) ((x)>>(int)(y))
-
#ifdef MRB_USE_FLOAT
#define floor(f) floorf(f)
#define ceil(f) ceilf(f)
@@ -961,26 +959,45 @@ fix_xor(mrb_state *mrb, mrb_value x)
return mrb_fixnum_value(val);
}
+#define NUMERIC_SHIFT_WIDTH_MAX (sizeof(mrb_int)*CHAR_BIT-1)
+
static mrb_value
lshift(mrb_state *mrb, mrb_int val, int width)
{
- if (width > (sizeof(mrb_int)*CHAR_BIT-1)) {
+ if (width > NUMERIC_SHIFT_WIDTH_MAX) {
mrb_raisef(mrb, E_RANGE_ERROR, "width(%d) > (%d:sizeof(mrb_int)*CHAR_BIT-1)", width,
- sizeof(mrb_int)*CHAR_BIT-1);
+ NUMERIC_SHIFT_WIDTH_MAX);
}
val = val << width;
return mrb_fixnum_value(val);
}
static mrb_value
-rshift(mrb_int val, int i)
+rshift(mrb_int val, int width)
{
- if (i >= sizeof(mrb_int)*CHAR_BIT-1) {
- if (val < 0) return mrb_fixnum_value(-1);
- return mrb_fixnum_value(0);
+ if (width >= NUMERIC_SHIFT_WIDTH_MAX) {
+ if (val < 0) {
+ val = -1;
}
- val = RSHIFT(val, i);
- return mrb_fixnum_value(val);
+ else {
+ val = 0;
+ }
+ }
+ else {
+ val = val >> width;
+ }
+
+ return mrb_fixnum_value(val);
+}
+
+static inline void
+fix_shift_get_width(mrb_state *mrb, mrb_int *width)
+{
+ mrb_value y;
+
+ mrb_get_args(mrb, "o", &y);
+ y = bit_coerce(mrb, y);
+ *width = mrb_fixnum(y);
}
/* 15.2.8.3.12 */
@@ -994,16 +1011,27 @@ rshift(mrb_int val, int i)
static mrb_value
fix_lshift(mrb_state *mrb, mrb_value x)
{
- mrb_value y;
- mrb_int val, width;
+ mrb_int width;
+ mrb_value result;
- mrb_get_args(mrb, "o", &y);
- val = mrb_fixnum(x);
- y = bit_coerce(mrb, y);
- width = mrb_fixnum(y);
- if (width < 0)
- return rshift(val, -width);
- return lshift(mrb, val, width);
+ fix_shift_get_width(mrb, &width);
+
+ if (width == 0) {
+ result = x;
+ }
+ else {
+ mrb_int val;
+
+ val = mrb_fixnum(x);
+ if (width < 0) {
+ result = rshift(val, -width);
+ }
+ else {
+ result = lshift(mrb, val, width);
+ }
+ }
+
+ return result;
}
/* 15.2.8.3.13 */
@@ -1017,17 +1045,27 @@ fix_lshift(mrb_state *mrb, mrb_value x)
static mrb_value
fix_rshift(mrb_state *mrb, mrb_value x)
{
- mrb_value y;
- mrb_int i, val;
+ mrb_int width;
+ mrb_value result;
- mrb_get_args(mrb, "o", &y);
- val = mrb_fixnum(x);
- y = bit_coerce(mrb, y);
- i = mrb_fixnum(y);
- if (i == 0) return x;
- if (i < 0)
- return lshift(mrb, val, -i);
- return rshift(val, i);
+ fix_shift_get_width(mrb, &width);
+
+ if (width == 0) {
+ result = x;
+ }
+ else {
+ mrb_int val;
+
+ val = mrb_fixnum(x);
+ if (width < 0) {
+ result = lshift(mrb, val, -width);
+ }
+ else {
+ result = rshift(val, width);
+ }
+ }
+
+ return result;
}
/* 15.2.8.3.23 */