77cd612f |
1 | /* Bitwise operations library */ |
2 | /* (c) Reuben Thomas 2000-2008 */ |
3 | /* See README for license */ |
4 | |
5 | #include <lua.h> |
6 | #include <lauxlib.h> |
7 | #include <limits.h> |
8 | |
9 | #include "pm3_bit_limits.h" |
10 | |
11 | |
12 | /* FIXME: Assumes lua_Integer is ptrdiff_t */ |
13 | #define LUA_INTEGER_MAX PTRDIFF_MAX |
14 | #define LUA_INTEGER_MIN PTRDIFF_MIN |
15 | |
16 | /* FIXME: Assumes size_t is an unsigned lua_Integer */ |
17 | typedef size_t lua_UInteger; |
18 | #define LUA_UINTEGER_MAX SIZE_MAX |
19 | |
20 | |
21 | /* Bit type size and limits */ |
22 | |
23 | #define BIT_BITS \ |
24 | (CHAR_BIT * sizeof(lua_Integer) > BITLIB_FLOAT_BITS ? \ |
25 | BITLIB_FLOAT_BITS : (CHAR_BIT * sizeof(lua_Integer))) |
26 | |
27 | /* This code may give warnings if BITLIB_FLOAT_* are too big to fit in |
28 | long, but that doesn't matter since in that case they won't be |
29 | used. */ |
30 | #define BIT_MAX \ |
31 | (CHAR_BIT * sizeof(lua_Integer) > BITLIB_FLOAT_BITS ? BITLIB_FLOAT_MAX : LUA_INTEGER_MAX) |
32 | |
33 | #define BIT_MIN \ |
34 | (CHAR_BIT * sizeof(lua_Integer) > BITLIB_FLOAT_BITS ? BITLIB_FLOAT_MIN : LUA_INTEGER_MIN) |
35 | |
36 | #define BIT_UMAX \ |
37 | (CHAR_BIT * sizeof(lua_Integer) > BITLIB_FLOAT_BITS ? BITLIB_FLOAT_UMAX : LUA_UINTEGER_MAX) |
38 | |
39 | |
40 | /* Define TOBIT to get a bit value */ |
41 | #ifdef BUILTIN_CAST |
42 | #define |
43 | #define TOBIT(L, n, res) \ |
44 | ((void)(res), luaL_checkinteger((L), (n))) |
45 | #else |
46 | #include <stdint.h> |
47 | #include <math.h> |
48 | |
49 | /* FIXME: Assumes lua_Number fits in a double (use of fmod). */ |
50 | #define TOBIT(L, n, res) \ |
51 | ((lua_Integer)(((res) = fmod(luaL_checknumber(L, (n)), (double)BIT_UMAX + 1.0)), \ |
52 | (res) > BIT_MAX ? ((res) -= (double)BIT_UMAX, (res) -= 1) : \ |
53 | ((res) < BIT_MIN ? ((res) += (double)BIT_UMAX, (res) += 1) : (res)))) |
54 | #endif |
55 | |
56 | |
57 | #define BIT_TRUNCATE(i) \ |
58 | ((i) & BIT_UMAX) |
59 | |
60 | |
61 | /* Operations |
62 | |
63 | The macros MONADIC and VARIADIC only deal with bitwise operations. |
64 | |
65 | LOGICAL_SHIFT truncates its left-hand operand before shifting so |
66 | that any extra bits at the most-significant end are not shifted |
67 | into the result. |
68 | |
69 | ARITHMETIC_SHIFT does not truncate its left-hand operand, so that |
70 | the sign bits are not removed and right shift work properly. |
71 | */ |
72 | |
73 | #define MONADIC(name, op) \ |
74 | static int bit_ ## name(lua_State *L) { \ |
75 | lua_Number f; \ |
76 | lua_pushinteger(L, BIT_TRUNCATE(op TOBIT(L, 1, f))); \ |
77 | return 1; \ |
78 | } |
79 | |
80 | #define VARIADIC(name, op) \ |
81 | static int bit_ ## name(lua_State *L) { \ |
82 | lua_Number f; \ |
83 | int n = lua_gettop(L), i; \ |
84 | lua_Integer w = TOBIT(L, 1, f); \ |
85 | for (i = 2; i <= n; i++) \ |
86 | w op TOBIT(L, i, f); \ |
87 | lua_pushinteger(L, BIT_TRUNCATE(w)); \ |
88 | return 1; \ |
89 | } |
90 | |
91 | #define LOGICAL_SHIFT(name, op) \ |
92 | static int bit_ ## name(lua_State *L) { \ |
93 | lua_Number f; \ |
94 | lua_pushinteger(L, BIT_TRUNCATE(BIT_TRUNCATE((lua_UInteger)TOBIT(L, 1, f)) op \ |
95 | (unsigned)luaL_checknumber(L, 2))); \ |
96 | return 1; \ |
97 | } |
98 | |
99 | #define ARITHMETIC_SHIFT(name, op) \ |
100 | static int bit_ ## name(lua_State *L) { \ |
101 | lua_Number f; \ |
102 | lua_pushinteger(L, BIT_TRUNCATE((lua_Integer)TOBIT(L, 1, f) op \ |
103 | (unsigned)luaL_checknumber(L, 2))); \ |
104 | return 1; \ |
105 | } |
106 | |
107 | MONADIC(cast, +) |
108 | MONADIC(bnot, ~) |
109 | VARIADIC(band, &=) |
110 | VARIADIC(bor, |=) |
111 | VARIADIC(bxor, ^=) |
112 | ARITHMETIC_SHIFT(lshift, <<) |
113 | LOGICAL_SHIFT(rshift, >>) |
114 | ARITHMETIC_SHIFT(arshift, >>) |
115 | |
116 | static const struct luaL_Reg bitlib[] = { |
117 | {"cast", bit_cast}, |
118 | {"bnot", bit_bnot}, |
119 | {"band", bit_band}, |
120 | {"bor", bit_bor}, |
121 | {"bxor", bit_bxor}, |
122 | {"lshift", bit_lshift}, |
123 | {"rshift", bit_rshift}, |
124 | {"arshift", bit_arshift}, |
125 | {NULL, NULL} |
126 | }; |
127 | |
128 | LUALIB_API int luaopen_bit (lua_State *L) { |
129 | luaL_newlib(L, bitlib); |
130 | //luaL_register(L, "bit", bitlib); |
131 | lua_pushnumber(L, BIT_BITS); |
132 | lua_setfield(L, -2, "bits"); |
133 | return 1; |
134 | } |
135 | |
136 | /** |
137 | LUALIB_API int luaopen_bit (lua_State *L) { |
138 | luaL_register(L, "bit", bitlib); |
139 | lua_pushnumber(L, BIT_BITS); |
140 | lua_setfield(L, -2, "bits"); |
141 | return 1; |
142 | } |
143 | **/ |
144 | /* |
145 | ** Open bit library |
146 | */ |
147 | int set_bit_library (lua_State *L) { |
148 | |
149 | luaL_requiref(L, "bit", luaopen_bit, 1); |
150 | lua_pop(L, 1); |
151 | return 1; |
152 | } |