1 #include "lua/internal.hpp"
2 #include "library/minmax.hpp"
3 #include "library/int24.hpp"
4 #include "library/serialization.hpp"
8 template<unsigned nbits
>
12 return 0xFFFFFFFFFFFFFFFFULL
;
14 return (1ULL << (nbits
&63)) - 1;
17 uint64_t maskx(unsigned nbits
)
20 return 0xFFFFFFFFFFFFFFFFULL
;
22 return (1ULL << (nbits
&63)) - 1;
25 template<unsigned nbits
>
26 uint64_t combine_none(uint64_t chain
, uint64_t arg
)
28 return (chain
& ~arg
) & maskn
<nbits
>();
31 template<unsigned nbits
>
32 uint64_t combine_any(uint64_t chain
, uint64_t arg
)
34 return (chain
| arg
) & maskn
<nbits
>();
37 template<unsigned nbits
>
38 uint64_t combine_all(uint64_t chain
, uint64_t arg
)
40 return (chain
& arg
) & maskn
<nbits
>();
43 template<unsigned nbits
>
44 uint64_t combine_parity(uint64_t chain
, uint64_t arg
)
46 return (chain
^ arg
) & maskn
<nbits
>();
49 template<unsigned nbits
>
50 uint64_t shift_lrotate(uint64_t base
, uint64_t amount
, uint64_t bits
)
52 uint64_t mask
= maskx(bits
);
54 base
= (base
<< amount
) | (base
>> (bits
- amount
));
55 return base
& mask
& maskn
<nbits
>();
58 template<unsigned nbits
>
59 uint64_t shift_rrotate(uint64_t base
, uint64_t amount
, uint64_t bits
)
61 uint64_t mask
= maskx(bits
);
63 base
= (base
>> amount
) | (base
<< (bits
- amount
));
64 return base
& mask
& maskn
<nbits
>();
67 template<unsigned nbits
>
68 uint64_t shift_lshift(uint64_t base
, uint64_t amount
, uint64_t bits
)
70 uint64_t mask
= maskx(bits
);
72 return base
& mask
& maskn
<nbits
>();
75 template<unsigned nbits
>
76 uint64_t shift_lrshift(uint64_t base
, uint64_t amount
, uint64_t bits
)
78 uint64_t mask
= maskx(bits
);
81 return base
& maskn
<nbits
>();
84 template<unsigned nbits
>
85 uint64_t shift_arshift(uint64_t base
, uint64_t amount
, uint64_t bits
)
87 uint64_t mask
= maskx(bits
);
89 bool negative
= ((base
>> (bits
- 1)) != 0);
91 base
|= ((negative
? maskn
<nbits
>() : 0) << (bits
- amount
));
92 return base
& mask
& maskn
<nbits
>();
100 template<unsigned nbits
>
103 return maskn
<nbits
>();
106 template<uint64_t (*combine
)(uint64_t chain
, uint64_t arg
), uint64_t (*init
)()>
107 int fold(lua::state
& L
, lua::parameters
& P
)
109 uint64_t ret
= init();
111 ret
= combine(ret
, P
.arg
<uint64_t>());
116 template<uint64_t (*sh
)(uint64_t base
, uint64_t amount
, uint64_t bits
), unsigned nbits
>
117 int shift(lua::state
& L
, lua::parameters
& P
)
119 uint64_t base
, amount
, bits
;
121 P(base
, P
.optional(amount
, 1), P
.optional(bits
, nbits
));
123 L
.pushnumber(sh(base
, amount
, bits
));
128 int bswap(lua::state
& L
, lua::parameters
& P
)
134 serialization::swap_endian(val
);
139 int bit_extract(lua::state
& L
, lua::parameters
& P
)
146 for(size_t i
= 0;; i
++) {
150 } else if(P
.is_number()) {
151 ret
|= (((num
>> P
.arg
<uint8_t>()) & 1) << i
);
159 int bit_value(lua::state
& L
, lua::parameters
& P
)
162 for(size_t i
= 0;; i
++) {
164 ret
|= (1ULL << P
.arg
<uint8_t>());
165 } else if(P
.is_nil()) {
174 int bit_test(lua::state
& L
, lua::parameters
& P
)
181 bool c
= all
? (t
== b
) : (t
!= 0);
186 template<bool complement
>
187 int bit_test2(lua::state
& L
, lua::parameters
& P
)
193 uint64_t t
= a
& (1ULL << b
);
194 L
.pushboolean((t
!= 0) != complement
);
198 const int CONST_poptable
[] = {0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4};
200 int popcount(uint64_t x
)
203 for(unsigned i
= 0; i
< 16; i
++) {
204 c
+= CONST_poptable
[x
& 15];
210 int bit_popcount(lua::state
& L
, lua::parameters
& P
)
216 L
.pushnumber(popcount(a
));
220 template<bool right
, unsigned nbits
>
221 int bit_cshift(lua::state
& L
, lua::parameters
& P
)
224 unsigned amount
, bits
;
226 P(a
, b
, P
.optional(amount
, 1), P
.optional(bits
, nbits
));
228 uint64_t mask
= maskx(bits
);
233 b
|= (a
<< (bits
- amount
));
239 a
|= (b
>> (bits
- amount
));
248 template<bool reverse
>
249 int flagdecode_core(lua::state
& L
, lua::parameters
& P
)
254 P(a
, b
, P
.optional(on
, ""), P
.optional(off
, ""));
256 auto on32
= utf8::to32(on
);
257 auto off32
= utf8::to32(off
);
259 size_t onl
= on32
.length();
260 size_t offl
= off32
.length();
261 auto onc
= onl
? on32
[onl
- 1] : '*';
262 auto offc
= offl
? off32
[offl
- 1] : '-';
265 size_t bias
= min(b
, (uint64_t)64) - 1;
266 for(i
= 0; i
< 64 && i
< b
; i
++) {
267 auto onc2
= (i
< onl
) ? on32
[i
] : onc
;
268 auto offc2
= (i
< offl
) ? off32
[i
] : offc
;
269 buffer
[reverse
? (bias
- i
) : i
] = ((a
>> i
) & 1) ? onc2
: offc2
;
272 L
.pushlstring(utf8::to8(buffer
));
276 int bit_compose(lua::state
& L
, lua::parameters
& P
)
290 template<typename T
, bool littleendian
>
291 int bit_ldbinarynumber(lua::state
& L
, lua::parameters
& P
)
297 str
= L
.tolstring(P
.skip(), len
);
300 if(pos
+ sizeof(T
) > len
)
301 throw std::runtime_error(P
.get_fname() + ": Offset out of range");
303 L
.pushnumber(serialization::read_endian
<T
>(str
+ pos
, littleendian
? -1 : 1));
307 template<typename T
, bool littleendian
>
308 int bit_stbinarynumber(lua::state
& L
, lua::parameters
& P
)
311 char buffer
[sizeof(T
)];
315 serialization::write_endian
<T
>(buffer
, val
, littleendian
? -1 : 1);
316 L
.pushlstring(buffer
, sizeof(T
));
320 int bit_quotent(lua::state
& L
, lua::parameters
& P
)
330 int bit_multidiv(lua::state
& L
, lua::parameters
& P
)
333 unsigned values
= L
.gettop();
337 for(unsigned i
= 1; i
< values
; i
++) {
348 int bit_mul32(lua::state
& L
, lua::parameters
& P
)
356 L
.pushnumber(c
& 0xFFFFFFFFU
);
357 L
.pushnumber(c
>> 32);
361 int bit_fextract(lua::state
& L
, lua::parameters
& P
)
369 L
.pushnumber(a
>> b
);
371 L
.pushnumber((a
>> b
) & ((1 << c
) - 1));
375 int bit_bfields(lua::state
& L
, lua::parameters
& P
)
378 unsigned values
= L
.gettop();
381 for(unsigned i
= 1; i
< values
; i
++) {
388 L
.pushnumber(v
& ((1 << q
) - 1));
395 lua::functions
LUA_bitops_fn(lua_func_bit
, "bit", {
396 {"flagdecode", flagdecode_core
<false>},
397 {"rflagdecode", flagdecode_core
<true>},
398 {"none", fold
<combine_none
<48>, ones
<48>>},
399 {"any", fold
<combine_any
<48>, zero
>},
400 {"all", fold
<combine_all
<48>, ones
<48>>},
401 {"parity", fold
<combine_parity
<48>, zero
>},
402 {"bnot", fold
<combine_none
<48>, ones
<48>>},
403 {"bor", fold
<combine_any
<48>, zero
>},
404 {"band", fold
<combine_all
<48>, ones
<48>>},
405 {"bxor", fold
<combine_parity
<48>, zero
>},
406 {"lrotate", shift
<shift_lrotate
<48>, 48>},
407 {"rrotate", shift
<shift_rrotate
<48>, 48>},
408 {"lshift", shift
<shift_lshift
<48>, 48>},
409 {"arshift", shift
<shift_arshift
<48>, 48>},
410 {"lrshift", shift
<shift_lrshift
<48>, 48>},
411 #ifdef LUA_SUPPORTS_INTEGERS
412 {"wnone", fold
<combine_none
<64>, ones
<64>>},
413 {"wany", fold
<combine_any
<64>, zero
>},
414 {"wall", fold
<combine_all
<64>, ones
<64>>},
415 {"wparity", fold
<combine_parity
<64>, zero
>},
416 {"wbnot", fold
<combine_none
<64>, ones
<64>>},
417 {"wbor", fold
<combine_any
<64>, zero
>},
418 {"wband", fold
<combine_all
<64>, ones
<64>>},
419 {"wbxor", fold
<combine_parity
<64>, zero
>},
420 {"wlrotate", shift
<shift_lrotate
<64>, 64>},
421 {"wrrotate", shift
<shift_rrotate
<64>, 64>},
422 {"wlshift", shift
<shift_lshift
<64>, 64>},
423 {"warshift", shift
<shift_arshift
<64>, 64>},
424 {"wlrshift", shift
<shift_lrshift
<64>, 64>},
425 {"wclshift", bit_cshift
<false, 64>},
426 {"wcrshift", bit_cshift
<true, 64>},
428 {"swapword", bswap
<uint16_t>},
429 {"swaphword", bswap
<ss_uint24_t
>},
430 {"swapdword", bswap
<uint32_t>},
431 {"swapqword", bswap
<uint64_t>},
432 {"swapsword", bswap
<int16_t>},
433 {"swapshword", bswap
<ss_int24_t
>},
434 {"swapsdword", bswap
<int32_t>},
435 {"swapsqword", bswap
<int64_t>},
436 {"extract", bit_extract
},
437 {"value", bit_value
},
438 {"test_any", bit_test
<false>},
439 {"test_all", bit_test
<true>},
440 {"test", bit_test2
<false>},
441 {"testn", bit_test2
<true>},
442 {"popcount", bit_popcount
},
443 {"clshift", bit_cshift
<false, 48>},
444 {"crshift", bit_cshift
<true, 48>},
445 {"compose", bit_compose
},
446 {"quotent", bit_quotent
},
447 {"multidiv", bit_multidiv
},
448 {"mul32", bit_mul32
},
449 {"fextract", bit_fextract
},
450 {"bfields", bit_bfields
},
451 {"binary_ld_u8be", bit_ldbinarynumber
<uint8_t, false>},
452 {"binary_ld_s8be", bit_ldbinarynumber
<int8_t, false>},
453 {"binary_ld_u16be", bit_ldbinarynumber
<uint16_t, false>},
454 {"binary_ld_s16be", bit_ldbinarynumber
<int16_t, false>},
455 {"binary_ld_u24be", bit_ldbinarynumber
<ss_uint24_t
, false>},
456 {"binary_ld_s24be", bit_ldbinarynumber
<ss_int24_t
, false>},
457 {"binary_ld_u32be", bit_ldbinarynumber
<uint32_t, false>},
458 {"binary_ld_s32be", bit_ldbinarynumber
<int32_t, false>},
459 {"binary_ld_u64be", bit_ldbinarynumber
<uint64_t, false>},
460 {"binary_ld_s64be", bit_ldbinarynumber
<int64_t, false>},
461 {"binary_ld_floatbe", bit_ldbinarynumber
<float, false>},
462 {"binary_ld_doublebe", bit_ldbinarynumber
<double, false>},
463 {"binary_ld_u8le", bit_ldbinarynumber
<uint8_t, true>},
464 {"binary_ld_s8le", bit_ldbinarynumber
<int8_t, true>},
465 {"binary_ld_u16le", bit_ldbinarynumber
<uint16_t, true>},
466 {"binary_ld_s16le", bit_ldbinarynumber
<int16_t, true>},
467 {"binary_ld_u24le", bit_ldbinarynumber
<ss_uint24_t
, true>},
468 {"binary_ld_s24le", bit_ldbinarynumber
<ss_int24_t
, true>},
469 {"binary_ld_u32le", bit_ldbinarynumber
<uint32_t, true>},
470 {"binary_ld_s32le", bit_ldbinarynumber
<int32_t, true>},
471 {"binary_ld_u64le", bit_ldbinarynumber
<uint64_t, true>},
472 {"binary_ld_s64le", bit_ldbinarynumber
<int64_t, true>},
473 {"binary_ld_floatle", bit_ldbinarynumber
<float, true>},
474 {"binary_ld_doublele", bit_ldbinarynumber
<double, true>},
475 {"binary_st_u8be", bit_stbinarynumber
<uint8_t, false>},
476 {"binary_st_s8be", bit_stbinarynumber
<int8_t, false>},
477 {"binary_st_u16be", bit_stbinarynumber
<uint16_t, false>},
478 {"binary_st_s16be", bit_stbinarynumber
<int16_t, false>},
479 {"binary_st_u24be", bit_stbinarynumber
<ss_uint24_t
, false>},
480 {"binary_st_s24be", bit_stbinarynumber
<ss_int24_t
, false>},
481 {"binary_st_u32be", bit_stbinarynumber
<uint32_t, false>},
482 {"binary_st_s32be", bit_stbinarynumber
<int32_t, false>},
483 {"binary_st_u64be", bit_stbinarynumber
<uint64_t, false>},
484 {"binary_st_s64be", bit_stbinarynumber
<int64_t, false>},
485 {"binary_st_floatbe", bit_stbinarynumber
<float, false>},
486 {"binary_st_doublebe", bit_stbinarynumber
<double, false>},
487 {"binary_st_u8le", bit_stbinarynumber
<uint8_t, true>},
488 {"binary_st_s8le", bit_stbinarynumber
<int8_t, true>},
489 {"binary_st_u16le", bit_stbinarynumber
<uint16_t, true>},
490 {"binary_st_s16le", bit_stbinarynumber
<int16_t, true>},
491 {"binary_st_u24le", bit_stbinarynumber
<ss_uint24_t
, true>},
492 {"binary_st_s24le", bit_stbinarynumber
<ss_int24_t
, true>},
493 {"binary_st_u32le", bit_stbinarynumber
<uint32_t, true>},
494 {"binary_st_s32le", bit_stbinarynumber
<int32_t, true>},
495 {"binary_st_u64le", bit_stbinarynumber
<uint64_t, true>},
496 {"binary_st_s64le", bit_stbinarynumber
<int64_t, true>},
497 {"binary_st_floatle", bit_stbinarynumber
<float, true>},
498 {"binary_st_doublele", bit_stbinarynumber
<double, true>},