2012-07-20 21:57:34 +00:00
|
|
|
#!/usr/bin/env luajit
|
2012-07-20 21:57:28 +00:00
|
|
|
|
2012-07-20 21:57:40 +00:00
|
|
|
-- Usage: luajit bittest.lua <number or "x"> [-ffi] [-bchk]
|
|
|
|
|
2012-07-20 21:57:28 +00:00
|
|
|
local string = require "string"
|
2012-08-10 19:11:43 +00:00
|
|
|
local math = require "math"
|
2012-07-20 21:57:28 +00:00
|
|
|
|
2012-07-20 21:57:40 +00:00
|
|
|
local bitar = require "bitar"
|
|
|
|
|
2012-07-20 21:57:28 +00:00
|
|
|
local print = print
|
2012-07-20 21:57:40 +00:00
|
|
|
local tonumber = tonumber
|
2012-07-20 21:57:28 +00:00
|
|
|
|
2012-08-02 10:52:44 +00:00
|
|
|
local getticks
|
|
|
|
|
2012-07-20 21:57:28 +00:00
|
|
|
if (string.dump) then
|
|
|
|
-- stand-alone
|
|
|
|
local os = require "os"
|
|
|
|
function getticks()
|
|
|
|
return os.clock()*1000
|
|
|
|
end
|
|
|
|
else
|
|
|
|
-- embedded
|
2013-07-07 20:59:05 +00:00
|
|
|
getticks = gv.gethiticks
|
2012-07-20 21:57:28 +00:00
|
|
|
|
|
|
|
module(...)
|
|
|
|
end
|
|
|
|
|
2012-07-20 21:57:40 +00:00
|
|
|
-- based on example from http://bitop.luajit.org/api.html
|
|
|
|
|
|
|
|
local m = string.dump and tonumber(arg[1]) or 1e7
|
2012-08-10 19:11:43 +00:00
|
|
|
local maxidx = math.floor(m/32)
|
2012-07-20 21:57:28 +00:00
|
|
|
|
2012-07-20 21:57:40 +00:00
|
|
|
local ffiar_p, boundchk_p = false, false
|
|
|
|
|
|
|
|
if (string.dump) then
|
|
|
|
if (arg[2]=="-ffi" or arg[3]=="-ffi") then
|
|
|
|
ffiar_p = true
|
|
|
|
end
|
|
|
|
|
|
|
|
if (arg[2]=="-bchk" or arg[3]=="-bchk") then
|
|
|
|
boundchk_p = true
|
|
|
|
end
|
|
|
|
end
|
2012-07-20 21:57:28 +00:00
|
|
|
|
|
|
|
function sieve()
|
|
|
|
local count = 0
|
|
|
|
local p = {}
|
|
|
|
|
2012-07-20 21:57:40 +00:00
|
|
|
if (ffiar_p) then
|
2012-08-10 19:11:43 +00:00
|
|
|
-- stand-alone using unchecked int32_t array: on x86_64 approx. 80 ms
|
|
|
|
-- for m = 1e7 (enabling bound checking makes it be around 100 ms)
|
2012-07-20 21:57:34 +00:00
|
|
|
local ffi = require "ffi"
|
2012-08-10 19:11:43 +00:00
|
|
|
local pp = ffi.new("int32_t [?]", maxidx + 1)
|
2012-07-20 21:57:34 +00:00
|
|
|
|
|
|
|
p = pp
|
2012-07-20 21:57:28 +00:00
|
|
|
|
2012-07-20 21:57:40 +00:00
|
|
|
if (boundchk_p) then
|
|
|
|
local mt = {
|
|
|
|
__index = function(tab,idx)
|
2012-08-10 19:11:43 +00:00
|
|
|
if (idx >= 0 and idx <= maxidx) then
|
2012-07-20 21:57:40 +00:00
|
|
|
return pp[idx]
|
|
|
|
end
|
|
|
|
end,
|
|
|
|
|
|
|
|
__newindex = function(tab,idx,val)
|
2012-08-10 19:11:43 +00:00
|
|
|
if (idx >= 0 and idx <= maxidx) then
|
2012-07-20 21:57:40 +00:00
|
|
|
pp[idx] = val
|
|
|
|
end
|
|
|
|
end,
|
|
|
|
}
|
|
|
|
|
|
|
|
p = setmetatable({}, mt)
|
2012-07-20 21:57:34 +00:00
|
|
|
end
|
2012-07-20 21:57:40 +00:00
|
|
|
|
2012-08-10 19:11:43 +00:00
|
|
|
for i=0,maxidx do p[i] = -1; end
|
2012-07-20 21:57:40 +00:00
|
|
|
else
|
|
|
|
p = bitar.new(m, 1)
|
2012-07-20 21:57:34 +00:00
|
|
|
end
|
|
|
|
|
2012-07-20 21:57:40 +00:00
|
|
|
local t = getticks()
|
|
|
|
|
2012-08-10 19:11:43 +00:00
|
|
|
if (ffiar_p) then
|
|
|
|
local bit = require "bit"
|
|
|
|
|
|
|
|
for i=2,m do
|
|
|
|
if (bit.band(p[bit.rshift(i, 5)], bit.lshift(1, i)) ~= 0) then
|
|
|
|
count = count + 1
|
|
|
|
for j=i+i,m,i do
|
|
|
|
local jx = bit.rshift(j, 5)
|
|
|
|
p[jx] = bit.band(p[jx], bit.rol(0xfffffffe, j));
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
else
|
|
|
|
for i=2,m do
|
|
|
|
if (p:isset(i)) then
|
|
|
|
count = count + 1
|
|
|
|
for j=i+i,m,i do p:set0(j); end
|
|
|
|
end
|
2012-07-20 21:57:28 +00:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2012-08-10 19:11:43 +00:00
|
|
|
-- When using bitar module: x86_64: approx. 110 ms
|
2012-07-20 21:57:40 +00:00
|
|
|
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))
|
2012-08-02 10:52:44 +00:00
|
|
|
|
2012-08-10 19:11:43 +00:00
|
|
|
return p, count
|
2012-07-20 21:57:28 +00:00
|
|
|
end
|
|
|
|
|
|
|
|
if (string.dump) then
|
2012-08-10 19:11:43 +00:00
|
|
|
local function printf(fmt, ...) print(string.format(fmt, ...)) end
|
2012-08-02 10:52:44 +00:00
|
|
|
|
2012-08-10 19:11:43 +00:00
|
|
|
local p, count = sieve()
|
|
|
|
local t = getticks()
|
2012-08-02 10:52:44 +00:00
|
|
|
|
2012-08-10 19:11:43 +00:00
|
|
|
if (ffiar_p) then
|
|
|
|
return
|
2012-08-02 10:52:44 +00:00
|
|
|
end
|
|
|
|
|
2012-08-10 19:11:43 +00:00
|
|
|
-- test serialization
|
|
|
|
local ser = tostring(p)
|
|
|
|
local maxbidx_str = string.match(ser, '%(([0-9]+),')
|
|
|
|
local p2 = bitar.new(tonumber(maxbidx_str), string.match(ser, "'(.*)'"))
|
|
|
|
printf("serialization + new: %.02f ms", tostring(getticks()-t))
|
|
|
|
|
|
|
|
assert(p==p2)
|
|
|
|
if (m >= 2) then
|
|
|
|
assert(#p == count+2) -- +2 is because 0 and 1 are set even though they're not primes
|
2012-08-02 10:52:44 +00:00
|
|
|
end
|
|
|
|
|
2012-08-10 19:11:43 +00:00
|
|
|
if (not ffiar_p) then
|
|
|
|
math.randomseed(os.time())
|
|
|
|
local maxbidx = math.random(0, 65536)
|
|
|
|
local p3 = bitar.new(maxbidx, 1)
|
|
|
|
assert(#p3 == maxbidx+1) -- bits 0 to maxbidx inclusive are set
|
|
|
|
end
|
|
|
|
--[[
|
2012-08-02 10:52:44 +00:00
|
|
|
print(p)
|
|
|
|
print(p-p) -- test set difference
|
2012-08-10 19:11:43 +00:00
|
|
|
print(-p)
|
|
|
|
--]]
|
2013-01-26 17:07:53 +00:00
|
|
|
|
|
|
|
-- Set difference of self with self is the same as set intersection of self
|
|
|
|
-- with complement of self:
|
2012-08-10 19:11:43 +00:00
|
|
|
assert(p-p == p*(-p))
|
2012-07-20 21:57:28 +00:00
|
|
|
end
|