Lunatic: 'bitar': rewrite ops for colon syntax, serialization, set ops.

git-svn-id: https://svn.eduke32.com/eduke32@2862 1a8010ca-5511-0410-912e-c29ae57300e0
This commit is contained in:
helixhorned 2012-08-02 10:52:44 +00:00
parent 569f0dbe7c
commit f4c7e3f77e
5 changed files with 138 additions and 28 deletions

View file

@ -170,7 +170,8 @@ ifneq (0,$(LUNATIC))
$(OBJ)/luaJIT_BC_lunacon.$o \
$(OBJ)/luaJIT_BC_geom.$o \
$(OBJ)/luaJIT_BC_randgen.$o \
$(OBJ)/luaJIT_BC_stat.$o
$(OBJ)/luaJIT_BC_stat.$o \
$(OBJ)/luaJIT_BC_bitar.$o
# now, take care of having the necessary symbols (sector, wall, etc.) in the
# executable no matter what the debugging level

View file

@ -1,33 +1,18 @@
-- "Bit array" module based on LuaJIT's BitOp.
local ffi = require "ffi"
local bit = require "bit"
local error = error
local assert = assert
local type = type
local setmetatable=setmetatable
module(...)
-- Create new bit array.
-- Returns a table p in which entries p[0] through p[floor((size+31)/32)]
-- are set to an initialization value: 0 if 0 has been passed, -1 if 1
-- has been passed.
function new(size, initval)
if (type(size) ~= "number" or size < 0) then
error("bad argument #1 to newarray (must be a nonnegative number)", 2)
end
if (initval ~= 0 and initval ~= 1) then
error("bad argument #2 to newarray (must be either 0 or 1)", 2)
end
local p = {}
for i=0,(size+31)/32 do
p[i] = -initval
end
return p
end
-- Is bit i set in bit array ar?
function isset(ar, i)
@ -45,3 +30,109 @@ function set1(ar, j)
local jx = bit.rshift(j, 5)
ar[jx] = bit.bor(ar[jx], bit.rol(0x00000001, j))
end
local ops = { isset=isset, set0=set0, set1=set1 }
local mt
mt = {
__index=ops,
-- set ops disguised as arithmetic ones...
__mul = function(ar1, ar2) -- set intersection
assert(#ar1 == #ar2)
local p = {}
for i=0,#ar1 do
p[i] = bit.band(ar1[i], ar2[i])
end
return setmetatable(p, mt)
end,
__add = function(ar1, ar2) -- set union
assert(#ar1 == #ar2)
local p = {}
for i=0,#ar1 do
p[i] = bit.bor(ar1[i], ar2[i])
end
return setmetatable(p, mt)
end,
__sub = function(ar1, ar2) -- set difference
assert(#ar1 == #ar2)
local p = {}
for i=0,#ar1 do
p[i] = bit.band(ar1[i], bit.bnot(ar2[i]))
end
return setmetatable(p, mt)
end,
-- serialization
__tostring = function(ar)
local maxidx=#ar
local size=maxidx+1
local hdr = "bitar.new('"
local ofs = #hdr
local totalstrlen = ofs+8*size+2
local str = ffi.new("char [?]", totalstrlen)
ffi.copy(str, hdr, ofs)
for i=0,maxidx do
-- 'a' is ASCII 97
for nib=0,7 do
str[ofs + 8*i + nib] = 97 + bit.band(bit.rshift(ar[i], 4*nib), 0x0000000f)
end
end
ffi.copy(str+totalstrlen-2, "')", 2)
return ffi.string(str, totalstrlen)
end,
}
-- Create new bit array.
-- Returns a table p in which entries p[0] through p[floor((maxbidx+31)/32)]
-- are set to an initialization value: 0 if 0 has been passed, -1 if 1
-- has been passed.
-- Storage: 4 bits/bit + O(1)? (per 32 bits: 64 bits key, 64 bits value)
function new(maxbidx, initval)
local p = {}
if (type(maxbidx)=="string") then
-- string containing hex digits (a..p) given, internal
local lstr = maxbidx
local numnibs = #lstr
assert(numnibs%8 == 0)
local size = numnibs/8
local maxidx = size-1
local str = ffi.new("char [?]", numnibs)
ffi.copy(str, lstr, numnibs)
for i=0,maxidx do
p[i] = 0
for nib=0,7 do
local hexdig = str[8*i + nib]
assert(hexdig >= 97 and hexdig < 97+16)
p[i] = bit.bor(p[i], bit.lshift(hexdig-97, 4*nib))
end
end
else
if (type(maxbidx) ~= "number" or not (maxbidx >= 0)) then
error("bad argument #1 to newarray (must be a nonnegative number)", 2)
end
if (initval ~= 0 and initval ~= 1) then
error("bad argument #2 to newarray (must be either 0 or 1)", 2)
end
for i=0,maxbidx/32 do
p[i] = -initval
end
end
return setmetatable(p, mt)
end

View file

@ -4,14 +4,14 @@
local string = require "string"
local getticks
local bit = require("bit")
local bitar = require "bitar"
local print = print
local tonumber = tonumber
local getticks
if (string.dump) then
-- stand-alone
local os = require "os"
@ -27,8 +27,6 @@ end
-- based on example from http://bitop.luajit.org/api.html
local isset, set0 = bitar.isset, bitar.set0
local m = string.dump and tonumber(arg[1]) or 1e7
local ffiar_p, boundchk_p = false, false
@ -82,17 +80,35 @@ function sieve()
local t = getticks()
for i=2,m do
if (isset(p, i)) then
if (p:isset(i)) then
count = count + 1
for j=i+i,m,i do set0(p, j); end
for j=i+i,m,i do p:set0(j); end
end
end
print(string.format("[%s] Found %d primes up to %d (%.02f ms)",
ffiar_p and "ffi-ar"..(boundchk_p and ", bchk" or "") or "tab-ar",
count, m, getticks()-t))
return p
end
if (string.dump) then
sieve()
local p = sieve()
local t = getticks()
-- test serialization
local p2 = bitar.new(string.match(tostring(p), "'(.*)'"))
print(getticks()-t)
for i=0,#p do
assert(p[i]==p2[i])
end
for i = 3,#p do
p[i] = nil
end
print(p)
print(p-p) -- test set difference
end

View file

@ -548,6 +548,7 @@ local allowed_modules = {
randgen = require("randgen"),
geom = require("geom"),
stat = require("stat"),
bitar = require("bitar"),
}
local package_loaded = {}

View file

@ -43,6 +43,7 @@ luaJIT_BC_con_lang;
luaJIT_BC_geom;
luaJIT_BC_randgen;
luaJIT_BC_stat;
luaJIT_BC_bitar;
rand_jkiss_u32;
rand_jkiss_dbl;