diff options
| -rw-r--r-- | lbitlib.c | 32 |
1 files changed, 20 insertions, 12 deletions
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | ** $Id: lbitlib.c,v 1.8 2010/10/25 20:31:11 roberto Exp roberto $ | 2 | ** $Id: lbitlib.c,v 1.9 2010/10/27 16:50:32 roberto Exp roberto $ |
| 3 | ** Standard library for bitwise operations | 3 | ** Standard library for bitwise operations |
| 4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
| 5 | */ | 5 | */ |
| @@ -13,12 +13,16 @@ | |||
| 13 | #include "lualib.h" | 13 | #include "lualib.h" |
| 14 | 14 | ||
| 15 | 15 | ||
| 16 | /* number of bits considered when shifting/rotating (must be a power of 2) */ | 16 | /* number of bits to consider in a number */ |
| 17 | #define NBITS 32 | 17 | #define NBITS 32 |
| 18 | 18 | ||
| 19 | #define ALLONES (~(((~(lua_Unsigned)0) << (NBITS - 1)) << 1)) | ||
| 19 | 20 | ||
| 20 | typedef LUA_INT32 b_int; | 21 | /* mask to trim extra bits */ |
| 21 | typedef unsigned LUA_INT32 b_uint; | 22 | #define trim(x) ((x) & ALLONES) |
| 23 | |||
| 24 | |||
| 25 | typedef lua_Unsigned b_uint; | ||
| 22 | 26 | ||
| 23 | 27 | ||
| 24 | #define getuintarg(L,arg) luaL_checkunsigned(L,arg) | 28 | #define getuintarg(L,arg) luaL_checkunsigned(L,arg) |
| @@ -29,7 +33,7 @@ static b_uint andaux (lua_State *L) { | |||
| 29 | b_uint r = ~(b_uint)0; | 33 | b_uint r = ~(b_uint)0; |
| 30 | for (i = 1; i <= n; i++) | 34 | for (i = 1; i <= n; i++) |
| 31 | r &= getuintarg(L, i); | 35 | r &= getuintarg(L, i); |
| 32 | return r; | 36 | return trim(r); |
| 33 | } | 37 | } |
| 34 | 38 | ||
| 35 | 39 | ||
| @@ -52,7 +56,7 @@ static int b_or (lua_State *L) { | |||
| 52 | b_uint r = 0; | 56 | b_uint r = 0; |
| 53 | for (i = 1; i <= n; i++) | 57 | for (i = 1; i <= n; i++) |
| 54 | r |= getuintarg(L, i); | 58 | r |= getuintarg(L, i); |
| 55 | lua_pushunsigned(L, r); | 59 | lua_pushunsigned(L, trim(r)); |
| 56 | return 1; | 60 | return 1; |
| 57 | } | 61 | } |
| 58 | 62 | ||
| @@ -62,14 +66,14 @@ static int b_xor (lua_State *L) { | |||
| 62 | b_uint r = 0; | 66 | b_uint r = 0; |
| 63 | for (i = 1; i <= n; i++) | 67 | for (i = 1; i <= n; i++) |
| 64 | r ^= getuintarg(L, i); | 68 | r ^= getuintarg(L, i); |
| 65 | lua_pushunsigned(L, r); | 69 | lua_pushunsigned(L, trim(r)); |
| 66 | return 1; | 70 | return 1; |
| 67 | } | 71 | } |
| 68 | 72 | ||
| 69 | 73 | ||
| 70 | static int b_not (lua_State *L) { | 74 | static int b_not (lua_State *L) { |
| 71 | b_uint r = ~getuintarg(L, 1); | 75 | b_uint r = ~getuintarg(L, 1); |
| 72 | lua_pushunsigned(L, r); | 76 | lua_pushunsigned(L, trim(r)); |
| 73 | return 1; | 77 | return 1; |
| 74 | } | 78 | } |
| 75 | 79 | ||
| @@ -77,12 +81,14 @@ static int b_not (lua_State *L) { | |||
| 77 | static int b_shift (lua_State *L, b_uint r, int i) { | 81 | static int b_shift (lua_State *L, b_uint r, int i) { |
| 78 | if (i < 0) { /* shift right? */ | 82 | if (i < 0) { /* shift right? */ |
| 79 | i = -i; | 83 | i = -i; |
| 84 | r = trim(r); | ||
| 80 | if (i >= NBITS) r = 0; | 85 | if (i >= NBITS) r = 0; |
| 81 | else r >>= i; | 86 | else r >>= i; |
| 82 | } | 87 | } |
| 83 | else { /* shift left */ | 88 | else { /* shift left */ |
| 84 | if (i >= NBITS) r = 0; | 89 | if (i >= NBITS) r = 0; |
| 85 | else r <<= i; | 90 | else r <<= i; |
| 91 | r = trim(r); | ||
| 86 | } | 92 | } |
| 87 | lua_pushunsigned(L, r); | 93 | lua_pushunsigned(L, r); |
| 88 | return 1; | 94 | return 1; |
| @@ -102,12 +108,12 @@ static int b_rshift (lua_State *L) { | |||
| 102 | static int b_arshift (lua_State *L) { | 108 | static int b_arshift (lua_State *L) { |
| 103 | b_uint r = getuintarg(L, 1); | 109 | b_uint r = getuintarg(L, 1); |
| 104 | int i = luaL_checkint(L, 2); | 110 | int i = luaL_checkint(L, 2); |
| 105 | if (i < 0 || !(r & 0x80000000)) | 111 | if (i < 0 || !(r & (1 << (NBITS - 1)))) |
| 106 | return b_shift(L, r, -i); | 112 | return b_shift(L, r, -i); |
| 107 | else { /* arithmetic shift for 'negative' number */ | 113 | else { /* arithmetic shift for 'negative' number */ |
| 108 | if (i >= NBITS) r = 0xffffffff; | 114 | if (i >= NBITS) r = ALLONES; |
| 109 | else | 115 | else |
| 110 | r = (r >> i) | ~(~(b_uint)0 >> i); /* add signal bit */ | 116 | r = trim((r >> i) | ~(~(b_uint)0 >> i)); /* add signal bit */ |
| 111 | lua_pushunsigned(L, r); | 117 | lua_pushunsigned(L, r); |
| 112 | return 1; | 118 | return 1; |
| 113 | } | 119 | } |
| @@ -117,8 +123,9 @@ static int b_arshift (lua_State *L) { | |||
| 117 | static int b_rot (lua_State *L, int i) { | 123 | static int b_rot (lua_State *L, int i) { |
| 118 | b_uint r = getuintarg(L, 1); | 124 | b_uint r = getuintarg(L, 1); |
| 119 | i &= (NBITS - 1); /* i = i % NBITS */ | 125 | i &= (NBITS - 1); /* i = i % NBITS */ |
| 126 | r = trim(r); | ||
| 120 | r = (r << i) | (r >> (NBITS - i)); | 127 | r = (r << i) | (r >> (NBITS - i)); |
| 121 | lua_pushunsigned(L, r); | 128 | lua_pushunsigned(L, trim(r)); |
| 122 | return 1; | 129 | return 1; |
| 123 | } | 130 | } |
| 124 | 131 | ||
| @@ -153,3 +160,4 @@ LUAMOD_API int luaopen_bit32 (lua_State *L) { | |||
| 153 | luaL_newlib(L, bitlib); | 160 | luaL_newlib(L, bitlib); |
| 154 | return 1; | 161 | return 1; |
| 155 | } | 162 | } |
| 163 | |||
