Skip to content

Commit

Permalink
- Add bitop
Browse files Browse the repository at this point in the history
  • Loading branch information
ParticleG committed Nov 18, 2024
1 parent a2fbb31 commit f6afd7b
Show file tree
Hide file tree
Showing 2 changed files with 373 additions and 0 deletions.
366 changes: 366 additions & 0 deletions assets/bitop.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,366 @@
local M = {_TYPE='module', _NAME='bitop.funcs', _VERSION='1.0-0'}

local floor = math.floor

local MOD = 2 ^ 32
local MODM = MOD - 1

local function memoize(f)

local mt = {}
local t = setmetatable({}, mt)

function mt:__index(k)
local v = f(k)
t[k] = v
return v
end

return t
end

local function make_bitop_uncached(t, m)
local function bitop(a, b)
local res, p = 0, 1
while a ~= 0 and b ~= 0 do
local am, bm = a % m, b % m
res = res + t[am][bm] * p
a = (a - am) / m
b = (b - bm) / m
p = p * m
end
res = res + (a + b) * p
return res
end
return bitop
end

local function make_bitop(t)
local op1 = make_bitop_uncached(t, 2 ^ 1)
local op2 = memoize(function(a)
return memoize(function(b)
return op1(a, b)
end)
end)
return make_bitop_uncached(op2, 2 ^ (t.n or 1))
end

-- ok? probably not if running on a 32-bit int Lua number type platform
function M.tobit(x)
return x % 2 ^ 32
end

M.bxor = make_bitop{[0]={[0]=0, [1]=1}, [1]={[0]=1, [1]=0}, n=4}
local bxor = M.bxor

function M.bnot(a)
return MODM - a
end
local bnot = M.bnot

function M.band(a, b)
return ((a + b) - bxor(a, b)) / 2
end
local band = M.band

function M.bor(a, b)
return MODM - band(MODM - a, MODM - b)
end
local bor = M.bor

local lshift, rshift -- forward declare

function M.rshift(a, disp) -- Lua5.2 insipred
if disp < 0 then
return lshift(a, -disp)
end
return floor(a % 2 ^ 32 / 2 ^ disp)
end
rshift = M.rshift

function M.lshift(a, disp) -- Lua5.2 inspired
if disp < 0 then
return rshift(a, -disp)
end
return (a * 2 ^ disp) % 2 ^ 32
end
lshift = M.lshift

function M.tohex(x, n) -- BitOp style
n = n or 8
local up
if n <= 0 then
if n == 0 then
return ''
end
up = true
n = -n
end
x = band(x, 16 ^ n - 1)
return ('%0' .. n .. (up and 'X' or 'x')):format(x)
end
local tohex = M.tohex

function M.extract(n, field, width) -- Lua5.2 inspired
width = width or 1
return band(rshift(n, field), 2 ^ width - 1)
end
local extract = M.extract

function M.replace(n, v, field, width) -- Lua5.2 inspired
width = width or 1
local mask1 = 2 ^ width - 1
v = band(v, mask1) -- required by spec?
local mask = bnot(lshift(mask1, field))
return band(n, mask) + lshift(v, field)
end
local replace = M.replace

function M.bswap(x) -- BitOp style
local a = band(x, 0xff);
x = rshift(x, 8)
local b = band(x, 0xff);
x = rshift(x, 8)
local c = band(x, 0xff);
x = rshift(x, 8)
local d = band(x, 0xff)
return lshift(lshift(lshift(a, 8) + b, 8) + c, 8) + d
end
local bswap = M.bswap

function M.rrotate(x, disp) -- Lua5.2 inspired
disp = disp % 32
local low = band(x, 2 ^ disp - 1)
return rshift(x, disp) + lshift(low, 32 - disp)
end
local rrotate = M.rrotate

function M.lrotate(x, disp) -- Lua5.2 inspired
return rrotate(x, -disp)
end
local lrotate = M.lrotate

M.rol = M.lrotate -- LuaOp inspired
M.ror = M.rrotate -- LuaOp insipred

function M.arshift(x, disp) -- Lua5.2 inspired
local z = rshift(x, disp)
if x >= 0x80000000 then
z = z + lshift(2 ^ disp - 1, 32 - disp)
end
return z
end
local arshift = M.arshift

function M.btest(x, y) -- Lua5.2 inspired
return band(x, y) ~= 0
end

--
-- Start Lua 5.2 "bit32" compat section.
--

M.bit32 = {} -- Lua 5.2 'bit32' compatibility

local function bit32_bnot(x)
return (-1 - x) % MOD
end
M.bit32.bnot = bit32_bnot

local function bit32_bxor(a, b, c, ...)
local z
if b then
a = a % MOD
b = b % MOD
z = bxor(a, b)
if c then
z = bit32_bxor(z, c, ...)
end
return z
elseif a then
return a % MOD
else
return 0
end
end
M.bit32.bxor = bit32_bxor

local function bit32_band(a, b, c, ...)
local z
if b then
a = a % MOD
b = b % MOD
z = ((a + b) - bxor(a, b)) / 2
if c then
z = bit32_band(z, c, ...)
end
return z
elseif a then
return a % MOD
else
return MODM
end
end
M.bit32.band = bit32_band

local function bit32_bor(a, b, c, ...)
local z
if b then
a = a % MOD
b = b % MOD
z = MODM - band(MODM - a, MODM - b)
if c then
z = bit32_bor(z, c, ...)
end
return z
elseif a then
return a % MOD
else
return 0
end
end
M.bit32.bor = bit32_bor

function M.bit32.btest(...)
return bit32_band(...) ~= 0
end

function M.bit32.lrotate(x, disp)
return lrotate(x % MOD, disp)
end

function M.bit32.rrotate(x, disp)
return rrotate(x % MOD, disp)
end

function M.bit32.lshift(x, disp)
if disp > 31 or disp < -31 then
return 0
end
return lshift(x % MOD, disp)
end

function M.bit32.rshift(x, disp)
if disp > 31 or disp < -31 then
return 0
end
return rshift(x % MOD, disp)
end

function M.bit32.arshift(x, disp)
x = x % MOD
if disp >= 0 then
if disp > 31 then
return (x >= 0x80000000) and MODM or 0
else
local z = rshift(x, disp)
if x >= 0x80000000 then
z = z + lshift(2 ^ disp - 1, 32 - disp)
end
return z
end
else
return lshift(x, -disp)
end
end

function M.bit32.extract(x, field, ...)
local width = ... or 1
if field < 0 or field > 31 or width < 0 or field + width > 32 then
error'out of range'
end
x = x % MOD
return extract(x, field, ...)
end

function M.bit32.replace(x, v, field, ...)
local width = ... or 1
if field < 0 or field > 31 or width < 0 or field + width > 32 then
error'out of range'
end
x = x % MOD
v = v % MOD
return replace(x, v, field, ...)
end

--
-- Start LuaBitOp "bit" compat section.
--

M.bit = {} -- LuaBitOp "bit" compatibility

function M.bit.tobit(x)
x = x % MOD
if x >= 0x80000000 then
x = x - MOD
end
return x
end
local bit_tobit = M.bit.tobit

function M.bit.tohex(x, ...)
return tohex(x % MOD, ...)
end

function M.bit.bnot(x)
return bit_tobit(bnot(x % MOD))
end

local function bit_bor(a, b, c, ...)
if c then
return bit_bor(bit_bor(a, b), c, ...)
elseif b then
return bit_tobit(bor(a % MOD, b % MOD))
else
return bit_tobit(a)
end
end
M.bit.bor = bit_bor

local function bit_band(a, b, c, ...)
if c then
return bit_band(bit_band(a, b), c, ...)
elseif b then
return bit_tobit(band(a % MOD, b % MOD))
else
return bit_tobit(a)
end
end
M.bit.band = bit_band

local function bit_bxor(a, b, c, ...)
if c then
return bit_bxor(bit_bxor(a, b), c, ...)
elseif b then
return bit_tobit(bxor(a % MOD, b % MOD))
else
return bit_tobit(a)
end
end
M.bit.bxor = bit_bxor

function M.bit.lshift(x, n)
return bit_tobit(lshift(x % MOD, n % 32))
end

function M.bit.rshift(x, n)
return bit_tobit(rshift(x % MOD, n % 32))
end

function M.bit.arshift(x, n)
return bit_tobit(arshift(x % MOD, n % 32))
end

function M.bit.rol(x, n)
return bit_tobit(lrotate(x % MOD, n % 32))
end

function M.bit.ror(x, n)
return bit_tobit(rrotate(x % MOD, n % 32))
end

function M.bit.bswap(x)
return bit_tobit(bswap(x % MOD))
end

return M
7 changes: 7 additions & 0 deletions main.lua
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,13 @@ love.setDeprecationOutput(false)
love.keyboard.setTextInput(false)
VERSION=require'version'

-- Bit module
local success
success,bit=pcall(require,"bit")
if not success then
bit=require"assets.bitop".bit
end

--------------------------------------------------------------
-- Create directories

Expand Down

0 comments on commit f6afd7b

Please sign in to comment.