1 #include "lua/internal.hpp"
3 #define BITWISE_BITS 48
4 #define BITWISE_MASK ((1ULL << (BITWISE_BITS)) - 1)
8 uint64_t combine_none(uint64_t chain
, uint64_t arg
)
10 return (chain
& ~arg
) & BITWISE_MASK
;
13 uint64_t combine_any(uint64_t chain
, uint64_t arg
)
15 return (chain
| arg
) & BITWISE_MASK
;
18 uint64_t combine_all(uint64_t chain
, uint64_t arg
)
20 return (chain
& arg
) & BITWISE_MASK
;
23 uint64_t combine_parity(uint64_t chain
, uint64_t arg
)
25 return (chain
^ arg
) & BITWISE_MASK
;
28 uint64_t shift_lrotate(uint64_t base
, uint64_t amount
, uint64_t bits
)
30 uint64_t mask
= ((1ULL << bits
) - 1);
32 base
= (base
<< amount
) | (base
>> (bits
- amount
));
33 return base
& mask
& BITWISE_MASK
;
36 uint64_t shift_rrotate(uint64_t base
, uint64_t amount
, uint64_t bits
)
38 uint64_t mask
= ((1ULL << bits
) - 1);
40 base
= (base
>> amount
) | (base
<< (bits
- amount
));
41 return base
& mask
& BITWISE_MASK
;
44 uint64_t shift_lshift(uint64_t base
, uint64_t amount
, uint64_t bits
)
46 uint64_t mask
= ((1ULL << bits
) - 1);
48 return base
& mask
& BITWISE_MASK
;
51 uint64_t shift_lrshift(uint64_t base
, uint64_t amount
, uint64_t bits
)
53 uint64_t mask
= ((1ULL << bits
) - 1);
56 return base
& BITWISE_MASK
;
59 uint64_t shift_arshift(uint64_t base
, uint64_t amount
, uint64_t bits
)
61 uint64_t mask
= ((1ULL << bits
) - 1);
63 bool negative
= ((base
>> (bits
- 1)) != 0);
65 base
|= ((negative
? BITWISE_MASK
: 0) << (bits
- amount
));
66 return base
& mask
& BITWISE_MASK
;
69 template<uint64_t (*combine
)(uint64_t chain
, uint64_t arg
), uint64_t init
>
70 class lua_symmetric_bitwise
: public lua_function
73 lua_symmetric_bitwise(const std::string
& s
) : lua_function(s
) {};
74 int invoke(lua_State
* L
)
77 while(!lua_isnone(L
, stacksize
+ 1))
80 for(int i
= 0; i
< stacksize
; i
++)
81 ret
= combine(ret
, get_numeric_argument
<uint64_t>(L
, i
+ 1, fname
.c_str()));
82 lua_pushnumber(L
, ret
);
87 template<uint64_t (*shift
)(uint64_t base
, uint64_t amount
, uint64_t bits
)>
88 class lua_shifter
: public lua_function
91 lua_shifter(const std::string
& s
) : lua_function(s
) {};
92 int invoke(lua_State
* L
)
96 uint64_t bits
= BITWISE_BITS
;
97 base
= get_numeric_argument
<uint64_t>(L
, 1, fname
.c_str());
98 get_numeric_argument(L
, 2, amount
, fname
.c_str());
99 get_numeric_argument(L
, 3, bits
, fname
.c_str());
100 lua_pushnumber(L
, shift(base
, amount
, bits
));
105 function_ptr_luafun
lua_bextract("bit.extract", [](lua_State
* LS
, const std::string
& fname
) -> int {
106 uint64_t num
= get_numeric_argument
<uint64_t>(LS
, 1, fname
.c_str());
108 for(size_t i
= 0;; i
++) {
109 if(lua_isnumber(LS
, i
+ 2)) {
110 uint8_t bit
= get_numeric_argument
<uint8_t>(LS
, i
+ 2, fname
.c_str());
111 ret
|= (((num
>> bit
) & 1) << i
);
112 } else if(lua_isboolean(LS
, i
+ 2)) {
113 if(lua_toboolean(LS
, i
+ 2))
118 lua_pushnumber(LS
, ret
);
122 function_ptr_luafun
lua_bvalue("bit.value", [](lua_State
* LS
, const std::string
& fname
) -> int {
124 for(size_t i
= 0;; i
++) {
125 if(lua_isnumber(LS
, i
+ 1)) {
126 uint8_t bit
= get_numeric_argument
<uint8_t>(LS
, i
+ 1, fname
.c_str());
127 ret
|= (1ULL << bit
);
128 } else if(lua_isnil(LS
, i
+ 1)) {
132 lua_pushnumber(LS
, ret
);
136 lua_symmetric_bitwise
<combine_none
, BITWISE_MASK
> bit_none("bit.none");
137 lua_symmetric_bitwise
<combine_none
, BITWISE_MASK
> bit_bnot("bit.bnot");
138 lua_symmetric_bitwise
<combine_any
, 0> bit_any("bit.any");
139 lua_symmetric_bitwise
<combine_any
, 0> bit_bor("bit.bor");
140 lua_symmetric_bitwise
<combine_all
, BITWISE_MASK
> bit_all("bit.all");
141 lua_symmetric_bitwise
<combine_all
, BITWISE_MASK
> bit_band("bit.band");
142 lua_symmetric_bitwise
<combine_parity
, 0> bit_parity("bit.parity");
143 lua_symmetric_bitwise
<combine_parity
, 0> bit_bxor("bit.bxor");
144 lua_shifter
<shift_lrotate
> bit_lrotate("bit.lrotate");
145 lua_shifter
<shift_rrotate
> bit_rrotate("bit.rrotate");
146 lua_shifter
<shift_lshift
> bit_lshift("bit.lshift");
147 lua_shifter
<shift_arshift
> bit_arshift("bit.arshift");
148 lua_shifter
<shift_lrshift
> bit_lrshift("bit.lrshift");