বিষয়বস্তুতে চলুন

মডিউল:bit32

উইকিঅভিধান, মুক্ত অভিধান থেকে

এই মডিউলের জন্য মডিউল:bit32/নথি-এ নথিপত্র তৈরি করা হয়ে থাকতে পারে

-- Convert number to int
local to_int = math.floor
local abs = math.abs

-- Convert number to 32-bit unsigned int
local function to_int32(x)
	-- x % y >= 0 if y >= 0
	return to_int(x) % 0x100000000
end

-- 4x4 bit OR table, e.g. or_44[0x4E] = 0x4 | 0xE
local or_44 = {
	[0] =  0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14, 15,
	       1,  1,  3,  3,  5,  5,  7,  7,  9,  9, 11, 11, 13, 13, 15, 15,
	       2,  3,  2,  3,  6,  7,  6,  7, 10, 11, 10, 11, 14, 15, 14, 15,
	       3,  3,  3,  3,  7,  7,  7,  7, 11, 11, 11, 11, 15, 15, 15, 15,
	       4,  5,  6,  7,  4,  5,  6,  7, 12, 13, 14, 15, 12, 13, 14, 15,
	       5,  5,  7,  7,  5,  5,  7,  7, 13, 13, 15, 15, 13, 13, 15, 15,
	       6,  7,  6,  7,  6,  7,  6,  7, 14, 15, 14, 15, 14, 15, 14, 15,
	       7,  7,  7,  7,  7,  7,  7,  7, 15, 15, 15, 15, 15, 15, 15, 15,
	       8,  9, 10, 11, 12, 13, 14, 15,  8,  9, 10, 11, 12, 13, 14, 15,
	       9,  9, 11, 11, 13, 13, 15, 15,  9,  9, 11, 11, 13, 13, 15, 15,
	      10, 11, 10, 11, 14, 15, 14, 15, 10, 11, 10, 11, 14, 15, 14, 15,
	      11, 11, 11, 11, 15, 15, 15, 15, 11, 11, 11, 11, 15, 15, 15, 15,
	      12, 13, 14, 15, 12, 13, 14, 15, 12, 13, 14, 15, 12, 13, 14, 15,
	      13, 13, 15, 15, 13, 13, 15, 15, 13, 13, 15, 15, 13, 13, 15, 15,
	      14, 15, 14, 15, 14, 15, 14, 15, 14, 15, 14, 15, 14, 15, 14, 15,
	      15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
}

-- 4x4 bit AND table, e.g. and_44[0x4E] = 0x4 & 0xE
local and_44 = {
	[0] =  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
	       0,  1,  0,  1,  0,  1,  0,  1,  0,  1,  0,  1,  0,  1,  0,  1,
	       0,  0,  2,  2,  0,  0,  2,  2,  0,  0,  2,  2,  0,  0,  2,  2,
	       0,  1,  2,  3,  0,  1,  2,  3,  0,  1,  2,  3,  0,  1,  2,  3,
	       0,  0,  0,  0,  4,  4,  4,  4,  0,  0,  0,  0,  4,  4,  4,  4,
	       0,  1,  0,  1,  4,  5,  4,  5,  0,  1,  0,  1,  4,  5,  4,  5,
	       0,  0,  2,  2,  4,  4,  6,  6,  0,  0,  2,  2,  4,  4,  6,  6,
	       0,  1,  2,  3,  4,  5,  6,  7,  0,  1,  2,  3,  4,  5,  6,  7,
	       0,  0,  0,  0,  0,  0,  0,  0,  8,  8,  8,  8,  8,  8,  8,  8,
	       0,  1,  0,  1,  0,  1,  0,  1,  8,  9,  8,  9,  8,  9,  8,  9,
	       0,  0,  2,  2,  0,  0,  2,  2,  8,  8, 10, 10,  8,  8, 10, 10,
	       0,  1,  2,  3,  0,  1,  2,  3,  8,  9, 10, 11,  8,  9, 10, 11,
	       0,  0,  0,  0,  4,  4,  4,  4,  8,  8,  8,  8, 12, 12, 12, 12,
	       0,  1,  0,  1,  4,  5,  4,  5,  8,  9,  8,  9, 12, 13, 12, 13,
	       0,  0,  2,  2,  4,  4,  6,  6,  8,  8, 10, 10, 12, 12, 14, 14,
	       0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14, 15,
}

-- 4x4 bit XOR table, e.g. xor_44[0x4E] = 0x4 ^ 0xE
local xor_44 = {
	[0] =  0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14, 15,
	       1,  0,  3,  2,  5,  4,  7,  6,  9,  8, 11, 10, 13, 12, 15, 14,
	       2,  3,  0,  1,  6,  7,  4,  5, 10, 11,  8,  9, 14, 15, 12, 13,
	       3,  2,  1,  0,  7,  6,  5,  4, 11, 10,  9,  8, 15, 14, 13, 12,
	       4,  5,  6,  7,  0,  1,  2,  3, 12, 13, 14, 15,  8,  9, 10, 11,
	       5,  4,  7,  6,  1,  0,  3,  2, 13, 12, 15, 14,  9,  8, 11, 10,
	       6,  7,  4,  5,  2,  3,  0,  1, 14, 15, 12, 13, 10, 11,  8,  9,
	       7,  6,  5,  4,  3,  2,  1,  0, 15, 14, 13, 12, 11, 10,  9,  8,
	       8,  9, 10, 11, 12, 13, 14, 15,  0,  1,  2,  3,  4,  5,  6,  7,
	       9,  8, 11, 10, 13, 12, 15, 14,  1,  0,  3,  2,  5,  4,  7,  6,
	      10, 11,  8,  9, 14, 15, 12, 13,  2,  3,  0,  1,  6,  7,  4,  5,
	      11, 10,  9,  8, 15, 14, 13, 12,  3,  2,  1,  0,  7,  6,  5,  4,
	      12, 13, 14, 15,  8,  9, 10, 11,  4,  5,  6,  7,  0,  1,  2,  3,
	      13, 12, 15, 14,  9,  8, 11, 10,  5,  4,  7,  6,  1,  0,  3,  2,
	      14, 15, 12, 13, 10, 11,  8,  9,  6,  7,  4,  5,  2,  3,  0,  1,
	      15, 14, 13, 12, 11, 10,  9,  8,  7,  6,  5,  4,  3,  2,  1,  0,
}

local function b44(tbl, dflt, ...)
	-- apply bitwise operation in 4-bit chunks.
	-- tbl is the table of 16x16 values used to perform bitop on 4-bit blocks
	-- dflt is a default value if no args given
	local arg = { ... }
	local to_int = to_int
	local x = to_int32(arg[1] or dflt)
	local y, r
	for i = 2, # arg do
		y = to_int32(arg[i])
		-- for i = 1, 8 do
		--	r, q = r + q * tbl[(to_int(x / q) % 16) * 16 + (to_int(y / q) % 16)], q * 16
		-- end
		-- x = r
		-- inlined, with optimizations and precomputation:
		x = (             tbl[(       x               % 16) * 16 + (       y               % 16)] +
		     0x00000010 * tbl[(to_int(x / 0x00000010) % 16) * 16 + (to_int(y / 0x00000010) % 16)] +
		     0x00000100 * tbl[(to_int(x / 0x00000100) % 16) * 16 + (to_int(y / 0x00000100) % 16)] +
		     0x00001000 * tbl[(to_int(x / 0x00001000) % 16) * 16 + (to_int(y / 0x00001000) % 16)] +
		     0x00010000 * tbl[(to_int(x / 0x00010000) % 16) * 16 + (to_int(y / 0x00010000) % 16)] +
		     0x00100000 * tbl[(to_int(x / 0x00100000) % 16) * 16 + (to_int(y / 0x00100000) % 16)] +
		     0x01000000 * tbl[(to_int(x / 0x01000000) % 16) * 16 + (to_int(y / 0x01000000) % 16)] +
		     0x10000000 * tbl[(to_int(x / 0x10000000)     ) * 16 + (to_int(y / 0x10000000)     )])
	end
	return x
end

local function band(...)
	return b44(and_44, -1, ...)
end

local function bor(...)
	return b44(or_44, 0, ...)
end

local function bxor(...)
	return b44(xor_44, 0, ...)
end

local function bnot(x)
	return 0xFFFFFFFF - to_int32(x)
end

local function btest(...)
	return band(...) ~= 0
end

local function lshift(n, disp)
	disp = to_int(disp)
	return abs(disp) >= 32 and 0 or (to_int32(n) * (2 ^ disp)) % 0x100000000
end

local function rshift(n, disp)
	disp = to_int(disp)
	return abs(disp) >= 32 and 0 or to_int(to_int32(n) * (2 ^ -disp))
end

local function arshift(n, disp)
	n = to_int32(n)
	disp = to_int(disp)
	local r = abs(disp) >= 32 and 0 or to_int(n * (2 ^ -disp))
	if n >= 0x80000000 then
		if disp >= 32 then
			r = 0xFFFFFFFF
		elseif disp > 0 then
			r = r + to_int32(0xFFFFFFFF * 2 ^ (32 - disp))
		end
	end
	return r
end

local function lrotate(n, disp)
	n = n * 2 ^ (to_int(disp) % 32)
	return to_int(n / 0x100000000) + to_int32(n)
end

local function rrotate(n, disp)
	n = n * 2 ^ (32 - (to_int(disp) % 32))
	return to_int(n / 0x100000000) + to_int32(n)
end

local function extract(n, field, width)
	width = to_int(width or 1)
	field = to_int(field)
	if field < 0 or field + width > 32 or width < 0 then
		error("trying to access non-existent bits")
	end
	return to_int(to_int32(n) * 2 ^ -field) % (2 ^ width)
end

local function replace(n, v, field, width)
	width = to_int(width or 1)
	field = to_int(field)
	if field < 0 or field + width > 32 or width < 0 then
		error("trying to access non-existent bits")
	end
	local field_shift = 2 ^ field
	local field_width = 2 ^ width
	return band(n, 0xFFFFFFFF - field_shift * (field_width - 1)) + field_shift * (v % field_width)
end

return {
	band = band,
	bor = bor,
	bxor = bxor,
	bnot = bnot,
	btest = btest,

	lshift = lshift,
	rshift = rshift,
	arshift = arshift,
	lrotate = lrotate,
	rrotate = rrotate,

	extract = extract,
	replace = replace,
}