1 #include "lua/internal.hpp"
2 #include "library/minmax.hpp"
4 #define BITWISE_BITS 48
5 #define BITWISE_MASK ((1ULL << (BITWISE_BITS)) - 1)
9 uint64_t combine_none(uint64_t chain
, uint64_t arg
)
11 return (chain
& ~arg
) & BITWISE_MASK
;
14 uint64_t combine_any(uint64_t chain
, uint64_t arg
)
16 return (chain
| arg
) & BITWISE_MASK
;
19 uint64_t combine_all(uint64_t chain
, uint64_t arg
)
21 return (chain
& arg
) & BITWISE_MASK
;
24 uint64_t combine_parity(uint64_t chain
, uint64_t arg
)
26 return (chain
^ arg
) & BITWISE_MASK
;
29 uint64_t shift_lrotate(uint64_t base
, uint64_t amount
, uint64_t bits
)
31 uint64_t mask
= ((1ULL << bits
) - 1);
33 base
= (base
<< amount
) | (base
>> (bits
- amount
));
34 return base
& mask
& BITWISE_MASK
;
37 uint64_t shift_rrotate(uint64_t base
, uint64_t amount
, uint64_t bits
)
39 uint64_t mask
= ((1ULL << bits
) - 1);
41 base
= (base
>> amount
) | (base
<< (bits
- amount
));
42 return base
& mask
& BITWISE_MASK
;
45 uint64_t shift_lshift(uint64_t base
, uint64_t amount
, uint64_t bits
)
47 uint64_t mask
= ((1ULL << bits
) - 1);
49 return base
& mask
& BITWISE_MASK
;
52 uint64_t shift_lrshift(uint64_t base
, uint64_t amount
, uint64_t bits
)
54 uint64_t mask
= ((1ULL << bits
) - 1);
57 return base
& BITWISE_MASK
;
60 uint64_t shift_arshift(uint64_t base
, uint64_t amount
, uint64_t bits
)
62 uint64_t mask
= ((1ULL << bits
) - 1);
64 bool negative
= ((base
>> (bits
- 1)) != 0);
66 base
|= ((negative
? BITWISE_MASK
: 0) << (bits
- amount
));
67 return base
& mask
& BITWISE_MASK
;
70 template<uint64_t (*combine
)(uint64_t chain
, uint64_t arg
), uint64_t init
>
71 class lua_symmetric_bitwise
: public lua_function
74 lua_symmetric_bitwise(const std::string
& s
) : lua_function(lua_func_bit
, s
) {};
75 int invoke(lua_state
& L
)
78 while(!L
.isnone(stacksize
+ 1))
81 for(int i
= 0; i
< stacksize
; i
++)
82 ret
= combine(ret
, L
.get_numeric_argument
<uint64_t>(i
+ 1, fname
.c_str()));
88 template<uint64_t (*shift
)(uint64_t base
, uint64_t amount
, uint64_t bits
)>
89 class lua_shifter
: public lua_function
92 lua_shifter(const std::string
& s
) : lua_function(lua_func_bit
, s
) {};
93 int invoke(lua_state
& L
)
97 uint64_t bits
= BITWISE_BITS
;
98 base
= L
.get_numeric_argument
<uint64_t>(1, fname
.c_str());
99 L
.get_numeric_argument(2, amount
, fname
.c_str());
100 L
.get_numeric_argument(3, bits
, fname
.c_str());
101 L
.pushnumber(shift(base
, amount
, bits
));
106 function_ptr_luafun
lua_bextract(lua_func_bit
, "bit.extract", [](lua_state
& L
, const std::string
& fname
)
108 uint64_t num
= L
.get_numeric_argument
<uint64_t>(1, fname
.c_str());
110 for(size_t i
= 0;; i
++) {
111 if(L
.isboolean(i
+ 2)) {
112 if(L
.toboolean(i
+ 2))
114 } else if(L
.isnumber(i
+ 2)) {
115 uint8_t bit
= L
.get_numeric_argument
<uint8_t>(i
+ 2, fname
.c_str());
116 ret
|= (((num
>> bit
) & 1) << i
);
124 function_ptr_luafun
lua_bvalue(lua_func_bit
, "bit.value", [](lua_state
& L
, const std::string
& fname
) -> int {
126 for(size_t i
= 0;; i
++) {
127 if(L
.isnumber(i
+ 1)) {
128 uint8_t bit
= L
.get_numeric_argument
<uint8_t>(i
+ 1, fname
.c_str());
129 ret
|= (1ULL << bit
);
130 } else if(L
.isnil(i
+ 1)) {
138 function_ptr_luafun
lua_testany(lua_func_bit
, "bit.test_any", [](lua_state
& L
, const std::string
& fname
)
140 uint64_t a
= L
.get_numeric_argument
<uint64_t>(1, fname
.c_str());
141 uint64_t b
= L
.get_numeric_argument
<uint64_t>(2, fname
.c_str());
142 L
.pushboolean((a
& b
) != 0);
146 function_ptr_luafun
lua_testall(lua_func_bit
, "bit.test_all", [](lua_state
& L
, const std::string
& fname
)
148 uint64_t a
= L
.get_numeric_argument
<uint64_t>(1, fname
.c_str());
149 uint64_t b
= L
.get_numeric_argument
<uint64_t>(2, fname
.c_str());
150 L
.pushboolean((a
& b
) == b
);
154 int poptable
[] = {0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4};
156 int popcount(uint64_t x
)
159 for(unsigned i
= 0; i
< 16; i
++) {
160 c
+= poptable
[x
& 15];
166 function_ptr_luafun
lua_popcount(lua_func_bit
, "bit.popcount", [](lua_state
& L
, const std::string
& fname
)
168 uint64_t a
= L
.get_numeric_argument
<uint64_t>(1, fname
.c_str());
169 L
.pushnumber(popcount(a
));
173 function_ptr_luafun
lua_clshift(lua_func_bit
, "bit.clshift", [](lua_state
& L
, const std::string
& fname
)
177 uint64_t a
= L
.get_numeric_argument
<uint64_t>(1, fname
.c_str());
178 uint64_t b
= L
.get_numeric_argument
<uint64_t>(2, fname
.c_str());
179 L
.get_numeric_argument(3, amount
, fname
.c_str());
180 L
.get_numeric_argument(4, bits
, fname
.c_str());
181 uint64_t mask
= ((1ULL << bits
) - 1);
186 a
|= (b
>> (bits
- amount
));
194 function_ptr_luafun
lua_crshift(lua_func_bit
, "bit.crshift", [](lua_state
& L
, const std::string
& fname
)
198 uint64_t a
= L
.get_numeric_argument
<uint64_t>(1, fname
.c_str());
199 uint64_t b
= L
.get_numeric_argument
<uint64_t>(2, fname
.c_str());
200 L
.get_numeric_argument(3, amount
, fname
.c_str());
201 L
.get_numeric_argument(4, bits
, fname
.c_str());
202 uint64_t mask
= ((1ULL << bits
) - 1);
206 b
|= (a
<< (bits
- amount
));
214 int flagdecode_core(lua_state
& L
, const std::string
& fname
, bool reverse
)
216 uint64_t a
= L
.get_numeric_argument
<uint64_t>(1, fname
.c_str());
217 uint64_t b
= L
.get_numeric_argument
<uint64_t>(2, fname
.c_str());
219 if(L
.type(3) == LUA_TSTRING
)
220 on
= L
.get_string(3, fname
.c_str());
221 if(L
.type(4) == LUA_TSTRING
)
222 off
= L
.get_string(4, fname
.c_str());
223 size_t onl
= on
.length();
224 size_t offl
= off
.length();
225 char onc
= onl
? on
[onl
- 1] : '*';
226 char offc
= offl
? off
[offl
- 1] : '-';
229 size_t bias
= min(b
, (uint64_t)64) - 1;
230 for(i
= 0; i
< 64 && i
< b
; i
++) {
231 char onc2
= (i
< onl
) ? on
[i
] : onc
;
232 char offc2
= (i
< offl
) ? off
[i
] : offc
;
233 buffer
[reverse
? (bias
- i
) : i
] = ((a
>> i
) & 1) ? onc2
: offc2
;
236 L
.pushstring(buffer
);
240 function_ptr_luafun
lua_flagdecode(lua_func_bit
, "bit.flagdecode", [](lua_state
& L
, const std::string
& fname
)
242 return flagdecode_core(L
, fname
, false);
245 function_ptr_luafun
lua_rflagdecode(lua_func_bit
, "bit.rflagdecode", [](lua_state
& L
,
246 const std::string
& fname
) -> int {
247 return flagdecode_core(L
, fname
, true);
250 lua_symmetric_bitwise
<combine_none
, BITWISE_MASK
> bit_none("bit.none");
251 lua_symmetric_bitwise
<combine_none
, BITWISE_MASK
> bit_bnot("bit.bnot");
252 lua_symmetric_bitwise
<combine_any
, 0> bit_any("bit.any");
253 lua_symmetric_bitwise
<combine_any
, 0> bit_bor("bit.bor");
254 lua_symmetric_bitwise
<combine_all
, BITWISE_MASK
> bit_all("bit.all");
255 lua_symmetric_bitwise
<combine_all
, BITWISE_MASK
> bit_band("bit.band");
256 lua_symmetric_bitwise
<combine_parity
, 0> bit_parity("bit.parity");
257 lua_symmetric_bitwise
<combine_parity
, 0> bit_bxor("bit.bxor");
258 lua_shifter
<shift_lrotate
> bit_lrotate("bit.lrotate");
259 lua_shifter
<shift_rrotate
> bit_rrotate("bit.rrotate");
260 lua_shifter
<shift_lshift
> bit_lshift("bit.lshift");
261 lua_shifter
<shift_arshift
> bit_arshift("bit.arshift");
262 lua_shifter
<shift_lrshift
> bit_lrshift("bit.lrshift");