Skip to content

Instantly share code, notes, and snippets.

@pablomayobre
Created April 2, 2016 20:13
Show Gist options
  • Save pablomayobre/41acbf4918ad4465c4cc8e151d940a81 to your computer and use it in GitHub Desktop.
Save pablomayobre/41acbf4918ad4465c4cc8e151d940a81 to your computer and use it in GitHub Desktop.
Bite is a common bit operations interface that uses BitOps, bit32, Lua 5.3 bit operators or plain Lua bit operations (The api is the same as BitOps plus some functions from bit32)
local bit = {}
local normalize = function (...)
local t = {}
for k,v in ipairs{...} do
t[k] = v <= 0x7fffffff and v or -(bit.bnot(v) + 1)
end
end
--LuaJIT BitOp library
local ok, bit = pcall(require, "bit")
if ok then
bit.bswap, bit.tohex = nil,nil
end
--Lua 5.2 bit32 library
if not ok then
ok, bit = pcall(require, "bit32")
if ok then
bit.replace, bit.extract, bit.btest = nil,nil,nil
bit.tobit = function (a)
return bit.bnot(bit.bnot(a))
end
bit.rol = bit.lrotate
bit.ror = bit.rrotate
local _oldlshift, _oldrshift _oldarshift = bit.lshift, bit.rshift, bit.arshift
bit.lshift = function (a,disp)
local disp = disp % 32
return _oldlshift(a,disp)
end
bit.rshift = function (a,disp)
local disp = disp % 32
return _oldrshift(a,disp)
end
bit.arshift = function (a,disp)
local disp = disp % 32
return _oldarshift(a,disp)
end
for k,v in pairs(bit) do
bit[k] = function (...) return normalize(v(...)) end
end
end
end
--Pure Lua implementation
if _VERSION == "Lua 5.3" then
local s = [[
local bit = {}
bit.tobit = function (a)
return math.tointeger(a) & 0xffffffff
end
bit.bnot = function (a)
return (~a) & 0xffffffff
end
local bxor,band,bor
bxor = function (a,b,...)
if b == nil then return a end
local c = (a ~ b) & 0xffffffff
return bxor(c,...)
end
band = function (a,b,...)
if b == nil then return a end
local c = (a & b) & 0xffffffff
return band(c,...)
end
bor = function (a,b,...)
if b == nil then return a end
local c = (a | b) & 0xffffffff
return bor(c,...)
end
bit.bxor = bxor
bit.band = band
bit.bor = bor
bit.rshift = function (a,disp)
local disp = math.tointeger(disp % 32)
return (a >> disp) & 0xffffffff
end
bit.lshift = function (a,disp)
local disp = math.tointeger(disp % 32)
return (a << disp) & 0xffffffff
end
bit.arshift = function (a,disp)
local disp = math.integer(disp % 32)
local a = math.tointeger(a) & 0xffffffff
if a == 0 then return a end
if disp > 0 then
local s = a > 0 and 1 or -1
local b = a > 0 and 0 or 1
return (s * (math.abs(a) >> disp) - b) & 0xffffffff
elseif disp < 0 then
return (a << disp) & 0xffffffff
else
return a
end
end
bit.ror = function ()
local disp = math.tointeger(disp % 32)
if a == 0 or disp == 0 then return a end
local a = math.tointeger(a) & 0xffffffff
local b,c = a << (31 - disp), a >> disp
return math.tointeger(b) + math.tointeger(c)
end
bit.rol = function ()
local disp = math.tointeger(disp % 32)
if a == 0 or disp == 0 then return a end
local a = math.tointeger(a) & 0xffffffff
local b,c = a << disp, a >> (31 - disp)
return math.tointeger(b) + math.tointeger(c)
end
for k,v in pairs(bit) do
bit[k] = function (...) return normalize(v(...)) end
end
return bit
]]
local err
ok,err = load(s,"bit","t")
if ok then
bit = ok()
end
end
if not ok then
bit = {}
bit.tobit = function (a)
return math.floor(a) % (0xffffffff + 1)
end
local xort = {{0,1},{1,0}}
local andt = {{0,0},{0,1}}
local ort = {{0,1},{1,1}}
local master
master = function (t,a,b,...)
if b == nil then return a end
local a,b = bit.tobit(a),bit.tobit(b)
local pow = 1
local c = 0
while a > 0 or b > 0 do
c = c + (t[(a % 2)+1][(b % 2)+1] * pow)
a = math.floor(a/2)
b = math.floor(b/2)
pow = pow * 2
end
return master(t,c,...)
end
bit.bnot = function (x)
local x = bit.tobit(x)
return bit.tobit((-1 - x) % 2^32)
end
bit.bxor = function (...)
return bit.tobit(master(xort,...))
end
bit.band = function (...)
return bit.tobit(master(andt,...))
end
bit.bor = function (...)
return bit.tobit(master(ort,...))
end
bit.lshift = function (a,disp)
local disp = math.floor(disp % 32)
if a == 0 or disp == 0 then return a end
local a = bit.tobit(a)
return bit.tobit(a * 2 ^ disp)
end
bit.rshift = function (a,disp)
local disp = math.floor(disp % 32)
if a == 0 or disp == 0 then return a end
local a = bit.tobit(a)
return bit.tobit(math.floor(a / 2 ^ disp))
end
bit.arshift = function (a,disp)
local disp = math.floor(disp % 32)
if a == 0 then return a end
local a = bit.tobit(a)
if disp > 0 then
local s = a > 0 and 1 or -1
local b = a > 0 and 0 or 1
return bit.tobit(s * (math.abs(a) / 2 ^ disp) - b)
elseif disp < 0 then
return bit.tobit(a * 2 ^ disp)
else
return a
end
end
bit.ror = function (a,disp)
local disp = math.floor(disp % 32)
if a == 0 or disp == 0 then return a end
local a = bit.tobit(a)
local b,c = a * 2 ^ (31 - disp), a / 2 ^ disp
return bit.tobit(bit.tobit(b) + bit.tobit(c))
end
bit.rol = function (a,disp)
local disp = math.floor(31 - (disp % 32))
if a == 0 or disp == 0 then return a end
return bit.ror(a,disp)
end
for k,v in pairs(bit) do
bit[k] = function (...) return normalize(v(...)) end
end
end
return bit
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment