gccause

-- DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-- THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-- (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-- This is an auxiliary tool that reads gccauses file generated by
-- gcmole.lua and prints tree of the calls that can potentially cause a GC
-- inside a given function.
--
-- Usage: lua tools/gcmole/gccause.lua <function-name-pattern>
--
assert(loadfile "gccauses")()
local P = ...
local T = {}
local function TrackCause(name, lvl)
   io.write(("  "):rep(lvl or 0), name, "\n")
   if GC[name] then
      local causes = GC[name]
      for i = 1, #causes do
	 local f = causes[i]
	 if not T[f] then
	    T[f] = true
	    TrackCause(f, (lvl or 0) + 1)
	 end
	 if f == '<GC>' then break end
      end
   end
end
for name, _ in pairs(GC) do
   if name:match(P) then
      T = {}
      TrackCause(name)
   end
end


gcmole

-- DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-- THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-- (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-- This is main driver for gcmole tool. See README for more details.
-- Usage: CLANG_BIN=clang-bin-dir lua tools/gcmole/gcmole.lua [arm|ia32|x64]
local DIR = arg[0]:match("^(.+)/[^/]+$")
local FLAGS = {
   -- Do not build gcsuspects file and reuse previously generated one.
   reuse_gcsuspects = false;
   -- Print commands to console before executing them.
   verbose = false;
   -- Perform dead variable analysis (generates many false positives).
   -- TODO add some sort of whiteliste to filter out false positives.
   dead_vars = false;
   -- When building gcsuspects whitelist certain functions as if they
   -- can be causing GC. Currently used to reduce number of false
   -- positives in dead variables analysis. See TODO for WHITELIST
   -- below.
   whitelist = true;
}
local ARGS = {}
for i = 1, #arg do
   local flag = arg[i]:match "^%-%-([%w_-]+)$"
   if flag then
      local no, real_flag = flag:match "^(no)([%w_-]+)$"
      if real_flag then flag = real_flag end
      flag = flag:gsub("%-", "_")
      if FLAGS[flag] ~= nil then
         FLAGS[flag] = (no ~= "no")
      else
         error("Unknown flag: " .. flag)
      end
   else
      table.insert(ARGS, arg[i])
   end
end
local ARCHS = ARGS[1] and { ARGS[1] } or { 'ia32', 'arm', 'x64', 'arm64' }
local io = require "io"
local os = require "os"
function log(...)
   io.stderr:write(string.format(...))
   io.stderr:write "\n"
end
-------------------------------------------------------------------------------
-- Clang invocation
local CLANG_BIN = os.getenv "CLANG_BIN"
local CLANG_PLUGINS = os.getenv "CLANG_PLUGINS"
if not CLANG_BIN or CLANG_BIN == "" then
   error "CLANG_BIN not set"
end
if not CLANG_PLUGINS or CLANG_PLUGINS == "" then
   CLANG_PLUGINS = DIR
end
local function MakeClangCommandLine(plugin, plugin_args, triple, arch_define)
   if plugin_args then
     for i = 1, #plugin_args do
        plugin_args[i] = "-Xclang -plugin-arg-" .. plugin
           .. " -Xclang " .. plugin_args[i]
     end
     plugin_args = " " .. table.concat(plugin_args, " ")
   end
   return CLANG_BIN .. "/clang++ -std=c++11 -c "
      .. " -Xclang -load -Xclang " .. CLANG_PLUGINS .. "/libgcmole.so"
      .. " -Xclang -plugin -Xclang "  .. plugin
      .. (plugin_args or "")
      .. " -Xclang -triple -Xclang " .. triple
      .. " -D" .. arch_define
      .. " -DENABLE_DEBUGGER_SUPPORT"
      .. " -DV8_I18N_SUPPORT"
      .. " -I./"
      .. " -Ithird_party/icu/source/common"
      .. " -Ithird_party/icu/source/i18n"
end
function InvokeClangPluginForEachFile(filenames, cfg, func)
   local cmd_line = MakeClangCommandLine(cfg.plugin,
                                         cfg.plugin_args,
                                         cfg.triple,
                                         cfg.arch_define)
   for _, filename in ipairs(filenames) do
      log("-- %s", filename)
      local action = cmd_line .. " " .. filename .. " 2>&1"
      if FLAGS.verbose then print('popen ', action) end
      local pipe = io.popen(action)
      func(filename, pipe:lines())
      local success = pipe:close()
      if not success then error("Failed to run: " .. action) end
   end
end
-------------------------------------------------------------------------------
-- GYP file parsing
local function ParseGYPFile()
   local gyp = ""
   local gyp_files = { "tools/gyp/v8.gyp", "test/cctest/cctest.gyp" }
   for i = 1, #gyp_files do
      local f = assert(io.open(gyp_files[i]), "failed to open GYP file")
      local t = f:read('*a')
      gyp = gyp .. t
      f:close()
   end
   local result = {}
   for condition, sources in
      gyp:gmatch "'sources': %[.-### gcmole%((.-)%) ###(.-)%]" do
      if result[condition] == nil then result[condition] = {} end
      for file in sources:gmatch "'%.%./%.%./src/([^']-%.cc)'" do
         table.insert(result[condition], "src/" .. file)
      end
      for file in sources:gmatch "'(test-[^']-%.cc)'" do
         table.insert(result[condition], "test/cctest/" .. file)
      end
   end
   return result
end
local function EvaluateCondition(cond, props)
   if cond == 'all' then return true end
   local p, v = cond:match "(%w+):(%w+)"
   assert(p and v, "failed to parse condition: " .. cond)
   assert(props[p] ~= nil, "undefined configuration property: " .. p)
   return props[p] == v
end
local function BuildFileList(sources, props)
   local list = {}
   for condition, files in pairs(sources) do
      if EvaluateCondition(condition, props) then
         for i = 1, #files do table.insert(list, files[i]) end
      end
   end
   return list
end
local sources = ParseGYPFile()
local function FilesForArch(arch)
   return BuildFileList(sources, { os = 'linux',
                                   arch = arch,
                                   mode = 'debug',
                                   simulator = ''})
end
local mtConfig = {}
mtConfig.__index = mtConfig
local function config (t) return setmetatable(t, mtConfig) end
function mtConfig:extend(t)
   local e = {}
   for k, v in pairs(self) do e[k] = v end
   for k, v in pairs(t) do e[k] = v end
   return config(e)
end
local ARCHITECTURES = {
   ia32 = config { triple = "i586-unknown-linux",
                   arch_define = "V8_TARGET_ARCH_IA32" },
   arm = config { triple = "i586-unknown-linux",
                  arch_define = "V8_TARGET_ARCH_ARM" },
   x64 = config { triple = "x86_64-unknown-linux",
                  arch_define = "V8_TARGET_ARCH_X64" },
   arm64 = config { triple = "x86_64-unknown-linux",
                    arch_define = "V8_TARGET_ARCH_ARM64" },
}
-------------------------------------------------------------------------------
-- GCSuspects Generation
local gc, gc_caused, funcs
local WHITELIST = {
   -- The following functions call CEntryStub which is always present.
   "MacroAssembler.*CallExternalReference",
   "MacroAssembler.*CallRuntime",
   "CompileCallLoadPropertyWithInterceptor",
   "CallIC.*GenerateMiss",
   -- DirectCEntryStub is a special stub used on ARM.
   -- It is pinned and always present.
   "DirectCEntryStub.*GenerateCall",
   -- TODO GCMole currently is sensitive enough to understand that certain
   --      functions only cause GC and return Failure simulataneously.
   --      Callsites of such functions are safe as long as they are properly
   --      check return value and propagate the Failure to the caller.
   --      It should be possible to extend GCMole to understand this.
   "Heap.*AllocateFunctionPrototype",
   -- Ignore all StateTag methods.
   "StateTag",
   -- Ignore printing of elements transition.
   "PrintElementsTransition"
};
local function AddCause(name, cause)
   local t = gc_caused[name]
   if not t then
      t = {}
      gc_caused[name] = t
   end
   table.insert(t, cause)
end
local function resolve(name)
   local f = funcs[name]
   if not f then
      f = {}
      funcs[name] = f
      if name:match "Collect.*Garbage" then
         gc[name] = true
         AddCause(name, "<GC>")
      end
      if FLAGS.whitelist then
         for i = 1, #WHITELIST do
            if name:match(WHITELIST[i]) then
               gc[name] = false
            end
         end
      end
   end
    return f
end
local function parse (filename, lines)
   local scope
   for funcname in lines do
      if funcname:sub(1, 1) ~= '\t' then
         resolve(funcname)
         scope = funcname
      else
         local name = funcname:sub(2)
         resolve(name)[scope] = true
      end
   end
end
local function propagate ()
   log "** Propagating GC information"
   local function mark(from, callers)
      for caller, _ in pairs(callers) do
         if gc[caller] == nil then
            gc[caller] = true
            mark(caller, funcs[caller])
         end
         AddCause(caller, from)
      end
   end
   for funcname, callers in pairs(funcs) do
      if gc[funcname] then mark(funcname, callers) end
   end
end
local function GenerateGCSuspects(arch, files, cfg)
   -- Reset the global state.
   gc, gc_caused, funcs = {}, {}, {}
   log ("** Building GC Suspects for %s", arch)
   InvokeClangPluginForEachFile (files,
                                 cfg:extend { plugin = "dump-callees" },
                                 parse)
   propagate()
   local out = assert(io.open("gcsuspects", "w"))
   for name, value in pairs(gc) do if value then out:write (name, '\n') end end
   out:close()
   local out = assert(io.open("gccauses", "w"))
   out:write "GC = {"
   for name, causes in pairs(gc_caused) do
      out:write("['", name, "'] = {")
      for i = 1, #causes do out:write ("'", causes[i], "';") end
      out:write("};\n")
   end
   out:write "}"
   out:close()
   log ("** GCSuspects generated for %s", arch)
end
--------------------------------------------------------------------------------
-- Analysis
local function CheckCorrectnessForArch(arch)
   local files = FilesForArch(arch)
   local cfg = ARCHITECTURES[arch]
   if not FLAGS.reuse_gcsuspects then
      GenerateGCSuspects(arch, files, cfg)
   end
   local processed_files = 0
   local errors_found = false
   local function SearchForErrors(filename, lines)
      processed_files = processed_files + 1
      for l in lines do
         errors_found = errors_found or
            l:match "^[^:]+:%d+:%d+:" or
            l:match "error" or
            l:match "warning"
         print(l)
      end
   end
   log("** Searching for evaluation order problems%s for %s",
       FLAGS.dead_vars and " and dead variables" or "",
       arch)
   local plugin_args
   if FLAGS.dead_vars then plugin_args = { "--dead-vars" } end
   InvokeClangPluginForEachFile(files,
                                cfg:extend { plugin = "find-problems",
                                             plugin_args = plugin_args },
                                SearchForErrors)
   log("** Done processing %d files. %s",
       processed_files,
       errors_found and "Errors found" or "No errors found")
   return errors_found
end
local function SafeCheckCorrectnessForArch(arch)
   local status, errors = pcall(CheckCorrectnessForArch, arch)
   if not status then
      print(string.format("There was an error: %s", errors))
      errors = true
   end
   return errors
end
local errors = false
for _, arch in ipairs(ARCHS) do
   if not ARCHITECTURES[arch] then
      error ("Unknown arch: " .. arch)
   end
   errors = SafeCheckCorrectnessForArch(arch, report) or errors
end
os.exit(errors and 1 or 0)


test

test.lua


-- Make lldb available in global
lldb = require('lldb')

-- Global assertion functions
function assertTrue(x)
    if not x then error('assertTrue failure') end
end

function assertFalse(x)
    if x then error('assertNotNil failure') end
end

function assertNotNil(x)
    if x == nil then error('assertNotNil failure') end
end

function assertEquals(x, y)
    if type(x) == 'table' and type(y) == 'table' then
        for k, _ in pairs(x) do
            assertEquals(x[k], y[k])
        end
    elseif type(x) ~= type(y) then
        error('assertEquals failure')
    elseif x ~= y then
        error('assertEquals failure')
    end
end

function assertStrContains(x, y)
    if not string.find(x, y, 1, true) then
        error('assertStrContains failure')
    end
end

-- Global helper functions
function read_file_non_empty_lines(f)
    local lines = {}
    while true do
        local line = f:read('*l')
        if not line then break end
        if line ~= '\n' then table.insert(lines, line) end
    end
    return lines
end

function split_lines(str)
    local lines = {}
    for line in str:gmatch("[^\r\n]+") do
        table.insert(lines, line)
    end
    return lines
end

function get_stopped_threads(process, reason)
    local threads = {}
    for i = 0, process:GetNumThreads() - 1 do
        local t = process:GetThreadAtIndex(i)
        if t:IsValid() and t:GetStopReason() == reason then
            table.insert(threads, t)
        end
    end
    return threads
end

function get_stopped_thread(process, reason)
    local threads = get_stopped_threads(process, reason)
    if #threads ~= 0 then return threads[1]
    else return nil end
end

-- Test helper

local _M = {}
local _m = {}

local _mt = { __index = _m }

function _M.create_test(name, exe, output, input)
    print('[lldb/lua] Create test ' .. name)
    exe = exe or os.getenv('TEST_EXE')
    output = output or os.getenv('TEST_OUTPUT')
    input = input or os.getenv('TEST_INPUT')
    lldb.SBDebugger.Initialize()
    local debugger = lldb.SBDebugger.Create()
    -- Ensure that debugger is created
    assertNotNil(debugger)
    assertTrue(debugger:IsValid())

    debugger:SetAsync(false)

    local lua_language = debugger:GetScriptingLanguage('lua')
    assertNotNil(lua_language)
    debugger:SetScriptLanguage(lua_language)

    local test = setmetatable({
        output = output,
        input = input,
        name = name,
        exe = exe,
        debugger = debugger
    }, _mt)
    _G[name] = test
    return test
end

function _m:create_target(exe)
    local target
    if not exe then exe = self.exe end
    target = self.debugger:CreateTarget(exe)
    -- Ensure that target is created
    assertNotNil(target)
    assertTrue(target:IsValid())
    return target
end

function _m:handle_command(command, collect)
    if collect == nil then collect = true end
    if collect then
        local ret = lldb.SBCommandReturnObject()
        local interpreter = self.debugger:GetCommandInterpreter()
        assertTrue(interpreter:IsValid())
        interpreter:HandleCommand(command, ret)
        self.debugger:GetOutputFile():Flush()
        self.debugger:GetErrorFile():Flush()
        assertTrue(ret:Succeeded())
        return ret:GetOutput()
    else
        self.debugger:HandleCommand(command)
        self.debugger:GetOutputFile():Flush()
        self.debugger:GetErrorFile():Flush()
    end
end

function _m:run()
    local tests = {}
    for k, v in pairs(self) do
        if string.sub(k, 1, 4) == 'Test' then
            table.insert(tests, k)
        end
    end
    table.sort(tests)
    for _, t in ipairs(tests) do
        print('[lldb/lua] Doing test ' .. self.name .. ' - ' .. t)
        local success = xpcall(self[t], function(e)
            print(debug.traceback())
        end, self)
        if not success then
            print('[lldb/lua] Failure in test ' .. self.name .. ' - ' .. t)
            return 1
        end
    end
    return 0
end

return _M


TestFileHandle

_T = require('lua_lldb_test').create_test('TestFileHandle')

function _T:TestLegacyFileOutScript()
    local f = io.open(self.output, 'w')
    self.debugger:SetOutputFile(f)
    self:handle_command('script print(1+1)')
    self.debugger:GetOutputFileHandle():write('FOO\n')
    self.debugger:GetOutputFileHandle():flush()
    f:close()

    f = io.open(self.output, 'r')
    assertEquals(read_file_non_empty_lines(f), {'2', 'FOO'})
    f:close()
end

function _T:TestLegacyFileOut()
    local f = io.open(self.output, 'w')
    self.debugger:SetOutputFile(f)
    self:handle_command('expression/x 3735928559', false)
    f:close()

    f = io.open(self.output, 'r')
    assertStrContains(f:read('*l'), 'deadbeef')
    f:close()
end

function _T:TestLegacyFileErr()
    local f = io.open(self.output, 'w')
    self.debugger:SetErrorFile(f)
    self:handle_command('lol', false)

    f = io.open(self.output, 'r')
    assertStrContains(f:read('*l'), 'is not a valid command')
    f:close()
end

os.exit(_T:run())


TestComprehensive

_T = require('lua_lldb_test').create_test('TestComprehensive')

function _T:Test0_CreateTarget()
    self.target = self:create_target()
    assertTrue(self.target:IsValid())
end

function _T:Test1_Breakpoint()
    self.main_bp = self.target:BreakpointCreateByName('main', 'a.out')
    self.loop_bp = self.target:BreakpointCreateByLocation('main.c', 28)
    assertTrue(self.main_bp:IsValid() and self.main_bp:GetNumLocations() == 1)
    assertTrue(self.loop_bp:IsValid() and self.loop_bp:GetNumLocations() == 1)
end

function _T:Test2_Launch()
    local error = lldb.SBError()
    self.args = { 'arg' }
    self.process = self.target:Launch(
        self.debugger:GetListener(),
        self.args,
        nil,
        nil,
        self.output,
        nil,
        nil,
        0,
        false,
        error
    )
    assertTrue(error:Success())
    assertTrue(self.process:IsValid())
end

function _T:Test3_BreakpointFindVariables()
    -- checking "argc" value
    local thread = get_stopped_thread(self.process, lldb.eStopReasonBreakpoint)
    assertNotNil(thread)
    assertTrue(thread:IsValid())
    local frame = thread:GetFrameAtIndex(0)
    assertTrue(frame:IsValid())
    local error = lldb.SBError()
    local var_argc = frame:FindVariable('argc')
    assertTrue(var_argc:IsValid())
    local var_argc_value = var_argc:GetValueAsSigned(error, 0)
    assertTrue(error:Success())
    assertEquals(var_argc_value, 2)

    -- checking "inited" value
    local continue = self.process:Continue()
    assertTrue(continue:Success())
    thread = get_stopped_thread(self.process, lldb.eStopReasonBreakpoint)
    assertNotNil(thread)
    assertTrue(thread:IsValid())
    frame = thread:GetFrameAtIndex(0)
    assertTrue(frame:IsValid())
    error = lldb.SBError()
    local var_inited = frame:FindVariable('inited')
    assertTrue(var_inited:IsValid())
    self.var_inited = var_inited
    local var_inited_value = var_inited:GetValueAsUnsigned(error, 0)
    assertTrue(error:Success())
    assertEquals(var_inited_value, 0xDEADBEEF)
end

function _T:Test3_RawData()
    local error = lldb.SBError()
    local address = self.var_inited:GetAddress()
    assertTrue(address:IsValid())
    local size = self.var_inited:GetByteSize()
    local raw_data = self.process:ReadMemory(address:GetOffset(), size, error)
    assertTrue(error:Success())
    local data_le = lldb.SBData.CreateDataFromUInt32Array(lldb.eByteOrderLittle, 1, {0xDEADBEEF})
    local data_be = lldb.SBData.CreateDataFromUInt32Array(lldb.eByteOrderBig, 1, {0xDEADBEEF})
    assertTrue(data_le:GetUnsignedInt32(error, 0) == 0xDEADBEEF or data_be:GetUnsignedInt32(error, 0) == 0xDEADBEEF)
    assertTrue(raw_data == "\xEF\xBE\xAD\xDE" or raw_data == "\xDE\xAD\xBE\xEF")
end

function _T:Test4_ProcessExit()
    self.loop_bp:SetAutoContinue(true)
    local continue = self.process:Continue()
    assertTrue(continue:Success())
    assertTrue(self.process:GetExitStatus() == 0)
end

function _T:Test5_FileOutput()
    local f = io.open(self.output, 'r')
    assertEquals(
        read_file_non_empty_lines(f),
        {
            self.exe,
            table.unpack(self.args),
            'I am a function.',
            'sum = 5050'
        }
    )
    f:close()
end

os.exit(_T:run())


TestProcessAPI

_T = require('lua_lldb_test').create_test('TestProcessAPI')

function _T:TestProcessLaunchSimple()
    local target = self:create_target()
    local args = { 'arg1', 'arg2', 'arg3' }
    local process = target:LaunchSimple(
        -- argv
        args,
        -- envp
        nil,
        -- working directory
        nil
    )
    assertTrue(process:IsValid())
    local stdout = process:GetSTDOUT(1000)
    assertEquals(split_lines(stdout), {self.exe, table.unpack(args)})
end

function _T:TestProcessLaunch()
    local target = self:create_target()
    local args = { 'arg1', 'arg2', 'arg3' }
    local error = lldb.SBError()
    local f = io.open(self.output, 'w')
    f:write()
    f:close()
    local process = target:Launch(
        -- listener
        self.debugger:GetListener(),
        -- argv
        args,
        -- envp
        nil,
        -- stdin
        nil,
        -- stdout
        self.output,
        -- stderr
        nil,
        -- working directory
        nil,
        -- launch flags
        0,
        -- stop at entry
        true,
        -- error
        error
    )
    assertTrue(error:Success())
    assertTrue(process:IsValid())
    local threads = get_stopped_threads(process, lldb.eStopReasonSignal)
    assertTrue(#threads ~= 0)
    local continue = process:Continue()
    assertTrue(continue:Success())
    local f = io.open(self.output, 'r')
    assertEquals(read_file_non_empty_lines(f), {self.exe, table.unpack(args)})
    f:close()
end

os.exit(_T:run())


TestBreakpointAPI

_T = require('lua_lldb_test').create_test('TestBreakpointAPI')

function _T:TestBreakpointIsValid()
    local target = self:create_target()
    local breakpoint = target:BreakpointCreateByName('AFunction', 'a.out')
    assertTrue(breakpoint:IsValid() and breakpoint:GetNumLocations() == 1)
    local did_delete = target:BreakpointDelete(breakpoint:GetID())
    assertTrue(did_delete)
    local del_bkpt = target:FindBreakpointByID(breakpoint:GetID())
    assertFalse(del_bkpt:IsValid())
    assertFalse(breakpoint:IsValid())
end

function _T:TestTargetDelete()
    local target = self:create_target()
    local breakpoint = target:BreakpointCreateByName('AFunction', 'a.out')
    assertTrue(breakpoint:IsValid() and breakpoint:GetNumLocations() == 1)
    local location = breakpoint:GetLocationAtIndex(0)
    assertTrue(location:IsValid())
    assertEquals(target, breakpoint:GetTarget())
    assertTrue(self.debugger:DeleteTarget(target))
    assertFalse(breakpoint:IsValid())
    assertFalse(location:IsValid())
end

function _T:TestBreakpointHitCount()
    local target = self:create_target()
    local breakpoint = target:BreakpointCreateByName('BFunction', 'a.out')
    assertTrue(breakpoint:IsValid() and breakpoint:GetNumLocations() == 1)
    breakpoint:SetAutoContinue(true)
    target:LaunchSimple(nil, nil, nil)
    assertEquals(breakpoint:GetHitCount(), 100)
end

function _T:TestBreakpointFrame()
    local target = self:create_target()
    local breakpoint = target:BreakpointCreateByName('main', 'a.out')
    assertTrue(breakpoint:IsValid() and breakpoint:GetNumLocations() == 1)
    local process = target:LaunchSimple({ 'arg1', 'arg2' }, nil, nil)
    local thread = get_stopped_thread(process, lldb.eStopReasonBreakpoint)
    assertNotNil(thread)
    assertTrue(thread:IsValid())
    local frame = thread:GetFrameAtIndex(0)
    assertTrue(frame:IsValid())
    local error = lldb.SBError()
    local var_argc = frame:FindVariable('argc')
    local var_argc_value = var_argc:GetValueAsSigned(error, 0)
    assertTrue(error:Success())
    assertEquals(var_argc_value, 3)
end

os.exit(_T:run())


testmodule

local mymodule = {}

function mymodule.foo()
  print("Hello World!")
end

return mymodule


-- A solution contains projects, and defines the available configurations
solution "p7zip"
   configurations { "Debug", "Release" }

-- includes for all projects
      includedirs {
        "../../../myWindows",
        "../../../",
        "../../../include_windows"
      }

      configuration "Debug"
         defines { "DEBUG", "_FILE_OFFSET_BITS=64", "_LARGEFILE_SOURCE", "_REENTRANT", "ENV_UNIX", "BREAK_HANDLER", "UNICODE", "_UNICODE" }
         flags { "Symbols" }

      configuration "Release"
         defines { "NDEBUG", "_FILE_OFFSET_BITS=64", "_LARGEFILE_SOURCE", "_REENTRANT", "ENV_UNIX", "BREAK_HANDLER", "UNICODE", "_UNICODE" }
         flags { "Optimize" }

---------------------------------
   project "all_c_code"
     kind "StaticLib"
      language "C"
      files {
	"../../../../C/Aes.c",
	"../../../../C/7zStream.c",
	"../../../../C/Alloc.c",
	"../../../../C/Bra.c",
	"../../../../C/Bra86.c",
	"../../../../C/BraIA64.c",
	"../../../../C/BwtSort.c",
	"../../../../C/Delta.c",
	"../../../../C/HuffEnc.c",
	"../../../../C/LzFind.c",
	"../../../../C/LzFindMt.c",
	"../../../../C/Lzma2Dec.c",
	"../../../../C/Lzma2Enc.c",
	"../../../../C/LzmaDec.c",
	"../../../../C/LzmaEnc.c",
	"../../../../C/MtCoder.c",
	"../../../../C/Ppmd7.c",
	"../../../../C/Ppmd7Dec.c",
	"../../../../C/Ppmd7Enc.c",
	"../../../../C/Ppmd8.c",
	"../../../../C/Ppmd8Dec.c",
	"../../../../C/Ppmd8Enc.c",
	"../../../../C/Sha256.c",
	"../../../../C/Sort.c",
	"../../../../C/Threads.c",
	"../../../../C/Xz.c",
	"../../../../C/XzCrc64.c",
	"../../../../C/XzDec.c",
	"../../../../C/XzEnc.c",
	"../../../../C/XzIn.c",

	"../../../../C/7zCrc.c",
	"../../../../C/7zCrcOpt.c"
      }

---------------------------------
   project "7za"
      kind "ConsoleApp"
      language "C++"
      files {
	"../../../myWindows/myGetTickCount.cpp",
	"../../../myWindows/wine_date_and_time.cpp",
	"../../../myWindows/myAddExeFlag.cpp",
	"../../../myWindows/mySplitCommandLine.cpp",

	"../../UI/Console/BenchCon.cpp",
	"../../UI/Console/ConsoleClose.cpp",
	"../../UI/Console/ExtractCallbackConsole.cpp",
	"../../UI/Console/List.cpp",
	"../../UI/Console/Main.cpp",
	"../../UI/Console/MainAr.cpp",
	"../../UI/Console/OpenCallbackConsole.cpp",
	"../../UI/Console/PercentPrinter.cpp",
	"../../UI/Console/UpdateCallbackConsole.cpp",
	"../../UI/Console/UserInputUtils.cpp",

	"../../../Common/CommandLineParser.cpp",
	"../../../Common/CRC.cpp",
	"../../../Common/IntToString.cpp",
	"../../../Common/ListFileUtils.cpp",
	"../../../Common/StdInStream.cpp",
	"../../../Common/StdOutStream.cpp",
	"../../../Common/MyString.cpp",
	"../../../Common/MyWindows.cpp",
	"../../../Common/StringConvert.cpp",
	"../../../Common/StringToInt.cpp",
	"../../../Common/UTFConvert.cpp",
	"../../../Common/MyVector.cpp",
	"../../../Common/Wildcard.cpp",

	"../../../Windows/Error.cpp",
	"../../../Windows/FileDir.cpp",
	"../../../Windows/FileFind.cpp",
	"../../../Windows/FileIO.cpp",
	"../../../Windows/FileName.cpp",
	"../../../Windows/PropVariant.cpp",
	"../../../Windows/PropVariantConversions.cpp",
	"../../../Windows/Synchronization.cpp",
	"../../../Windows/System.cpp",
	"../../../Windows/Time.cpp",

	"../../Common/CreateCoder.cpp",
	"../../Common/CWrappers.cpp",
	"../../Common/FilePathAutoRename.cpp",
	"../../Common/FileStreams.cpp",
	"../../Common/FilterCoder.cpp",
	"../../Common/InBuffer.cpp",
	"../../Common/InOutTempBuffer.cpp",
	"../../Common/LimitedStreams.cpp",
	"../../Common/LockedStream.cpp",
	"../../Common/MemBlocks.cpp",
	"../../Common/MethodId.cpp",
	"../../Common/MethodProps.cpp",
	"../../Common/OffsetStream.cpp",
	"../../Common/OutBuffer.cpp",
	"../../Common/OutMemStream.cpp",
	"../../Common/ProgressMt.cpp",
	"../../Common/ProgressUtils.cpp",
	"../../Common/StreamBinder.cpp",
	"../../Common/StreamObjects.cpp",
	"../../Common/StreamUtils.cpp",
	"../../Common/VirtThread.cpp",

	"../../UI/Common/ArchiveCommandLine.cpp",
	"../../UI/Common/ArchiveExtractCallback.cpp",
	"../../UI/Common/ArchiveOpenCallback.cpp",
	"../../UI/Common/Bench.cpp",
	"../../UI/Common/DefaultName.cpp",
	"../../UI/Common/EnumDirItems.cpp",
	"../../UI/Common/Extract.cpp",
	"../../UI/Common/ExtractingFilePath.cpp",
	"../../UI/Common/LoadCodecs.cpp",
	"../../UI/Common/OpenArchive.cpp",
	"../../UI/Common/PropIDUtils.cpp",
	"../../UI/Common/SetProperties.cpp",
	"../../UI/Common/SortUtils.cpp",
	"../../UI/Common/TempFiles.cpp",
	"../../UI/Common/Update.cpp",
	"../../UI/Common/UpdateAction.cpp",
	"../../UI/Common/UpdateCallback.cpp",
	"../../UI/Common/UpdatePair.cpp",
	"../../UI/Common/UpdateProduce.cpp",

	"../../Archive/Bz2Handler.cpp",
	"../../Archive/DeflateProps.cpp",
	"../../Archive/GzHandler.cpp",
	"../../Archive/LzmaHandler.cpp",
	"../../Archive/PpmdHandler.cpp",
	"../../Archive/SplitHandler.cpp",
	"../../Archive/XzHandler.cpp",
	"../../Archive/ZHandler.cpp",

	"../../Archive/Common/CoderMixer2.cpp",
	"../../Archive/Common/CoderMixer2MT.cpp",
	"../../Archive/Common/CrossThreadProgress.cpp",
	"../../Archive/Common/DummyOutStream.cpp",
	"../../Archive/Common/FindSignature.cpp",
	"../../Archive/Common/HandlerOut.cpp",
	"../../Archive/Common/InStreamWithCRC.cpp",
	"../../Archive/Common/ItemNameUtils.cpp",
	"../../Archive/Common/MultiStream.cpp",
	"../../Archive/Common/OutStreamWithCRC.cpp",
	"../../Archive/Common/ParseProperties.cpp",

	"../../Archive/7z/7zCompressionMode.cpp",
	"../../Archive/7z/7zDecode.cpp",
	"../../Archive/7z/7zEncode.cpp",
	"../../Archive/7z/7zExtract.cpp",
	"../../Archive/7z/7zFolderInStream.cpp",
	"../../Archive/7z/7zFolderOutStream.cpp",
	"../../Archive/7z/7zHandler.cpp",
	"../../Archive/7z/7zHandlerOut.cpp",
	"../../Archive/7z/7zHeader.cpp",
	"../../Archive/7z/7zIn.cpp",
	"../../Archive/7z/7zOut.cpp",
	"../../Archive/7z/7zProperties.cpp",
	"../../Archive/7z/7zSpecStream.cpp",
	"../../Archive/7z/7zUpdate.cpp",
	"../../Archive/7z/7zRegister.cpp",

	"../../Archive/Cab/CabBlockInStream.cpp",
	"../../Archive/Cab/CabHandler.cpp",
	"../../Archive/Cab/CabHeader.cpp",
	"../../Archive/Cab/CabIn.cpp",
	"../../Archive/Cab/CabRegister.cpp",

	"../../Archive/Tar/TarHandler.cpp",
	"../../Archive/Tar/TarHandlerOut.cpp",
	"../../Archive/Tar/TarHeader.cpp",
	"../../Archive/Tar/TarIn.cpp",
	"../../Archive/Tar/TarOut.cpp",
	"../../Archive/Tar/TarRegister.cpp",
	"../../Archive/Tar/TarUpdate.cpp",

	"../../Archive/Zip/ZipAddCommon.cpp",
	"../../Archive/Zip/ZipHandler.cpp",
	"../../Archive/Zip/ZipHandlerOut.cpp",
	"../../Archive/Zip/ZipHeader.cpp",
	"../../Archive/Zip/ZipIn.cpp",
	"../../Archive/Zip/ZipItem.cpp",
	"../../Archive/Zip/ZipOut.cpp",
	"../../Archive/Zip/ZipUpdate.cpp",
	"../../Archive/Zip/ZipRegister.cpp",

	"../../Compress/Bcj2Coder.cpp",
	"../../Compress/Bcj2Register.cpp",
	"../../Compress/BcjCoder.cpp",
	"../../Compress/BcjRegister.cpp",
	"../../Compress/BitlDecoder.cpp",
	"../../Compress/BranchCoder.cpp",
	"../../Compress/BranchMisc.cpp",
	"../../Compress/BranchRegister.cpp",
	"../../Compress/ByteSwap.cpp",
	"../../Compress/BZip2Crc.cpp",
	"../../Compress/BZip2Decoder.cpp",
	"../../Compress/BZip2Encoder.cpp",
	"../../Compress/BZip2Register.cpp",
	"../../Compress/CopyCoder.cpp",
	"../../Compress/CopyRegister.cpp",
	"../../Compress/Deflate64Register.cpp",
	"../../Compress/DeflateDecoder.cpp",
	"../../Compress/DeflateEncoder.cpp",
	"../../Compress/DeflateRegister.cpp",
	"../../Compress/DeltaFilter.cpp",
	"../../Compress/ImplodeDecoder.cpp",
	"../../Compress/ImplodeHuffmanDecoder.cpp",
	"../../Compress/Lzma2Decoder.cpp",
	"../../Compress/Lzma2Encoder.cpp",
	"../../Compress/Lzma2Register.cpp",
	"../../Compress/LzmaDecoder.cpp",
	"../../Compress/LzmaEncoder.cpp",
	"../../Compress/LzmaRegister.cpp",
	"../../Compress/LzOutWindow.cpp",
	"../../Compress/Lzx86Converter.cpp",
	"../../Compress/LzxDecoder.cpp",
	"../../Compress/PpmdDecoder.cpp",
	"../../Compress/PpmdEncoder.cpp",
	"../../Compress/PpmdRegister.cpp",
	"../../Compress/PpmdZip.cpp",
	"../../Compress/QuantumDecoder.cpp",
	"../../Compress/ShrinkDecoder.cpp",
	"../../Compress/ZDecoder.cpp",

	"../../Crypto/7zAes.cpp",
	"../../Crypto/7zAesRegister.cpp",
	"../../Crypto/HmacSha1.cpp",
	"../../Crypto/MyAes.cpp",
	"../../Crypto/Pbkdf2HmacSha1.cpp",
	"../../Crypto/RandGen.cpp",
	"../../Crypto/Sha1.cpp",
	"../../Crypto/WzAes.cpp",
	"../../Crypto/ZipCrypto.cpp",
	"../../Crypto/ZipStrong.cpp"

      }

      configuration "linux"
	links       {  "all_c_code", "pthread" }


alltests

dofile("run_bench_tests.lua");
-- must be run last, because one of the tests sets a debug tracer
-- we don't want that active during the benchmark
dofile("tests.lua");


-- run benchmark scripts.
--
local write = io.write
local use_profiler = false
local profile_mode = 2
local profile_all = true
local prof_start = function(file,mode) end
local prof_stop = function() end
local output_fd = io.stdout
local old_print = print
local script_print = old_print
--local run_type = (arg and arg[1]) or "bench"
local run_type="test"

local function redirect_print(...)
	for i,val in ipairs(...) do
		write(val)
		write("\t")
	end
	write("\n")
end

if use_profiler then
	require("profiler")
	if profile_all then
		profiler.start("Stats.log", profile_mode)
	else
		prof_start = profiler.start
		prof_stop = profiler.stop
	end
end

local function run_bench(filename, input, ...)
	local old_arg=arg
	local old_input=io.input()
	local title=nil
	local sclock,eclock
	for i,val in ipairs(...) do
		if run_type ~= "bench" then
			title=string.format("run script: '%s', with arg='%s'\n", filename, val)
			write(title)
		end
		io.flush()
		sclock=os.clock()
		-- load script.
		local func=loadfile(filename)
		-- create arg environment variable for script.
		local arg={}
		arg[0]=filename
		arg[1]=val
		local env=getfenv(func)
		env['arg'] = arg
		env['print'] = script_print
		-- redirect stdin
		io.input(input)
		io.flush()
		-- redirect stdout
		if output_fd ~= io.stdout then
			io.output(output_fd)
			if title then
				write(title)
			end
		end
		-- start script.
		prof_start(filename .. '_arg_' .. val .. "_profile.log", profile_mode)
		local res= {pcall(func,{val})}
		prof_stop()
--		LLVM local begin
--		eclock=os.clock()
		eclock=sclock
		print(filename);
--		LLVM local end
		io.output(io.stdout)
		-- script finished.
		io.flush()
		print("results = ", unpack(res))
		local idx=filename:find(".lua")
		write(string.format("%s:%0.2f\n", filename:sub(7, idx-1), eclock - sclock))
		collectgarbage("collect")
		io.flush()
		io.input(old_input)
	end
	arg=old_arg
end

local function print_script_list(list)
	for i,v in ipairs(list) do
		if v then
			local script,input,params = unpack(v)
			local idx=script:find(".lua")
			if script:find("bench/") == 1 then
				script = script:sub(7,idx-1)
				if input == io.stdin then input = "" end
				params = table.concat(params,",")
				write(script)
				write(":")
				write(input)
				write(":")
				write(params)
				write("\n")
			end
		end
	end
end

local scripts_full={
 {"tests/echo.lua", io.stdin, {"test","23425","908798","test"}},--only in full
 {"bench/ackermann.lua", io.stdin, {9,10,11}},
 {"bench/ary.lua", io.stdin, {3000,5000,7000,9000}},
 {"bench/binarytrees.lua", io.stdin, {12,14,16}},
 {"bench/chameneos.lua", io.stdin, {10000,100000,1000000}},
 {"bench/except.lua", io.stdin, {100000,150000,200000,250000}},
 {"bench/fannkuch.lua", io.stdin, {9,10,11}},
 {"bench/fasta.lua", io.stdin, {25000,250000,2500000}},--only in full
 {"bench/fibo.lua", io.stdin, {12,24,32}},
 {"bench/harmonic.lua", io.stdin, {6000000,8000000,10000000}},
 {"bench/hash.lua", io.stdin, {40000,60000,80000,100000}},
 {"bench/hash2.lua", io.stdin, {50,100,150,200}},
 {"bench/heapsort.lua", io.stdin, {20000,40000,60000,80000,100000}},
 {"bench/hello.lua", io.stdin, {1,50,100,150,200}},
 {"bench/knucleotide.lua", "input/knucleotide-input20000.txt", {1}},
 {"bench/lists.lua", io.stdin, {4,8,12,16,18}},
 {"bench/mandelbrot.lua", io.stdin, {200,400,600}},--only in full
 {"bench/matrix.lua", io.stdin, {10,200,400,600}},
-- {"bench/message.lua", io.stdin, {1000,2000,3000}},
 {"bench/meteor.lua", io.stdin, {0}},
 {"bench/methcall.lua", io.stdin, {100000,400000,700000,1000000}},
 {"bench/moments.lua", "input/moments-input400000.txt", {1}},
 {"bench/nbody.lua", io.stdin, {200000,2000000,20000000}},
 {"bench/nestedloop.lua", io.stdin, {8,12,16,18}},
 {"bench/nsieve.lua", io.stdin, {7,8,9}},
 {"bench/nsievebits.lua", io.stdin, {7,8,9}},
 {"bench/objinst.lua", io.stdin, {400000,700000,1000000,1500000}},
 {"bench/partialsums.lua", io.stdin, {25000,250000,2500000}},
 {"bench/pidigits.lua", io.stdin, {600,800,1000}},
 {"bench/process.lua", io.stdin, {1000,2000,3000}},
 {"bench/prodcons.lua", io.stdin, {30000,70000,100000,150000}},
 {"bench/random.lua", io.stdin, {9000,300000,600000,900000}},
 {"bench/recursive.lua", io.stdin, {3,7,11}},
 {"bench/regexdna.lua", "input/regexdna-input100000.txt", {1}},
 {"bench/regexmatch.lua", "input/regexmatch-input2000.txt", {1}},
 {"bench/revcomp.lua", "input/revcomp-input250000.txt", {1}},
 {"bench/reversefile.lua", "input/reversefile-input50.txt", {1}},
 {"bench/sieve.lua", io.stdin, {300,600,900,1200}},
 {"bench/spectralnorm.lua", io.stdin, {500,1500,2500}},
 {"bench/spellcheck.lua", "input/spellcheck-input30.txt", {1}},
 {"bench/strcat.lua", io.stdin, {10000,20000,30000,40000}},
 {"bench/sumcol.lua", "input/sumcol-input.txt", {1}},
 {"bench/takfp.lua", io.stdin, {8,9,10}},
-- {"bench/tcprequest.lua", io.stdin, {120,160,200}},
 {"bench/wc.lua", "input/wc-input3000.txt", {1}},
 {"bench/wordfreq.lua", "input/wordfreq-input20.txt", {1}}
}

local scripts_medium={
 {"bench/ackermann.lua", io.stdin, {9,10,11}},
 {"bench/ary.lua", io.stdin, {7000,8000,9000,10000}},
 {"bench/binarytrees.lua", io.stdin, {12,14,15}},
 {"bench/chameneos.lua", io.stdin, {1000000,2000000,3000000}},
 {"bench/except.lua", io.stdin, {500000,1000000,2000000,3000000}},
 {"bench/fannkuch.lua", io.stdin, {9,10,11}},
 {"bench/fibo.lua", io.stdin, {32,34,36}},
 {"bench/harmonic.lua", io.stdin, {20000000,30000000,50000000}},
 {"bench/hash.lua", io.stdin, {100000,200000,300000,400000}},
 {"bench/hash2.lua", io.stdin, {300,400,500,600}},
 {"bench/heapsort.lua", io.stdin, {200000,400000,600000,800000,1000000}},
 {"bench/hello.lua", io.stdin, {1,50,100,150,200}},
 {"bench/knucleotide.lua", "input/knucleotide-input20000.txt", {1}},
 {"bench/lists.lua", io.stdin, {20,30,40,50,60}},
 {"bench/matrix.lua", io.stdin, {200,400,600,700}},
 {"bench/meteor.lua", io.stdin, {0}},
 {"bench/methcall.lua", io.stdin, {700000,1000000,1500000,3000000}},
 {"bench/moments.lua", "input/moments-input400000.txt", {1}},
 {"bench/nbody.lua", io.stdin, {60000,200000,500000}},
 {"bench/nestedloop.lua", io.stdin, {17,18,19,20}},
 {"bench/nsieve.lua", io.stdin, {7,8,9}},
 {"bench/nsievebits.lua", io.stdin, {7,8,9}},
 {"bench/objinst.lua", io.stdin, {400000,700000,1000000,1500000}},
 {"bench/partialsums.lua", io.stdin, {250000,2500000,5000000}},
 {"bench/pidigits.lua", io.stdin, {600,800,1000}},
 {"bench/process.lua", io.stdin, {10000,20000,30000}},
 {"bench/prodcons.lua", io.stdin, {700000,800000,1000000,1500000}},
 {"bench/random.lua", io.stdin, {3000000,5000000,7000000,9000000}},
 {"bench/recursive.lua", io.stdin, {5,7,9}},
 {"bench/regexdna.lua", "input/regexdna-input100000.txt", {1}},
 {"bench/regexmatch.lua", "input/regexmatch-input2000.txt", {1}},
 {"bench/revcomp.lua", "input/revcomp-input250000.txt", {1}},
 {"bench/reversefile.lua", "input/reversefile-input50.txt", {1}},
 {"bench/sieve.lua", io.stdin, {300,600,900,1200}},
 {"bench/spectralnorm.lua", io.stdin, {500,1000}},
 {"bench/spellcheck.lua", "input/spellcheck-input30.txt", {1}},
 {"bench/strcat.lua", io.stdin, {1500000,4000000,7000000}},
 {"bench/sumcol.lua", "input/sumcol-input2000.txt", {1}},
 {"bench/takfp.lua", io.stdin, {8,9,10}},
 {"bench/wc.lua", "input/wc-input3000.txt", {1}},
 {"bench/wordfreq.lua", "input/wordfreq-input20.txt", {1}}
}

local scripts_short={
 {"bench/ackermann.lua", io.stdin, {9}},
 {"bench/ary.lua", io.stdin, {7000}},
 {"bench/binarytrees.lua", io.stdin, {12}},
 {"bench/chameneos.lua", io.stdin, {350000}},
 {"bench/except.lua", io.stdin, {500000}},
 {"bench/fannkuch.lua", io.stdin, {9}},
 {"bench/fibo.lua", io.stdin, {31}},
 {"bench/harmonic.lua", io.stdin, {20000000}},
 {"bench/hash.lua", io.stdin, {200000}},
 {"bench/hash2.lua", io.stdin, {250}},
 {"bench/heapsort.lua", io.stdin, {150000}},
 {"bench/hello.lua", io.stdin, {1}},
 {"bench/knucleotide.lua", "input/knucleotide-input20000.txt", {1}},
 {"bench/lists.lua", io.stdin, {35}},
 {"bench/matrix.lua", io.stdin, {250}},
 {"bench/meteor.lua", io.stdin, {0}},
 {"bench/methcall.lua", io.stdin, {1000000}},
 {"bench/moments.lua", "input/moments-input400000.txt", {1}},
 {"bench/nbody.lua", io.stdin, {70000}},
 {"bench/nestedloop.lua", io.stdin, {17}},
 {"bench/nsieve.lua", io.stdin, {7}},
 {"bench/nsievebits.lua", io.stdin, {6}},
 {"bench/objinst.lua", io.stdin, {400000}},
 {"bench/partialsums.lua", io.stdin, {800000}},
 {"bench/pidigits.lua", io.stdin, {150}},
 {"bench/process.lua", io.stdin, {60000}},
 {"bench/prodcons.lua", io.stdin, {1000000}},
 {"bench/random.lua", io.stdin, {3000000}},
 {"bench/recursive.lua", io.stdin, {5}},
 {"bench/regexdna.lua", "input/regexdna-input100000.txt", {1}},
 {"bench/regexmatch.lua", "input/regexmatch-input2000.txt", {1}},
 {"bench/revcomp.lua", "input/revcomp-input250000.txt", {1}},
 {"bench/reversefile.lua", "input/reversefile-input50.txt", {1}},
 {"bench/sieve.lua", io.stdin, {400}},
 {"bench/spectralnorm.lua", io.stdin, {300}},
 {"bench/spellcheck.lua", "input/spellcheck-input30.txt", {1}},
 {"bench/strcat.lua", io.stdin, {1500000}},
 {"bench/sumcol.lua", "input/sumcol-input2000.txt", {1}},
 {"bench/takfp.lua", io.stdin, {8}},
 {"bench/wc.lua", "input/wc-input3000.txt", {1}},
 {"bench/wordfreq.lua", "input/wordfreq-input20.txt", {1}}
}

-- local scripts = scripts_full
--local scripts = scripts_medium
local scripts = scripts_short
local sclock,eclock

if run_type == "bench" then
	output_fd = io.open("/dev/null","a")
	script_print = function(...) end
elseif run_type == "test" then
	if arg[2] then
		output_fd = io.open(arg[2],"a")
		script_print = redirect_print
	end
end

if run_type ~= "script_lists" then
	sclock=os.clock()
	for i,v in ipairs(scripts) do
		if v then
			run_bench(unpack(v))
		end
	end

	if profile_all and use_profiler then
		profiler.stop()
	end
	--LLVM local begin
	--eclock=os.clock()
	eclock=sclock
	--LLVM local end
	write(string.format("Total bench time = %f\n", eclock - sclock))

	io.close(output_fd)
else
	write("#!/bin/sh\n\n")
	write('SCRIPT_FULL_LIST="\n')
	print_script_list(scripts_full)
	write('"\n\n')
	write('SCRIPT_MEDIUM_LIST="\n')
	print_script_list(scripts_medium)
	write('"\n\n')
	write('SCRIPT_SHORT_LIST="\n')
	print_script_list(scripts_short)
	write('"\n\n')
end


tests

dofile("test/bisect.lua");
dofile("test/cf.lua");
dofile("test/echo.lua");
-- dofile("test/env.lua");
dofile("test/factorial.lua");
dofile("test/fibfor.lua");
dofile("test/fib.lua");
dofile("test/globals.lua");
dofile("test/hello.lua");
dofile("test/life.lua");
dofile("test/sieve.lua");
dofile("test/sort.lua");
dofile("test/table.lua");
dofile("test/trace-calls.lua");
dofile("test/trace-globals.lua");
dofile("test/xd.lua");


fannkuch

-- The Computer Language Shootout
-- http://shootout.alioth.debian.org/
-- contributed by Mike Pall

local function fannkuch(n)
  local p, q, s, odd, check, maxflips = {}, {}, {}, true, 0, 0
  for i=1,n do p[i] = i; s[i] = i end
  repeat
    -- Print max. 30 permutations.
    if check < 30 then
      if not p[n] then return maxflips end	-- Catch n = 0, 1, 2.
      for i=1,n do io.write(p[i]) end; io.write("\n")
      check = check + 1
    end
    -- Copy and flip.
    local q1 = p[1]				-- Cache 1st element.
    if p[n] ~= n and q1 ~= 1 then		-- Avoid useless work.
      for i=2,n do q[i] = p[i] end		-- Work on a copy.
      for flips=1,1000000 do			-- Flip ...
	local j = q1 - 1
	for i=2,q1/2 do q[i], q[j] = q[j], q[i]; j = j - 1 end
	local qq = q[q1]
	if qq == 1 then				-- ... until 1st element is 1.
	  if flips > maxflips then maxflips = flips end -- New maximum?
	  break
	end
	q[q1] = q1
	q1 = qq
      end
    end
    -- Permute.
    if odd then
      p[2], p[1] = p[1], p[2]; odd = false	-- Rotate 1<-2.
    else
      p[2], p[3] = p[3], p[2]; odd = true	-- Rotate 1<-2 and 1<-2<-3.
      for i=3,n do
	local sx = s[i]
	if sx ~= 1 then sx = sx - 1; s[i] = sx; break end
	if i == n then return maxflips end	-- Out of permutations.
	s[i] = i
	-- Rotate 1<-...<-i+1.
	local t = p[1]; for j=1,i do p[j] = p[j+1] end; p[i+1] = t
      end
    end
  until false
end

local n = tonumber(arg and arg[1]) or 1
io.write("Pfannkuchen(", n, ") = ", fannkuch(n), "\n")


spellcheck

-- $Id: spellcheck.lua,v 1.2 2004-05-25 02:26:33 bfulgham Exp $
-- http://www.bagley.org/~doug/shootout/
-- based on code from Roberto Ierusalimschy

local dict_file = "input/spellcheck-dict.txt"

assert(io.open(dict_file))
local dict = {}
for line in io.lines(dict_file) do
  dict[line] = true
end

for word in io.lines() do
  if not dict[word] then print(word) end
end


process

-- The Great Computer Language Shootout
-- http://shootout.alioth.debian.org/
--
-- contributed by Isaac Gouy

local function link(n)
   local message, next = 0

   if n-1 > 0 then
      next = coroutine.create(link)
      _,message = coroutine.resume(next,n-1)
   end
   coroutine.yield(message + 1)
end

local n = tonumber(arg[1]) or 1000
local message = 0
local chain = coroutine.create(link)

_,message = coroutine.resume(chain,n)
io.write(message, "\n")


fasta

-- The Computer Language Shootout
-- http://shootout.alioth.debian.org/
-- contributed by Mike Pall

local IM = 139968
local IA = 3877
local IC = 29573
local Last = 42

local sub, write = string.sub, io.write

local function random(max)
  local y = (Last * IA + IC) % IM
  Last = y
  return (max * y) / IM
end

local function make_repeat_fasta(id, desc, s, n)
  write(">", id, " ", desc, "\n")
  local p, sn, s2 = 1, #s, s..s
  for i=60,n,60 do
    write(sub(s2, p, p + 59), "\n")
    p = p + 60; if p > sn then p = p - sn end
  end
  local tail = n % 60
  if tail > 0 then write(sub(s2, p, p + tail-1), "\n") end
end

local make_random_fasta = loadstring([=[local write = ...
return function(id, desc, f, n)
  write(">", id, " ", desc, "\n")
  for i=60,n,60 do write(]=]..string.rep("f(),",60)..[=["\n") end
  local tail = n % 60
  if tail > 0 then for j=1,tail do write(f()) end; write("\n") end
end]=])(write)

local function bisect(c, p, lo, hi)
  local n = hi - lo
  if n == 0 then return "return '"..c[hi].."'\n" end
  local mid = math.floor(n / 2)
  return "if r < "..p[lo+mid].." then\n"..bisect(c, p, lo, lo+mid)..
         "else\n"..bisect(c, p, lo+mid+1, hi).."end\n"
end

local function make_bisect(tab)
  local c, p, sum = {}, {}, 0
  for i,row in ipairs(tab) do
    c[i] = row[1]
    sum = sum + row[2]
    p[i] = sum
  end
  return loadstring("local rr = ...\nreturn function()\nlocal r = rr(1)\n"..
    bisect(c, p, 1, #tab).."end\n")(random)
end

local alu =
  "GGCCGGGCGCGGTGGCTCACGCCTGTAATCCCAGCACTTTGG"..
  "GAGGCCGAGGCGGGCGGATCACCTGAGGTCAGGAGTTCGAGA"..
  "CCAGCCTGGCCAACATGGTGAAACCCCGTCTCTACTAAAAAT"..
  "ACAAAAATTAGCCGGGCGTGGTGGCGCGCGCCTGTAATCCCA"..
  "GCTACTCGGGAGGCTGAGGCAGGAGAATCGCTTGAACCCGGG"..
  "AGGCGGAGGTTGCAGTGAGCCGAGATCGCGCCACTGCACTCC"..
  "AGCCTGGGCGACAGAGCGAGACTCCGTCTCAAAAA"

local iub = make_bisect{
  { "a", 0.27 },
  { "c", 0.12 },
  { "g", 0.12 },
  { "t", 0.27 },
  { "B", 0.02 },
  { "D", 0.02 },
  { "H", 0.02 },
  { "K", 0.02 },
  { "M", 0.02 },
  { "N", 0.02 },
  { "R", 0.02 },
  { "S", 0.02 },
  { "V", 0.02 },
  { "W", 0.02 },
  { "Y", 0.02 },
}

local homosapiens = make_bisect{
  { "a", 0.3029549426680 },
  { "c", 0.1979883004921 },
  { "g", 0.1975473066391 },
  { "t", 0.3015094502008 },
}

local N = tonumber(arg and arg[1]) or 1000
make_repeat_fasta('ONE', 'Homo sapiens alu', alu, N*2)
make_random_fasta('TWO', 'IUB ambiguity codes', iub, N*3)
make_random_fasta('THREE', 'Homo sapiens frequency', homosapiens, N*5)


tcprequest

local socket = require "socket"
local posix = require "posix"

local M, reply_size, request_size = 100, 4096, 64
local N = tonumber(arg and arg[1]) or 1

local function client(sk)
  local repsize = reply_size
  local request = string.rep(" ", request_size)
  local replies = 0
  for i=1,N*M do
    sk:send(request)
    sk:receive(repsize)
    replies = replies + 1
  end
  io.write("replies: ", replies, "\tbytes: ", sk:getstats(), "\n")
  io.flush()
  sk:close()
end

local function server(sk)
  local reqsize = request_size
  local reply = string.rep(" ", reply_size)
  for i=1,N*M do
    sk:receive(reqsize)
    sk:send(reply)
  end
  sk:close()
end

local ls = socket.bind("127.0.0.1", 0)
if posix.fork() == 0 then		-- Child is client
  client(socket.connect(ls:getsockname()))
  os.exit()
else					-- Parent is server
  server(ls:accept())
  ls:close()
  posix.wait()
end


matrix

-- $Id: matrix.lua,v 1.2 2004-07-04 07:29:51 bfulgham Exp $
-- http://shootout.alioth.debian.org/
-- with help from Roberto Ierusalimschy

local n = tonumber((arg and arg[1]) or 1)

local size = 30

function mkmatrix(rows, cols)
    local count = 1
    local mx = {}
    for i=1,rows do
	local row = {}
	for j=1,cols do
	    row[j] = count
	    count = count + 1
	end
	mx[i] = row
    end
    return(mx)
end

function mmult(rows, cols, m1, m2)
    local m3 = {}
    for i=1,rows do
        local m3i = {}
        m3[i] = m3i
        local m1i = m1[i]              -- "cache" m1[i]
        for j=1,cols do
            local rowj = 0
            for k=1,cols do
                rowj = rowj + m1i[k] * m2[k][j]
            end
            m3i[j] = rowj
        end
    end
    return(m3)
end

local m1 = mkmatrix(size, size)
local m2 = mkmatrix(size, size)
for i=1,n do
    mm = mmult(size, size, m1, m2)
end
io.write(string.format("%d %d %d %d\n", mm[1][1], mm[3][4], mm[4][3], mm[5][5]))


-- The Computer Language Shootout
-- http://shootout.alioth.debian.org/
-- contributed by Mike Pall
-- Generate a decision tree based solver for the meteor puzzle.
local function generatesolver(countinit)
  local pairs, ipairs, format = pairs, ipairs, string.format
  local byte, min, sort = string.byte, math.min, table.sort
  -- Cached position to distance lookup.
  local dist = setmetatable({}, { __index = function(t, xy)
    local x = xy%10; local y = (xy-x)/10
    if (x+y)%2 == 1 then y = y + 1; x = 10 - x end
    local d = xy + 256*x*x + 1024*y*y; t[xy] = d; return d
  end})
  -- Lookup table to validate a cell and to find its successor.
  local ok = {}
  for i=0,150 do ok[i] = false end
  for i=99,0,-1 do
    local x = i%10
    if ((i-x)/10+x)%2 == 0 then
      ok[i] = i + (ok[i+1] and 1 or (ok[i+2] and 2 or 3))
    end
  end
  -- Temporary board state for the island checks.
  local islands, slide = {}, {20,22,24,26,28,31,33,35,37,39}
  local bbc, bb = 0, {}
  for i=0,19 do bb[i] = false; bb[i+80] = false end
  for i=20,79 do bb[i] = ok[i] end
  -- Recursive flood fill algorithm.
  local function fill(bb, p)
    bbc = bbc + 1
    local n = p+2; if bb[n] then bb[n] = false; fill(bb, n) end
    n = p-2; if bb[n] then bb[n] = false; fill(bb, n) end
    n = p-9; if bb[n] then bb[n] = false; fill(bb, n) end
    n = p-11; if bb[n] then bb[n] = false; fill(bb, n) end
    n = p+9; if bb[n] then bb[n] = false; fill(bb, n) end
    n = p+11; if bb[n] then bb[n] = false; fill(bb, n) end
  end
  -- Generate pruned, sliding decision trees.
  local dtrees = {{}, {}, {}, {}, {}, {}, {}, {}, {}, {}}
  local rot = { nil, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {} }
  for k=0,9 do
    -- Generate 10 initial pieces from line noise. :-)
    rot[1] = t
    for i,xy in ipairs(t) do
      local x = xy%10; local y = (xy-x-60)/10
      -- Add 11 more variations by rotating and flipping.
      for j=2,12 do
	if j == 7 then y = -y else x,y = (x+3*y)/2, (y-x)/2 end
	rot[j][i] = x+10*y
      end
    end
    for r,v in ipairs(rot) do
      -- Exploit symmetry and leave out half of the orientations of one piece.
      -- The selected piece gives the best reduction of the solution space.
      if k ~= 3 or r%2 == 0 then
	-- Normalize to origin, add distance, sort by distance from origin.
	local m = min(v[1], v[2], v[3], v[4], v[5])
	for i=1,5 do v[i] = dist[v[i]-m] end
	sort(v)
	local v2, v3, v4, v5 = v[2]%256, v[3]%256, v[4]%256, v[5]%256
	-- Slide the piece across 2 rows, prune the tree, check for islands.
	for j,p in ipairs(slide) do
	  bb[p] = false
	  if ok[p+v2] and ok[p+v3] and ok[p+v4] and ok[p+v5] then -- Prune.
	    for i=p+1,79 do bb[i] = ok[i] end -- Clear remaining board.
	    bb[p+v2] = false; bb[p+v3] = false -- Add piece.
	    bb[p+v4] = false; bb[p+v5] = false
	    bbc = j -- Flood fill and count the filled positions.
	    if bb[71] then bb[71] = false; fill(bb, 71) end -- Lower left.
	    if bb[79] then bb[79] = false; fill(bb, 79) end -- Lower right.
	    local di = 0
	    if bbc < 22 then bbc = 26
	    elseif bbc < 26 then -- Island found, locate it, fill from above.
	      for i=p+2,79 do if bb[i] then di = i-p; break end end
	      for i=p-9,p-1 do if ok[i] then fill(bb, i) bbc = bbc - 1 end end
	    end
	    if bbc == 26 then -- Prune boards with static islands.
	      local tb = dtrees[j] -- Build decision tree in distance order.
	      local ta = tb[v2]; if not ta then ta = {}; tb[v2] = ta end
	      tb = ta[v3]; if not tb then tb = {}; ta[v3] = tb end
	      ta = tb[v4]; if not ta then ta = {}; tb[v4] = ta; islands[ta] = di
	      elseif islands[ta] ~= di then islands[ta] = 0 end
	      ta[v5] = di*10+k -- Leaves hold island check and piece number.
	    end
	  end
	end
      end
    end
  end
  local s = "local u0,u1,u2,u3,u4,u5,u6,u7,u8,u9" -- Piece use flags.
  for p=0,99 do if ok[p] then s = s..",b"..p end end -- Board cells.
  s = s.."\n"..[[
local countinit = ...
local count = countinit
local bmin, bmax, pcs = 9, 0, {}
local smin, smax
local write, reverse = io.write, string.reverse
-- Print min/max boards.
local function printboard(s)
  local flip = true
  for x in string.gmatch(string.gsub(s, ".", "%1 "), "..........") do
    write(x, flip and "\n " or "\n")
    flip = not flip
  end
  write("\n")
end
-- Print result.
local function printresult()
  write(countinit-count, " solutions found\n\n")
  printboard(smin)
  printboard(smax)
end
-- Generate piece lookup array from the order of use.
local function genp()
  local p = pcs
  p[u0] = "0" p[u1] = "1" p[u2] = "2" p[u3] = "3" p[u4] = "4"
  p[u5] = "5" p[u6] = "6" p[u7] = "7" p[u8] = "8" p[u9] = "9"
  return p
end
-- Goal function.
local function f91(k)
  if k ~= 10 then return end
  count = count - 2 -- Need to count the symmetric solution, too.
  repeat
    -- Quick precheck before constructing the string.
    local b0, b99 = b0, b99
    if b0 <= bmin then bmin = b0 elseif b0 >= bmax then bmax = b0
    elseif b99 <= bmin then bmin = b99 elseif b99 >= bmax then bmax = b99
    else break end
    -- Translate the filled board to a string.
    local p = genp()
    local s = p[b0] ]]
  for p=2,99 do if ok[p] then s = s.."..p[b"..p.."]" end end
  s = s..[[
    -- Remember min/max boards, dito for the symmetric board.
    if not smin then smin = s; smax = s
    elseif s < smin then smin = s elseif s > smax then smax = s end
    s = reverse(s)
    if s < smin then smin = s elseif s > smax then smax = s end
  until true
  if count <= 0 then error() end -- Early abort if max count given.
end
local f93 = f91
]]
  -- Recursively convert the decision tree to Lua code.
  local function codetree(tree, d, p, pn)
    local found, s = false, ""
    d = d + 1
    for a,t in pairs(tree) do
      local b = p+a
      if b < 100 then -- Prune the tree at the lower border.
	local pp = b ~= pn and pn or ok[b] -- Find maximum successor function.
	if d >= 5 then -- Try to place the last cell of a piece and advance.
	  found = true
	  local u = t%10
	  local di = (t-u)/10
	  if di ~= 0 and d == 5 then
	    di = di + p; if pp == di then pp = ok[di] end
	    s = format("%sif b%d and not u%d and not b%d then b%d=k u%d=k f%d(k) u%d=N b%d=N end\n",
		       s, di, u, b, b, u, pp, u, b)
	  else
	    s = format("%sif not u%d and not b%d then b%d=k u%d=k f%d(k) u%d=N b%d=N end\n",
		       s, u, b, b, u, pp, u, b)
	  end
	else -- Try to place an intermediate cell.
	  local di = d ~= 4 and 0 or islands[t]
	  if di == 0 then
	    local st = codetree(t, d, p, pp)
	    if st then
	      found = true
	      s = format("%sif not b%d then b%d=k\n%sb%d=N end\n", s, b, b, st, b)
	    end
	  else -- Combine island checks.
	    di = di + p; if pp == di then pp = ok[di] end
	    local st = codetree(t, 6, p, pp)
	    if st then
	      found = true
	      s = format("%sif b%d and not b%d then b%d=k\n%sb%d=N end\n", s, di, b, b, st, b)
	    end
	  end
	end
      end
    end
    return found and s
  end
  -- Embed the decision tree into a function hierarchy.
  local j = 5
  for p=88,0,-1 do
    local pn = ok[p]
    if pn then
      s = format("%slocal function f%d(k)\nlocal N if b%d then return f%d(k) end k=k+1 b%d=k\n%sb%d=N end\n",
	    s, p, p, pn, p, codetree(dtrees[j], 1, p, pn), p)
      j = j - 1; if j == 0 then j = 10 end
    end
  end
  -- Compile and return solver function and result getter.
  return loadstring(s.."return f0, printresult\n", "solver")(countinit)
end
-- Generate the solver function hierarchy.
local solver, printresult = generatesolver(tonumber(arg and arg[1]) or 10000)
-- The optimizer for LuaJIT 1.1.x is not helpful here, so turn it off.
if jit and jit.opt and jit.version_num < 10200 then jit.opt.start(0) end
-- Run the solver protected to get partial results (max count or ctrl-c).
pcall(solver, 0)
printresult()


takfp

--- The Great Computer Language Shootout
-- http://shootout.alioth.debian.org/
--
-- implemented by: Isaac Gouy
-- Modified by Mike Pall

local function Tak(x,y,z)
	if y>=x then return z end
	return Tak( Tak(x-1.0,y,z), Tak(y-1.0,z,x), Tak(z-1.0,x,y) )
end

n = tonumber(arg and arg[1]) or 1
io.write( string.format("%.1f\n", Tak(n*3.0,n*2.0,n*1.0)) )


harmonic

-- The Great Computer Language Shootout
-- http://shootout.alioth.debian.org/
--
-- contributed by Isaac Gouy

local n = tonumber(arg and arg[1]) or 10000000
local partialSum = 0.0

for d = 1,n do partialSum = partialSum + (1.0/d) end

io.write(string.format("%0.9f",partialSum), "\n")


revcomp

-- The Computer Language Shootout
-- http://shootout.alioth.debian.org/
-- contributed by Mike Pall (with ideas from Rici Lake)

local sub = string.sub
iubc = setmetatable({
  A="T", C="G", B="V", D="H", K="M", R="Y",
  a="T", c="G", b="V", d="H", k="M", r="Y",
  T="A", G="C", V="B", H="D", M="K", Y="R", U="A",
  t="A", g="C", v="B", h="D", m="K", y="R", u="A",
  N="N", S="S", W="W", n="N", s="S", w="W",
}, { __index = function(t, s)
  local r = t[sub(s, 2)]..t[sub(s, 1, 1)]; t[s] = r; return r end })

local wcode = [=[
return function(t, n)
  if n == 1 then return end
  local iubc, sub, write = iubc, string.sub, io.write
  local s = table.concat(t, "", 1, n-1)
  for i=#s-59,1,-60 do
    write(]=]
for i=59,3,-4 do wcode = wcode.."iubc[sub(s, i+"..(i-3)..", i+"..i..")], " end
wcode = wcode..[=["\n")
  end
  local r = #s % 60
  if r ~= 0 then
    for i=r,1,-4 do write(iubc[sub(s, i-3 < 1 and 1 or i-3, i)]) end
    write("\n")
  end
end
]=]
local writerev = loadstring(wcode)()

local t, n = {}, 1
for line in io.lines() do
  local c = sub(line, 1, 1)
  if c == ">" then writerev(t, n); io.write(line, "\n"); n = 1
  elseif c ~= ";" then t[n] = line; n = n + 1 end
end
writerev(t, n)


heapsort

#!/usr/bin/lua
-- $Id: heapsort.lua,v 1.2 2004-06-12 16:19:43 bfulgham Exp $
-- http://shootout.alioth.debian.org
-- contributed by Roberto Ierusalimschy

local IM = 139968
local IA =   3877
local IC =  29573

local LAST = 42
function gen_random(max)
	LAST = math.fmod((LAST * IA + IC), IM)
	return( (max * LAST) / IM )
end

function heapsort(n, ra)
	local j, i, rra
	local l = math.floor(n/2) + 1
	local ir = n;
	while 1 do
	if l > 1 then
		l = l - 1
		rra = ra[l]
	else
		rra = ra[ir]
		ra[ir] = ra[1]
		ir = ir - 1
		if (ir == 1) then
			ra[1] = rra
			return
		end
	end
	i = l
	j = l * 2
	while j <= ir do
		if (j < ir) and (ra[j] < ra[j+1]) then
			j = j + 1
		end
		if rra < ra[j] then
			ra[i] = ra[j]
			i = j
			j = j + i
		else
			j = ir + 1
		end
	end
	ra[i] = rra
	end
end

local ary = {}
local N = (tonumber((arg and arg[1])) or 5)

for i=1, N do
	ary[i] = gen_random(1.0)
end

heapsort(N, ary)

io.write(string.format("%0.10f\n", ary[N]))


reversefile

#!/usr/bin/lua
-- $Id: reversefile.lua,v 1.2 2004-06-12 16:19:44 bfulgham Exp $
-- http://www.bagley.org/~doug/shootout/

local lines = {}
local nl = 0

for l in io.lines() do
    nl = nl + 1
    lines[nl] = l
end

for i=nl,1,-1 do
    io.write(lines[i], "\n")
end


except

-- $Id: except.lua,v 1.2 2004-05-23 04:36:29 bfulgham Exp $
-- http://www.bagley.org/~doug/shootout/
-- from Roberto Ierusalimschy

-- uses `call' to catch errors; return the error message
-- (or nil if there are no errors)

function try (f, arg)
  local status, err = pcall(f, arg)
  if not status then return err end
end

local HI = 0
local LO = 0

function some_function (n)
  local res = try(hi_function, n)
  if res then print("We shouldn't get here: " .. res) end
end

function hi_function (n)
  local res = try(lo_function, n)
  if res == "Hi_Exception" then HI = HI+1
  elseif res then error(res, 0)  -- rethrow
  end
end

function lo_function (n)
  local res = try(blowup, n)
  if res == "Lo_Exception" then LO = LO+1
  elseif res then error(res, 0)  -- rethrow
  end
end

function blowup (n)
  if math.fmod(n,2) ~= 0 then error("Lo_Exception", 0)
  else error("Hi_Exception",0)
  end
end

N = (arg and arg[1]) or 1
for i=1,N do
  some_function(i)
end

print(string.format("Exceptions: HI=%d / LO=%d", HI, LO))


prodcons

-- The Great Computer Language Shootout
-- http://shootout.alioth.debian.org
-- contributed by Isaac Gouy (Lua novice)

n = tonumber(arg[1]) or 1

produced = 0
consumed = 0
buffer = 0

function producer()
   return coroutine.create(

      function()
         while produced < n do
            produced = produced + 1
            buffer = produced
               -- io.write(buffer)
            coroutine.yield()
         end
      end

   )
end

function consumer(p)
   return coroutine.create(

      function()
         local value = 0
         while consumed < n do
            coroutine.resume(p)
            value = buffer
               -- io.write(" -> ", value, "\n")
            consumed = consumed + 1
         end
      end

   )
end

coroutine.resume( consumer( producer() ))
io.write(produced, " ", consumed, "\n")


hash

-- $Id: hash.lua,v 1.2 2004-05-22 04:31:50 bfulgham Exp $
-- http://www.bagley.org/~doug/shootout/
-- Author: Roberto Ierusalimschy
local n = tonumber((arg and arg[1]) or 1)
local X={}
for i=1,n do
  X[string.format("%x", i)] = i
end
local c = 0
for i=n,1,-1 do
  if X[i..''] then c = c+1 end
end


objinst

-- $Id: objinst.lua,v 1.4 2004-07-04 22:26:59 bfulgham Exp $
-- http://shootout.alioth.debian.org/
-- contributed by Roberto Ierusalimschy

--------------------------------------------------------------
-- Toggle class
--------------------------------------------------------------

Toggle = {}

function Toggle:value ()
  return self.state
end

function Toggle:activate ()
  self.state = not self.state
  return self
end

function Toggle:new (start_state)
  local o = {state = start_state}
  self.__index = self
  setmetatable(o, self)
  return o
end

--------------------------------------------------------------
-- NthToggle class
--------------------------------------------------------------

NthToggle = Toggle:new()

function NthToggle:activate ()
  self.counter = self.counter + 1
  if self.counter >= self.count_max then
    self.state = not self.state
    self.counter = 0
  end
  return self
end

function NthToggle:new (start_state, max_counter)
  local o = Toggle.new(self, start_state)
  o.count_max = max_counter
  o.counter = 0
  return o
end

-----------------------------------------------------------
-- main
-----------------------------------------------------------
function main ()
    local N = tonumber((arg and arg[1])) or 1
    local toggle = Toggle:new(1)
    for i=1,5 do
      toggle:activate()
      print(toggle:value() and "true" or "false")
    end
    for i=1,N do
      toggle = Toggle:new(1)
    end

    print("")

    local ntoggle = NthToggle:new(1, 3)
    for i=1,8 do
      ntoggle:activate()
      print(ntoggle:value() and "true" or "false")
    end
    for i=1,N do
      ntoggle = NthToggle:new(1, 3)
    end
end

main()


fibo

-- $Id: fibo.lua,v 1.3 2005-04-25 19:01:38 igouy-guest Exp $
-- http://www.bagley.org/~doug/shootout/

function fib(n)
    if (n < 2) then return(1) end
    return( fib(n-2) + fib(n-1) )
end

N = tonumber((arg and arg[1])) or 1
io.write(fib(N), "\n")


nestedloop

-- $Id: nestedloop.lua,v 1.1.1.1 2004-05-19 18:10:56 bfulgham Exp $
-- http://www.bagley.org/~doug/shootout/

local n = tonumber((arg and arg[1]) or 1)
local x = 0
for a=1,n do
    for b=1,n do
	for c=1,n do
	    for d=1,n do
		for e=1,n do
		    for f=1,n do
			x = x + 1
		    end
		end
	    end
	end
    end
end
io.write(x,"\n")


sieve

-- $Id: sieve.lua,v 1.1.1.1 2004-05-19 18:12:27 bfulgham Exp $
-- http://www.bagley.org/~doug/shootout/
--
-- Roberto Ierusalimschy pointed out the for loop is much
-- faster for our purposes here than using a while loop.

function main(num)
    local flags = {}
    for num=num,1,-1 do
	count = 0
	for i=2,8192 do
	    flags[i] = 1
	end
	for i=2,8192 do
	    if flags[i] == 1 then
	        for k=i+i, 8192, i do
		    flags[k] = 0
		end
	        count = count + 1
	    end
	end
    end
end

NUM = tonumber((arg and arg[1])) or 1
count = 0
main(NUM)
io.write("Count: ", count, "\n")


knucleotide

-- The Great Computer Language Shootout
-- http://shootout.alioth.debian.org/
-- contributed by Mike Pall

local function kfrequency(seq, freq, k, frame)
  local sub = string.sub
  local k1 = k - 1
  for i=frame,string.len(seq)-k1,k do
    local c = sub(seq, i, i+k1)
    freq[c] = freq[c] + 1
  end
end

local function freqdefault()
  return 0
end

local function count(seq, frag)
  local k = string.len(frag)
  local freq = setmetatable({}, { __index = freqdefault })
  for frame=1,k do kfrequency(seq, freq, k, frame) end
  io.write(freq[frag] or 0, "\t", frag, "\n")
end

local function frequency(seq, k)
  local freq = setmetatable({}, { __index = freqdefault })
  for frame=1,k do kfrequency(seq, freq, k, frame) end
  local sfreq, sn = {}, 1
  for c,v in pairs(freq) do sfreq[sn] = c; sn = sn + 1 end
  table.sort(sfreq, function(a, b)
    local fa, fb = freq[a], freq[b]
    return fa == fb and a > b or fa > fb
  end)
  sum = string.len(seq)-k+1
  for _,c in ipairs(sfreq) do
    io.write(string.format("%s %0.3f\n", c, (freq[c]*100)/sum))
  end
  io.write("\n")
end

local function readseq()
  local sub = string.sub
  for line in io.lines() do
    if sub(line, 1, 1) == ">" and sub(line, 2, 6) == "THREE" then break end
  end
  local lines, ln = {}, 0
  for line in io.lines() do
    local c = sub(line, 1, 1)
    if c == ">" then
      break
    elseif c ~= ";" then
      ln = ln + 1
      lines[ln] = line
    end
  end
  return string.upper(table.concat(lines, "", 1, ln))
end

local seq = readseq()
frequency(seq, 1)
frequency(seq, 2)
count(seq, "GGT")
count(seq, "GGTA")
count(seq, "GGTATT")
count(seq, "GGTATTTTAATT")
count(seq, "GGTATTTTAATTTATAGT")


regexdna

-- The Computer Language Shootout
-- http://shootout.alioth.debian.org/
-- contributed by Mike Pall

local gmatch, gsub, write = string.gmatch, string.gsub, io.write

local seq = io.read("*a")
local ilen = #seq

seq = gsub(seq, ">.-\n", "")
seq = gsub(seq, "\n", "")
local clen = #seq

local variants = {
  "agggtaaa", "tttaccct",
  "[cgt]gggtaaa", "tttaccc[acg]",
  "a[act]ggtaaa", "tttacc[agt]t",
  "ag[act]gtaaa", "tttac[agt]ct",
  "agg[act]taaa", "ttta[agt]cct",
  "aggg[acg]aaa", "ttt[cgt]ccct",
  "agggt[cgt]aa", "tt[acg]accct",
  "agggta[cgt]a", "t[acg]taccct",
  "agggtaa[cgt]", "[acg]ttaccct",
}
local count, prev = 0
for i,pattern in ipairs(variants) do
  for _ in gmatch(seq, pattern) do count = count + 1 end
  if prev then
    write(prev, "|", pattern, " ", count, "\n")
    count = 0
    prev = nil
  else
    prev = pattern
  end
end

local subst = {
  B = "(c|g|t)", D = "(a|g|t)",   H = "(a|c|t)", K = "(g|t)",
  M = "(a|c)",   N = "(a|c|g|t)", R = "(a|g)",   S = "(c|g)",
  V = "(a|c|g)", W = "(a|t)",     Y = "(c|t)",
}
-- Dumbing down forced by "the rules":
for k,v in pairs(subst) do seq = gsub(seq, k, v) end
-- Otherwise you're better off with: seq = gsub(seq, "[BDHKMNRSVWY]", subst)

write("\n", ilen, "\n", clen, "\n", #seq, "\n")


spectralnorm

-- The Computer Language Shootout
-- http://shootout.alioth.debian.org/
-- contributed by Isaac Gouy, tuned by Mike Pall

local function A(i, j)
  local ij = i+j
  return 1.0 / (ij * (ij+1) * 0.5 + i+1)
end

local function Av(n, x, y)
  for i = 0,n-1 do
    local a = 0
    for j = 0,n-1 do a = a + A(i,j) * x[j] end
    y[i] = a
  end
end

local function Atv(n, x, y)
  for i = 0,n-1 do
    local a = 0
    for j = 0,n-1 do a = a + A(j,i) * x[j] end
    y[i] = a
  end
end

local function AtAv(n, x, y, t)
  Av(n, x, t)
  Atv(n, t, y)
end

local n = tonumber(arg and arg[1]) or 100
local u, v, t = {}, {}, {}
for i = 0,n-1 do u[i] = 1 end

for i = 1,10 do AtAv(n, u, v, t) AtAv(n, v, u, t) end

local vBv, vv = 0, 0
for i = 0,n-1 do
  local ui, vi = u[i], v[i]
  vBv = vBv + ui*vi
  vv = vv + vi*vi
end

io.write(string.format("%0.9f\n", math.sqrt(vBv / vv)))


nbody

-- The Great Computer Language Shootout
-- http://shootout.alioth.debian.org/
-- contributed by Isaac Gouy, tuned by Mike Pall

local sqrt = math.sqrt

local PI = 3.141592653589793
local SOLAR_MASS = 4 * PI * PI
local DAYS_PER_YEAR = 365.24

local Jupiter = {
   x = 4.84143144246472090e+00
  ,y = -1.16032004402742839e+00
  ,z = -1.03622044471123109e-01
  ,vx = 1.66007664274403694e-03 * DAYS_PER_YEAR
  ,vy = 7.69901118419740425e-03 * DAYS_PER_YEAR
  ,vz = -6.90460016972063023e-05 * DAYS_PER_YEAR
  ,mass = 9.54791938424326609e-04 * SOLAR_MASS
}

local Saturn = {
   x = 8.34336671824457987e+00
  ,y = 4.12479856412430479e+00
  ,z = -4.03523417114321381e-01
  ,vx = -2.76742510726862411e-03 * DAYS_PER_YEAR
  ,vy = 4.99852801234917238e-03 * DAYS_PER_YEAR
  ,vz = 2.30417297573763929e-05 * DAYS_PER_YEAR
  ,mass = 2.85885980666130812e-04 * SOLAR_MASS
}

local Uranus = {
   x = 1.28943695621391310e+01
  ,y = -1.51111514016986312e+01
  ,z = -2.23307578892655734e-01
  ,vx = 2.96460137564761618e-03 * DAYS_PER_YEAR
  ,vy = 2.37847173959480950e-03 * DAYS_PER_YEAR
  ,vz = -2.96589568540237556e-05 * DAYS_PER_YEAR
  ,mass = 4.36624404335156298e-05 * SOLAR_MASS
}

local Neptune = {
   x = 1.53796971148509165e+01
  ,y = -2.59193146099879641e+01
  ,z = 1.79258772950371181e-01
  ,vx = 2.68067772490389322e-03 * DAYS_PER_YEAR
  ,vy = 1.62824170038242295e-03 * DAYS_PER_YEAR
  ,vz = -9.51592254519715870e-05 * DAYS_PER_YEAR
  ,mass = 5.15138902046611451e-05 * SOLAR_MASS
}

local Sun = { x = 0, y = 0, z = 0,
              vx = 0, vy = 0, vz = 0, mass = SOLAR_MASS }

local function advance(bodies, nbody, dt)
  for i=1,nbody do
    local bi = bodies[i]
    local bix, biy, biz, bimass = bi.x, bi.y, bi.z, bi.mass
    local bivx, bivy, bivz = bi.vx, bi.vy, bi.vz
    for j=i+1,nbody do
      local bj = bodies[j]
      local dx, dy, dz = bix-bj.x, biy-bj.y, biz-bj.z
      local distance = sqrt(dx*dx + dy*dy + dz*dz)
      local mag = dt / (distance * distance * distance)
      local bim, bjm = bimass*mag, bj.mass*mag
      bivx = bivx - (dx * bjm)
      bivy = bivy - (dy * bjm)
      bivz = bivz - (dz * bjm)
      bj.vx = bj.vx + (dx * bim)
      bj.vy = bj.vy + (dy * bim)
      bj.vz = bj.vz + (dz * bim)
    end
    bi.vx = bivx
    bi.vy = bivy
    bi.vz = bivz
  end
  for i=1,nbody do
    local bi = bodies[i]
    bi.x = bi.x + (dt * bi.vx)
    bi.y = bi.y + (dt * bi.vy)
    bi.z = bi.z + (dt * bi.vz)
  end
end

local function energy(bodies, nbody)
  local e = 0
  for i=1,nbody do
    local bi = bodies[i]
    local vx, vy, vz, bim = bi.vx, bi.vy, bi.vz, bi.mass
    e = e + (0.5 * bim * (vx*vx + vy*vy + vz*vz))
    for j=i+1,nbody do
      local bj = bodies[j]
      local dx, dy, dz = bi.x-bj.x, bi.y-bj.y, bi.z-bj.z
      local distance = sqrt(dx*dx + dy*dy + dz*dz)
      e = e - ((bim * bj.mass) / distance)
    end
  end
  return e
end

local function offsetMomentum(b, nbody)
  local px, py, pz = 0, 0, 0
  for i=1,nbody do
    local bi = b[i]
    local bim = bi.mass
    px = px + (bi.vx * bim)
    py = py + (bi.vy * bim)
    pz = pz + (bi.vz * bim)
  end
  b[1].vx = -px / SOLAR_MASS
  b[1].vy = -py / SOLAR_MASS
  b[1].vz = -pz / SOLAR_MASS
end

local N = tonumber(arg and arg[1]) or 1000
local bodies = { Sun, Jupiter, Saturn, Uranus, Neptune }
local nbody = table.getn(bodies)

offsetMomentum(bodies, nbody)
io.write( string.format("%0.9f",energy(bodies, nbody)), "\n")
for i=1,N do advance(bodies, nbody, 0.01) end
io.write( string.format("%0.9f",energy(bodies, nbody)), "\n")


strcat

-- $Id: strcat.lua,v 1.3 2004-07-08 03:47:07 bfulgham Exp $
-- http://shootout.alioth.debian.org
-- contributed by Roberto Ierusalimschy

local n = tonumber((arg and arg[1]) or 1)
local buff = {}
for i=1,n do
  table.insert(buff, "hello\n")
end
local s = table.concat(buff)
print(string.len(s))


-- $Id: hash2.lua,v 1.2 2004-05-20 02:39:49 bfulgham Exp $
-- http://www.bagley.org/~doug/shootout/
-- with help from Roberto Ierusalimschy

local n = tonumber((arg and arg[1]) or 1)

local hash1={}
for i=0,10000 do
    hash1["foo_"..i] = i
end
local hash2={}
for i=1,n do
    for k,v in pairs(hash1) do
	hash2[k] = v + (hash2[k] or 0)
    end
end

io.write(string.format("%d %d %d %d\n", hash1["foo_1"], hash1["foo_9999"],
	     hash2["foo_1"], hash2["foo_9999"]))


wordfreq

-- $Id: wordfreq.lua,v 1.1.1.1 2004-05-19 18:14:18 bfulgham Exp $
-- http://www.bagley.org/~doug/shootout/
-- implemented by: Roberto Ierusalimschy

-- this version reads input line by line and so it is
-- noticably slower than the version that reads the
-- input in blocks.

local read = io.read
local gsub,strlower,format = string.gsub,string.lower,string.format
local tinsert,sort = table.insert,table.sort

local words = {}   -- list of all words (for sorting)
local count = {}   -- count occurrences of each word

while 1 do
  local line = read()
  if line == nil then break end
  gsub(strlower(line), "(%l+)", function (w)
    local cw = count[w]
    if cw == nil then     -- first occurrence?
      cw = 0
      tinsert(words, w)
    end
    count[w] = cw + 1
  end)
end

sort(words, function (a,b)
  return  count[a] > count[b]  or
         (count[a] == count[b] and a > b)
end)

for i=1,#words do
  local w = words[i]
  io.write(format("%7d\t%s\n", count[w], w))
end


ary

-- $Id: ary.lua,v 1.2 2004-05-22 07:25:00 bfulgham Exp $
-- http://www.bagley.org/~doug/shootout/

local n = tonumber((arg and arg[1]) or 1)

local x, y = {}, {}
local last = n - 1

for i=0,last do
  x[i] = i + 1
  y[i] = 0
end
for k=1,1000 do
  for j=last,0,-1 do
    y[j] = y[j] + x[j]
  end
end

io.write(y[0], " ", y[last], "\n")


wc

--- The Great Computer Language Shootout
-- http://shootout.alioth.debian.org/
--
-- Contributed by Roberto Ierusalimschy
-- Modified by Mike Pall

BUFSIZE = 2^12
local read, len, gsub = io.read, string.len, string.gsub

local cc,lc,wc = 0,0,0
while true do
    local lines, rest = read(BUFSIZE, "*l")
    if lines == nil then break end
    if rest then lines = lines..rest..'\n' end
    cc = cc+len(lines)
    local _,t = gsub(lines, "%S+", "")   -- count words in the line
    wc = wc+t
    _,t = gsub(lines, "\n", "\n")   -- count newlines in the line
    lc = lc+t
end

io.write(lc, " ", wc, " ", cc, "\n")


nsievebits

-- The Great Computer Language Shootout
-- http://shootout.alioth.debian.org/
-- contributed by Mike Pall

local floor, ceil = math.floor, math.ceil

local precision = 50 -- Maximum precision of lua_Number (minus safety margin).
local onebits = (2^precision)-1

local function nsieve(p, m)
  local cm = ceil(m/precision)
  do local onebits = onebits; for i=0,cm do p[i] = onebits end end
  local count, idx, bit = 0, 2, 2
  for i=2,m do
    local r = p[idx] / bit
    if r - floor(r) >= 0.5 then -- Bit set?
      local kidx, kbit = idx, bit
      for k=i+i,m,i do
        kidx = kidx + i
        while kidx >= cm do kidx = kidx - cm; kbit = kbit + kbit end
        local x = p[kidx]
        local r = x / kbit
        if r - floor(r) >= 0.5 then p[kidx] = x - kbit*0.5 end -- Clear bit.
      end
      count = count + 1
    end
    idx = idx + 1
    if idx >= cm then idx = 0; bit = bit + bit end
  end
  return count
end

local N = tonumber(arg and arg[1]) or 1
if N < 2 then N = 2 end
local primes = {}

for i=0,2 do
  local m = (2^(N-i))*10000
  io.write(string.format("Primes up to %8d %8d\n", m, nsieve(primes, m)))
end


mandelbrot

-- The Computer Language Shootout
-- http://shootout.alioth.debian.org/
-- contributed by Mike Pall

local width = tonumber(arg and arg[1]) or 100
local height, wscale = width, 2/width
local m, limit2 = 50, 4.0
local write, char = io.write, string.char

write("P4\n", width, " ", height, "\n")

for y=0,height-1 do
  local Ci = 2*y / height - 1
  for xb=0,width-1,8 do
    local bits = 0
    local xbb = xb+7
    for x=xb,xbb < width and xbb or width-1 do
      bits = bits + bits
      local Zr, Zi, Zrq, Ziq = 0.0, 0.0, 0.0, 0.0
      local Cr = x * wscale - 1.5
      for i=1,m do
        local Zri = Zr*Zi
        Zr = Zrq - Ziq + Cr
        Zi = Zri + Zri + Ci
        Zrq = Zr*Zr
        Ziq = Zi*Zi
        if Zrq + Ziq > limit2 then
          bits = bits + 1
          break
        end
      end
    end
    if xbb >= width then
      for x=width,xbb do bits = bits + bits + 1 end
    end
    write(char(255-bits))
  end
end


regexmatch

-- $Id: regexmatch.lua,v 1.2 2004-06-12 16:19:44 bfulgham Exp $
-- http://shootout.alioth.debian.org
-- contributed by Roberto Ierusalimschy

local text = io.read("*a")

-- make sure text does not start with a number
text = "\n" .. text

-- pattern is: not a digit, optional (, 3 digits, optional ),
-- space, 3 digits, space or hyphen, 4 digits, not a digit
local pattern = "%D(%(?)(%d%d%d)(%)?) (%d%d%d)[- ](%d%d%d%d)%f[%D]"

local N = tonumber((arg and arg[1])) or 1
local count = 0
for i=N,1,-1 do
  for open,area,close,exch,digits in string.gmatch(text, pattern) do
      if (open == '(') == (close == ')') then
        local tel = "("..area..") "..exch.."-"..digits
        if i == 1 then
          count = count+1
          io.write(count, ": ", tel, "\n")
        end
      end
    end
end


chameneos

-- The Great Computer Language Shootout
-- http://shootout.alioth.debian.org/
-- contributed by Mike Pall

local co = coroutine
local create, resume, yield = co.create, co.resume, co.yield

local N = tonumber(arg and arg[1]) or 10
local first, second

-- Meet another creature.
local function meet(me)
  while second do yield() end -- Wait until meeting place clears.
  local other = first
  if other then -- Hey, I found a new friend!
    first = nil
    second = me
  else -- Sniff, nobody here (yet).
    local n = N - 1
    if n < 0 then return end -- Uh oh, the mall is closed.
    N = n
    first = me
    repeat yield(); other = second until other -- Wait for another creature.
    second = nil
    yield() -- Be nice and let others meet up.
  end
  return other
end

-- Create a very social creature.
local function creature(color)
  return create(function()
    local me = color
    for met=0,1e9 do
      local other = meet(me)
      if not other then return met end
      if me ~= other then
        if me == "blue" then me = other == "red" and "yellow" or "red"
        elseif me == "red" then me = other == "blue" and "yellow" or "blue"
        else me = other == "blue" and "red" or "blue" end
      end
    end
  end)
end

-- Trivial round-robin scheduler.
local function schedule(threads)
  local resume = resume
  local nthreads, meetings = table.getn(threads), 0
  repeat
    for i=1,nthreads do
      local thr = threads[i]
      if not thr then return meetings end
      local ok, met = resume(thr)
      if met then
        meetings = meetings + met
        threads[i] = nil
      end
    end
  until false
end

-- A bunch of colorful creatures.
local threads = {
  creature("blue"),
  creature("red"),
  creature("yellow"),
  creature("blue"),
}

io.write(schedule(threads), "\n")


moments

-- $Id: moments.lua,v 1.2 2004-05-24 02:23:25 bfulgham Exp $
-- http://www.bagley.org/~doug/shootout/
-- implemented by: Roberto Ierusalimschy

local nums = {}
local n = 0
local sum = 0
while 1 do
  local line = io.read()
  if line == nil then break end
  line = line+0        -- convert line to number
  sum = sum + line
  n = n + 1
  nums[n] = line
end

local mean = sum/n

local average_deviation, variance, skew, kurtosis = 0, 0, 0, 0

for i = 1, n do
  local deviation = nums[i] - mean
  average_deviation = average_deviation + math.abs(deviation)
  variance = variance + deviation^2
  skew = skew + deviation^3
  kurtosis = kurtosis + deviation^4
end

average_deviation = average_deviation/n
variance = variance/(n-1)
local standard_deviation = math.sqrt(variance)
if variance ~= 0 then
  skew = skew / (n * variance * standard_deviation)
  kurtosis = kurtosis/(n * variance * variance) - 3.0
end

table.sort(nums)
local mid = math.floor(n/2)
local median
if math.fmod(n,2) == 1 then
  median = nums[mid+1]
else
  median = (nums[mid] + nums[mid+1])/2
end

io.write(string.format("n:                  %d\n", n))
io.write(string.format("median:             %f\n", median))
io.write(string.format("mean:               %f\n", mean))
io.write(string.format("average_deviation:  %f\n", average_deviation))
io.write(string.format("standard_deviation: %f\n", standard_deviation))
io.write(string.format("variance:           %f\n", variance))
io.write(string.format("skew:               %f\n", skew))
io.write(string.format("kurtosis:           %f\n", kurtosis))


sumcol

-- $Id: sumcol.lua,v 1.3 2004-07-08 03:47:07 bfulgham Exp $
-- http://www.bagley.org/~doug/shootout/

local sum = 0
for line in io.lines() do
    sum = sum + line
end
print(sum)


recursive

-- The Computer Language Shootout
-- http://shootout.alioth.debian.org/
-- contributed by Mike Pall

local function ack(m, n)
  if m == 0 then return n+1 end
  if n == 0 then return ack(m-1, 1) end
  return ack(m-1, (ack(m, n-1))) -- The parentheses are deliberate.
end

local function fib(n)
  if n < 2 then return 1 end
  return fib(n-2) + fib(n-1)
end

local function tak(x, y, z)
  if y >= x then return z end
  return tak(tak(x-1, y, z), tak(y-1, z, x), (tak(z-1, x, y)))
end

local write, format = io.write, string.format
local n = tonumber(arg[1]) - 1
write(format("Ack(3,%d): %d\n", n+1, ack(3, n+1)))
write(format("Fib(%.1f): %.1f\n", n+28.0, fib(n+28.0)))
write(format("Tak(%d,%d,%d): %d\n", 3*n, 2*n, n, tak(3*n, 2*n, n)))
write(format("Fib(3): %d\n", fib(3)))
write(format("Tak(3.0,2.0,1.0): %.1f\n", tak(3.0, 2.0, 1.0)))


nsieve

-- The Computer Language Shootout
-- http://shootout.alioth.debian.org/
-- contributed by Isaac Gouy
-- modified by Mike Pall

local function nsieve(m,isPrime)
   for i=2,m do
      isPrime[i] = true
   end
   local count = 0

   for i=2,m do
      if isPrime[i] then
         for k=i+i, m, i do
--            if isPrime[k] then isPrime[k] = false end
            isPrime[k] = false
         end
         count = count + 1
      end
   end
   return count
end

local n = tonumber(arg and arg[1]) or 1
if n < 2 then n = 2 end
local flags = {}

local m = (2^n)*10000
io.write( string.format("Primes up to %8d %8d", m, nsieve(m,flags)), "\n")

m = (2^(n-1))*10000
io.write( string.format("Primes up to %8d %8d", m, nsieve(m,flags)), "\n")

m = (2^(n-2))*10000
io.write( string.format("Primes up to %8d %8d", m, nsieve(m,flags)), "\n")


binarytrees

-- The Computer Language Shootout
-- http://shootout.alioth.debian.org/
-- contributed by Mike Pall
-- modified by Sokolov yura

--collectgarbage("setstepmul", 0) -- sometimes it helps much. For this benchmark ~ 10%

local function BottomUpTree(item, depth)
  if depth > 0 then
    local i = item + item
    depth = depth - 1
    local left, right = BottomUpTree(i-1, depth), BottomUpTree(i, depth)
    return { item, left, right }
  else
    return { item } -- Faster for LuaJIT: return { item, false }
  end
end

local function ItemCheck(tree)
  if #tree == 3 then -- Faster for LuaJIT: if tree[2] then
    return tree[1] + ItemCheck(tree[2]) - ItemCheck(tree[3])
  else
    return tree[1]
  end
end

local N = tonumber(arg and arg[1]) or 0
local mindepth = 4
local maxdepth = mindepth + 2
if maxdepth < N then maxdepth = N end

do
  local stretchdepth = maxdepth + 1
  local stretchtree = BottomUpTree(0, stretchdepth)
  io.write(string.format("stretch tree of depth %d\t check: %d\n",
    stretchdepth, ItemCheck(stretchtree)))
end

local longlivedtree = BottomUpTree(0, maxdepth)

for depth=mindepth,maxdepth,2 do
  local iterations = 2 ^ (maxdepth - depth + mindepth)
  local check = 0
  for i=1,iterations do
    check = check + ItemCheck(BottomUpTree(1, depth)) +
            ItemCheck(BottomUpTree(-1, depth))
  end
  io.write(string.format("%d\t trees of depth %d\t check: %d\n",
    iterations*2, depth, check))
end

io.write(string.format("long lived tree of depth %d\t check: %d\n",
  maxdepth, ItemCheck(longlivedtree)))


hello

-- $Id: hello.lua,v 1.1.1.1 2004-05-19 18:10:16 bfulgham Exp $
-- http://www.bagley.org/~doug/shootout/

io.write("hello world\n")


random

-- The Computer Language Shootout
-- http://shootout.alioth.debian.org/
-- contributed by Roberto Ierusalimschy, tuned by Mike Pall

local IM = 139968
local IA = 3877
local IC = 29573
local LAST = 42

local function gen_random(max)
  local y = (LAST * IA + IC) % IM
  LAST = y
  return (max * y) / IM
end

local N = tonumber(arg and arg[1]) or 1
for i=2,N do gen_random(100) end
io.write(string.format("%.9f\n", gen_random(100)))


lists

-- $Id: lists.lua,v 1.1.1.1 2004-05-19 18:10:23 bfulgham Exp $
-- http://www.bagley.org/~doug/shootout/
-- implemented by: Roberto Ierusalimschy

--------------------------------------------------------------
-- List module
-- defines a prototipe for lists
--------------------------------------------------------------

List = {first = 0, last = -1}

function List:new ()
  local n = {}
  for k,v in pairs(self) do n[k] = v end
  return n
end

function List:length ()
  return self.last - self.first + 1
end

function List:pushleft (value)
  local first = self.first - 1
  self.first = first
  self[first] = value
end

function List:pushright (value)
  local last = self.last + 1
  self.last = last
  self[last] = value
end

function List:popleft ()
  local first = self.first
  if first > self.last then error"list is empty" end
  local value = self[first]
  self[first] = nil  -- to allow collection
  self.first = first+1
  return value
end

function List:popright ()
  local last = self.last
  if self.first > last then error"list is empty" end
  local value = self[last]
  self[last] = nil  -- to allow collection
  self.last = last-1
  return value
end

function List:reverse ()
  local i, j = self.first, self.last
  while i<j do
    self[i], self[j] = self[j], self[i]
    i = i+1
    j = j-1
  end
end

function List:equal (otherlist)
  if self:length() ~= otherlist:length() then return nil end
  local diff = otherlist.first - self.first
  for i1=self.first,self.last do
    if self[i1] ~= otherlist[i1+diff] then return nil end
  end
  return 1
end

-----------------------------------------------------------
-----------------------------------------------------------

-- Some tests

function test ()
  local SIZE = 10000
  -- create a list with elements 1..SIZE
  local l1 = List:new()
  for i=1,SIZE do
    l1:pushright(i)
  end
  -- creates a copy of l1
  local l2 = l1:new()
  -- remove each individual item from left side of l2 and
  -- append to right side of l3 (preserving order)
  local l3 = List:new()
  while l2:length() > 0 do
    l3:pushright(l2:popleft())
  end
  -- remove each individual item from right side of l3 and
  -- append to right side of l2 (reversing list)
  while l3:length() > 0 do
    l2:pushright(l3:popright())
  end
  -- reverse l1 in place
  l1:reverse()
  -- compare Li1 and Li2 for equality
  -- and return length of the list
  if not l1:equal(l2) then return nil
  else return l1:length()
  end
end

N = tonumber((arg and arg[1])) or 1
for i=1, N do
  result = test()
end
print(result)


meteor

-- The Great Computer Language Shootout
-- http://shootout.alioth.debian.org/
-- contributed by Mike Pall
-- Generate a decision tree based solver for the meteor puzzle.
local function generatesolver(countinit)
  local pairs, ipairs, format = pairs, ipairs, string.format
  local byte, min, sort = string.byte, math.min, table.sort
  -- Cached position to distance lookup.
  local dist = setmetatable({}, { __index = function(t, xy)
    local x = xy%10; local y = (xy-x)/10
    if (x+y)%2 == 1 then y = y + 1; x = 10 - x end
    local d = xy + 256*x*x + 1024*y*y; t[xy] = d; return d
  end})
  -- Generate an optimized decision tree (within 4% of a hand-tuned tree).
  local dtree = {}
  local rot = { nil, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {} }
  for k=0,9 do
    -- Generate 10 initial pieces from line noise. :-)
    rot[1] = t
    for i,xy in ipairs(t) do
      local x = xy%10; local y = (xy-x-60)/10
      -- Add 11 more variations by rotating and flipping.
      for j=2,12 do
	if j == 7 then y = -y else x,y = (x+3*y)/2, (y-x)/2 end
	rot[j][i] = x+10*y
      end
    end
    for _,v in ipairs(rot) do
      -- Normalize to origin, add distance, sort by distance from origin.
      local m = min(v[1], v[2], v[3], v[4], v[5])
      for i=1,5 do v[i] = dist[v[i]-m] end
      sort(v)
      -- Insert into decision tree in distance order.
      local tt = dtree
      for i=2,4 do
	local xy = v[i]%256
	local tn = tt[xy]
	if not tn then tn = {}; tt[xy] = tn end -- Create nodes as needed.
	tt = tn
      end
      tt[v[5]%256] = k -- Leaves hold the piece numbers.
    end
  end
  -- Lookup table to validate a cell and to find its successor.
  local ok = {}
  for i=0,150 do ok[i] = false end
  for i=99,0,-1 do
    local x = i%10
    if ((i-x)/10+x)%2 == 0 then
      ok[i] = i + (ok[i+1] and 1 or (ok[i+2] and 2 or 3))
    end
  end
  local s = "local u0,u1,u2,u3,u4,u5,u6,u7,u8,u9" -- Piece use flags.
  for p=0,99 do if ok[p] then s = s..",b"..p end end -- Board cells.
  s = s.."\n"..[[
local countinit = ...
local count = countinit
local b0a, b0b, pcs = 9, 0, {}
local smin, smax
local write = io.write
-- Print min/max boards.
local function printboard(s)
  local flip = true
  for x in string.gmatch(string.gsub(s, ".", "%1 "), "..........") do
    write(x, flip and "\n " or "\n")
    flip = not flip
  end
  write("\n")
end
-- Print result.
local function printresult()
  write(countinit-count, " solutions found\n\n")
  printboard(smin)
  printboard(smax)
end
-- Generate piece lookup array from the order of use.
local function genp()
  local p = pcs
  p[u0] = "0" p[u1] = "1" p[u2] = "2" p[u3] = "3" p[u4] = "4"
  p[u5] = "5" p[u6] = "6" p[u7] = "7" p[u8] = "8" p[u9] = "9"
  return p
end
-- Goal function.
local function f91(k)
  if k ~= 10 then return end
  count = count - 1
  repeat
    -- Quick precheck before constructing the string.
    local b0 = b0
    if b0 <= b0a then b0a = b0 elseif b0 >= b0b then b0b = b0 else break end
    -- Translate the filled board to a string.
    local p = genp()
    local s = p[b0] ]]
  for p=2,99 do if ok[p] then s = s.."..p[b"..p.."]" end end
  s = s..[[
    -- Remember min/max boards.
    if not smin then smin = s; smax = s
    elseif s < smin then smin = s elseif s > smax then smax = s end
  until true
  if count == 0 then error("") end -- Early abort if max count given.
end
local f93 = f91
]]
  -- Recursively prune the decision tree and convert it to Lua code.
  local function codetree(tree, d, p, pn)
    local found, s = false, ""
    d = d + 1
    for a,t in pairs(tree) do
      local b = p+a
      local pp = ok[b]
      if pp then -- Prune the tree on-the-fly.
	if b ~= pn then pp = pn end -- Find maximum successor function.
	if d == 5 then -- Try to place the last cell of a piece and advance.
	  found = true
	  s = format("%sif not u%d and not b%d then b%d=k u%d=k f%d(k) u%d=N b%d=N end\n",
		     s, t, b, b, t, pp, t, b)
	else -- Try to place an intermediate cell.
	  local st = codetree(t, d, p, pp)
	  if st then -- But only if the subtree is not empty.
	    found = true
	    s = format("%sif not b%d then b%d=k\n%sb%d=N end\n", s, b, b, st, b)
	  end
	end
      end
    end
    return found and s
  end
  -- Embed the decision tree into a function hierarchy.
  for p=88,0,-1 do
    local pn = ok[p]
    if pn then
      s = format("%slocal function f%d(k)\nlocal N if b%d then return f%d(k) end k=k+1 b%d=k\n%sb%d=N end\n",
	    s, p, p, pn, p, codetree(dtree, 1, p, pn), p)
    end
  end
  -- Compile and return solver function and result getter.
  return loadstring(s.."return f0, printresult\n", "solver")(countinit)
end
-- Run the solver protected to get partial results (max count or ctrl-c).
local solver, printresult = generatesolver(tonumber(arg and arg[1]) or 0)
pcall(solver, 0)
printresult()


message

-- The Great Computer Language Shootout
-- http://shootout.alioth.debian.org/
-- contributed by Mike Pall

local co = coroutine
local wrap, yield = co.wrap, co.yield
if co.cstacksize then co.cstacksize(1) end -- Use minimum C stack.

local function link(n)
  if n > 1 then
    local cofunc = wrap(link)
    cofunc(n-1)
    yield()
    repeat yield(cofunc() + 1) until false
  else
    repeat yield(1) until false
  end
end

local N = tonumber(arg and arg[1]) or 10
local cofunc = wrap(link)
cofunc(500)
local count = 0
for i = 1,N do count = count + cofunc() end
io.write(count, "\n")


ackermann

--- The Great Computer Lanuage Shootout
--  http://shootout.alioth.debian.org
--
-- Contributed by ???
-- Modified by Mike Pall (email withheld by request)
--
local function Ack(m, n)
  if m == 0 then return n+1 end
  if n == 0 then return Ack(m-1, 1) end
  return Ack(m-1, Ack(m, n-1))
end
local N = tonumber(arg and arg[1]) or 1
io.write("Ack(3,", N ,"): ", Ack(3,N), "\n")


methcall

-- $Id: methcall.lua,v 1.2 2004-06-12 16:19:43 bfulgham Exp $
-- http://shootout.alioth.debian.org
-- contributed by Roberto Ierusalimschy

--------------------------------------------------------------
-- Toggle class
--------------------------------------------------------------

Toggle = {}

function Toggle:value ()
  return self.state
end

function Toggle:activate ()
  self.state = not self.state
  return self
end

function Toggle:new (start_state)
  local o = {state = start_state}
  self.__index =self
  setmetatable(o, self)
  return o
end

--------------------------------------------------------------
-- NthToggle class
--------------------------------------------------------------

NthToggle = Toggle:new()

function NthToggle:activate ()
  self.counter = self.counter + 1
  if self.counter >= self.count_max then
    self.state = not self.state
    self.counter = 0
  end
  return self
end

function NthToggle:new (start_state, max_counter)
  local o = Toggle.new(self, start_state)
  o.count_max = max_counter
  o.counter = 0
  return o
end

-----------------------------------------------------------
-- main
-----------------------------------------------------------

function main ()
  local N = tonumber((arg and arg[1])) or 1

  local val = 1
  local toggle = Toggle:new(val)
  for i=1,N do
    val = toggle:activate():value()
  end
  print(val and "true" or "false")

  val = 1
  local ntoggle = NthToggle:new(val, 3)
  for i=1,N do
    val = ntoggle:activate():value()
  end
  print(val and "true" or "false")
end

main()


pidigits

-- The Great Computer Language Shootout
-- http://shootout.alioth.debian.org/
--
-- contributed by Isaac Gouy

-- requires BigNum library
-- http://oss.digirati.com.br/luabignum/

require( "BigNum.lua" ) ;

-- Transformation

local T = {}

function T.bigzero() return BigNum.new(0) end
function T.bigone() return BigNum.new(1) end
function T.bigten() return BigNum.new(10) end

function T.new(q,r,s,t)
   return {
       q = BigNum.new(q)
      ,r = BigNum.new(r)
      ,s = BigNum.new(s)
      ,t = BigNum.new(t)
      ,k = 0
      }
end

function T.unity() return T.new(1,0,0,1) end
function T.zero() return T.new(0,0,0,0) end

function T.compose(a,b)
   local qq = T.bigzero()
   local qr = T.bigzero()
   local rt = T.bigzero()
   local qrrt = T.bigzero()
   local sq = T.bigzero()
   local ts = T.bigzero()
   local sqts = T.bigzero()
   local sr = T.bigzero()
   local tt = T.bigzero()
   local srtt = T.bigzero()

   BigNum.mul(a.q,b.q,qq)

   BigNum.mul(a.q,b.r,qr)
   BigNum.mul(a.r,b.t,rt)
   BigNum.add(qr,rt,qrrt)

   BigNum.mul(a.s,b.q,sq)
   BigNum.mul(a.t,b.s,ts)
   BigNum.add(sq,ts,sqts)

   BigNum.mul(a.s,b.r,sr)
   BigNum.mul(a.t,b.t,tt)
   BigNum.add(sr,tt,srtt)

   return T.new(qq, qrrt, sqts, srtt)
end

function T.extract(a,j)
   local bigj = BigNum.new(j)
   local qj = T.bigzero()
   local qjr = T.bigzero()
   local sj = T.bigzero()
   local sjt = T.bigzero()
   local n = T.bigzero()
   local sjt = T.bigzero()

   BigNum.mul(a.q,bigj,qj)
   BigNum.add(qj,a.r,qjr)

   BigNum.mul(a.s,bigj,sj)
   BigNum.add(sj,a.t,sjt)

   local d = T.bigzero()
   local r = T.bigzero()
   BigNum.div(qjr,sjt,d,r)

   return math.floor( tonumber( BigNum.mt.tostring(d) ))
end

function T.next(a)
   a.k = a.k + 1
   a.q = BigNum.new(a.k)
   a.r = BigNum.new(4*a.k + 2)
   a.s = T.bigzero()
   a.t = BigNum.new(2*a.k + 1)
   return a
end

-- Pi Digit Stream

local P = {}

function P.new()
   return {
       z = T.unity()
      ,x = T.zero()
      ,inverse = T.zero()
      }
end

function P.produce(a,j)
   local i = a.inverse
   i.q = T.bigten()
   i.r = BigNum.new(-10*j)
   i.s = T.bigzero()
   i.t = T.bigone()
   return T.compose(i,a.z)
end

function P.consume(a,b)
   return T.compose(a.z,b)
end

function P.digit(a)
   return T.extract(a.z,3)
end

function P.isSafe(a,j)
   return j == T.extract(a.z,4)
end

function P.next(a)
   local y
   y = P.digit(a)
   if P.isSafe(a,y) then
      a.z = P.produce(a,y)
      return y
   else
      a.z = P.consume(a,T.next(a.x))
      return P.next(a)
   end
end

-- Main

n = tonumber(arg and arg[1]) or 27
i = 0
length = 10
pidigit = P.new()

while n > 0 do
   if n < length then
      for _ = 1,n do io.write( P.next(pidigit) ) end
      for _ = n,length do io.write( ' ' ) end
      i = i + n
   else
      for _ = 1,length do io.write( P.next(pidigit) ) end
      i = i + length
   end
   io.write('\t:', i, '\n')
   n = n - length
end


partialsums

-- The Computer Language Shootout
-- http://shootout.alioth.debian.org/
-- contributed by Mike Pall

local n = tonumber(arg[1])
local function pr(fmt, x) io.write(string.format(fmt, x)) end

local a1, a2, a3, a4, a5, a6, a7, a8, a9, alt = 1, 0, 0, 0, 0, 0, 0, 0, 0, 1
local sqrt, sin, cos = math.sqrt, math.sin, math.cos
for k=1,n do
  local k2, sk, ck = k*k, sin(k), cos(k)
  local k3 = k2*k
  a1 = a1 + (2/3)^k
  a2 = a2 + 1/sqrt(k)
  a3 = a3 + 1/(k2+k)
  a4 = a4 + 1/(k3*sk*sk)
  a5 = a5 + 1/(k3*ck*ck)
  a6 = a6 + 1/k
  a7 = a7 + 1/k2
  a8 = a8 + alt/k
  a9 = a9 + alt/(k+k-1)
  alt = -alt
end
pr("%.9f\t(2/3)^k\n", a1)
pr("%.9f\tk^-0.5\n", a2)
pr("%.9f\t1/k(k+1)\n", a3)
pr("%.9f\tFlint Hills\n", a4)
pr("%.9f\tCookson Hills\n", a5)
pr("%.9f\tHarmonic\n", a6)
pr("%.9f\tRiemann Zeta\n", a7)
pr("%.9f\tAlternating Harmonic\n", a8)
pr("%.9f\tGregory\n", a9)


xd

-- hex dump
-- usage: lua xd.lua < file
local offset=0
while true do
 local s=io.read(16)
 if s==nil then return end
 io.write(string.format("%08X  ",offset))
 string.gsub(s,"(.)",
 io.write(string.rep(" ",3*(16-string.len(s))))
 io.write(" ",string.gsub(s,"%c","."),"\n")
 offset=offset+16
end