-
-
Save airstruck/7512632fc86afc36998d7b8290045ad8 to your computer and use it in GitHub Desktop.
bit packing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
local Smash = {} | |
local FULL_BYTE = 256 | |
local INV_BYTE = 1 / FULL_BYTE | |
local char, floor = string.char, math.floor | |
local tinsert, tconcat = table.insert, table.concat | |
local function bytesToString (byteArray) | |
for i = 1, #byteArray do byteArray[i] = char(byteArray[i]) end | |
return tconcat(byteArray) | |
end | |
local function packBytes (num) | |
local out = {} | |
while num > 0 do | |
out[#out + 1] = num % FULL_BYTE | |
num = floor(num * INV_BYTE) | |
end | |
return out | |
end | |
function Smash.packArray (ints, bits) | |
local num = 0 | |
for i = 1, #ints do num = num * 2 ^ bits + ints[i] end | |
return bytesToString(packBytes(num)) | |
end | |
function Smash.packFields (ints, fields) | |
local num = 0 | |
for i = 1, #fields do num = num * 2 ^ fields[i] + (ints[i] or 0) end | |
return bytesToString(packBytes(num)) | |
end | |
local function unpackBytes (str) | |
for i = #str, 1, -1 do num = num * FULL_BYTE + str:byte(i) end | |
end | |
local function unpackInt (num, bits, out) | |
local mod = 2 ^ bits | |
tinsert(out, 1, num % mod) | |
return floor(num / mod) | |
end | |
function Smash.unpackArray (str, bits) | |
local num, out = unpackBytes(str), {} | |
while num > 0 do num = unpackInt(num, bits, out) end | |
return out | |
end | |
function Smash.unpackFields (str, fields) | |
local num, out = unpackBytes(str), {} | |
for i = #fields, 1, -1 do num = unpackInt(num, fields[i], out) end | |
return out | |
end | |
local triples = { [0] = '000', '001', '010', '011', '100', '101', '110', '111' } | |
local function toByte (d) return triples[tonumber(d)] end | |
-- takes a number and returns a string with a binary representation. | |
function Smash.toBinary (n) | |
return ('%o'):format(n):gsub('.', toByte):gsub('^0*', '') | |
end | |
return Smash |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment