diff --git a/manual.lyx b/manual.lyx index f82ffbb7..48a7ebb9 100644 --- a/manual.lyx +++ b/manual.lyx @@ -2146,6 +2146,43 @@ bit.popcount(number a) Population count of a. \end_layout +\begin_layout Subsubsection +bit.clshift(number a, number b, [number amount,[number bits]]) +\end_layout + +\begin_layout Standard +Does chained left shift on a, b by amount positions, assuming numbers to + be of specified number of bits. +\end_layout + +\begin_layout Subsubsection +bit.crshift(number a, number b, [number amount,[number bits]]) +\end_layout + +\begin_layout Standard +Does chained right shift on a, b by amount positions, assuming numbers to + be of specified number of bits. +\end_layout + +\begin_layout Subsubsection +bit.flagdecode(number a, number bits, [string on, [string off]]) +\end_layout + +\begin_layout Standard +Return string of length bits where ith character is ith character of on + if bit i is on, otherwise ith character of off. + Out of range reads give last character, or '*'/'-' if empty. +\end_layout + +\begin_layout Subsubsection +bit.rflagdecode(number a, number bits, [string on, [string off]]) +\end_layout + +\begin_layout Standard +Like bit.flagdecode, but outputs the string in the opposite order (most significa +nt bit first). +\end_layout + \begin_layout Subsection Table gui: \end_layout diff --git a/manual.txt b/manual.txt index 528133da..e1a53731 100644 --- a/manual.txt +++ b/manual.txt @@ -1059,6 +1059,31 @@ Are all set bits in b also set in a? Population count of a. +8.2.15 bit.clshift(number a, number b, [number amount,[number + bits]]) + +Does chained left shift on a, b by amount positions, assuming +numbers to be of specified number of bits. + +8.2.16 bit.crshift(number a, number b, [number amount,[number + bits]]) + +Does chained right shift on a, b by amount positions, assuming +numbers to be of specified number of bits. + +8.2.17 bit.flagdecode(number a, number bits, [string on, [string + off]]) + +Return string of length bits where ith character is ith character +of on if bit i is on, otherwise ith character of off. Out of +range reads give last character, or '*'/'-' if empty. + +8.2.18 bit.rflagdecode(number a, number bits, [string on, [string + off]]) + +Like bit.flagdecode, but outputs the string in the opposite order +(most significant bit first). + 8.3 Table gui: Most of these functions can only be called in on_paint and diff --git a/src/lua/bit.cpp b/src/lua/bit.cpp index 67951b99..e1f7e2b9 100644 --- a/src/lua/bit.cpp +++ b/src/lua/bit.cpp @@ -1,4 +1,5 @@ #include "lua/internal.hpp" +#include "library/minmax.hpp" #define BITWISE_BITS 48 #define BITWISE_MASK ((1ULL << (BITWISE_BITS)) - 1) @@ -165,6 +166,79 @@ namespace return 1; }); + function_ptr_luafun lua_clshift("bit.clshift", [](lua_State* LS, const std::string& fname) -> int { + unsigned amount = 1; + unsigned bits = 48; + uint64_t a = get_numeric_argument(LS, 1, fname.c_str()); + uint64_t b = get_numeric_argument(LS, 2, fname.c_str()); + get_numeric_argument(LS, 3, amount, fname.c_str()); + get_numeric_argument(LS, 4, bits, fname.c_str()); + uint64_t mask = ((1ULL << bits) - 1); + a &= mask; + b &= mask; + a <<= amount; + a &= mask; + a |= (b >> (bits - amount)); + b <<= amount; + b &= mask; + lua_pushnumber(LS, a); + lua_pushnumber(LS, b); + return 2; + }); + + function_ptr_luafun lua_crshift("bit.crshift", [](lua_State* LS, const std::string& fname) -> int { + unsigned amount = 1; + unsigned bits = 48; + uint64_t a = get_numeric_argument(LS, 1, fname.c_str()); + uint64_t b = get_numeric_argument(LS, 2, fname.c_str()); + get_numeric_argument(LS, 3, amount, fname.c_str()); + get_numeric_argument(LS, 4, bits, fname.c_str()); + uint64_t mask = ((1ULL << bits) - 1); + a &= mask; + b &= mask; + b >>= amount; + b |= (a << (bits - amount)); + b &= mask; + a >>= amount; + lua_pushnumber(LS, a); + lua_pushnumber(LS, b); + return 2; + }); + + int flagdecode_core(lua_State* LS, const std::string& fname, bool reverse) + { + uint64_t a = get_numeric_argument(LS, 1, fname.c_str()); + uint64_t b = get_numeric_argument(LS, 2, fname.c_str()); + std::string on, off; + if(lua_type(LS, 3) == LUA_TSTRING) + on = get_string_argument(LS, 3, fname.c_str()); + if(lua_type(LS, 4) == LUA_TSTRING) + off = get_string_argument(LS, 4, fname.c_str()); + size_t onl = on.length(); + size_t offl = off.length(); + char onc = onl ? on[onl - 1] : '*'; + char offc = offl ? off[offl - 1] : '-'; + char buffer[65]; + unsigned i; + size_t bias = min(b, (uint64_t)64) - 1; + for(i = 0; i < 64 && i < b; i++) { + char onc2 = (i < onl) ? on[i] : onc; + char offc2 = (i < offl) ? off[i] : offc; + buffer[reverse ? (bias - i) : i] = ((a >> i) & 1) ? onc2 : offc2; + } + buffer[i] = '\0'; + lua_pushstring(LS, buffer); + return 1; + } + + function_ptr_luafun lua_flagdecode("bit.flagdecode", [](lua_State* LS, const std::string& fname) -> int { + return flagdecode_core(LS, fname, false); + }); + + function_ptr_luafun lua_rflagdecode("bit.rflagdecode", [](lua_State* LS, const std::string& fname) -> int { + return flagdecode_core(LS, fname, true); + }); + lua_symmetric_bitwise bit_none("bit.none"); lua_symmetric_bitwise bit_bnot("bit.bnot"); lua_symmetric_bitwise bit_any("bit.any");