mirror of
https://github.com/DrBeef/Raze.git
synced 2024-11-15 08:52:00 +00:00
Lunatic: add 'stat' module for running statistics.
Also, rewrite the mapastats iterator and the LIZTROOP hitscan timing in terms of that. git-svn-id: https://svn.eduke32.com/eduke32@2858 1a8010ca-5511-0410-912e-c29ae57300e0
This commit is contained in:
parent
fdfcca557b
commit
a00f411b3b
7 changed files with 114 additions and 18 deletions
|
@ -167,7 +167,8 @@ ifneq (0,$(LUNATIC))
|
|||
GAMEOBJS+= $(OBJ)/luaJIT_BC_con_lang.$o \
|
||||
$(OBJ)/luaJIT_BC_lunacon.$o \
|
||||
$(OBJ)/luaJIT_BC_geom.$o \
|
||||
$(OBJ)/luaJIT_BC_randgen.$o
|
||||
$(OBJ)/luaJIT_BC_randgen.$o \
|
||||
$(OBJ)/luaJIT_BC_stat.$o
|
||||
|
||||
# now, take care of having the necessary symbols (sector, wall, etc.) in the
|
||||
# executable no matter what the debugging level
|
||||
|
|
|
@ -547,6 +547,7 @@ local allowed_modules = {
|
|||
|
||||
randgen = require("randgen"),
|
||||
geom = require("geom"),
|
||||
stat = require("stat"),
|
||||
}
|
||||
|
||||
local package_loaded = {}
|
||||
|
|
|
@ -42,6 +42,7 @@ luaJIT_BC_lunacon;
|
|||
luaJIT_BC_con_lang;
|
||||
luaJIT_BC_geom;
|
||||
luaJIT_BC_randgen;
|
||||
luaJIT_BC_stat;
|
||||
|
||||
rand_jkiss_u32;
|
||||
rand_jkiss_dbl;
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
#!/usr/local/bin/luajit
|
||||
#!/usr/bin/env luajit
|
||||
|
||||
-- Generic map iterator.
|
||||
|
||||
|
|
|
@ -6,6 +6,10 @@ local string = require "string"
|
|||
local math = require "math"
|
||||
|
||||
local print = print
|
||||
local type = type
|
||||
|
||||
local stat = require "stat"
|
||||
|
||||
|
||||
module(...)
|
||||
|
||||
|
@ -14,37 +18,29 @@ local function printf(fmt, ...)
|
|||
print(string.format(fmt, ...))
|
||||
end
|
||||
|
||||
|
||||
local N = 0
|
||||
|
||||
local sumnumsectors = 0
|
||||
local sumnumwalls = 0
|
||||
|
||||
local sumratio = 0
|
||||
local sumsqratio = 0
|
||||
local s = stat.new()
|
||||
|
||||
function success(map, fn)
|
||||
local ns = map.numsectors
|
||||
local nw = map.numwalls
|
||||
|
||||
N = N+1
|
||||
|
||||
sumratio = sumratio + nw/ns
|
||||
sumsqratio = sumsqratio + (nw/ns)^2
|
||||
s:add(nw/ns)
|
||||
|
||||
sumnumsectors = sumnumsectors+ns
|
||||
sumnumwalls = sumnumwalls+nw
|
||||
end
|
||||
|
||||
function finish()
|
||||
printf("%d maps\n", N)
|
||||
res = s:getstats()
|
||||
|
||||
printf("%d maps\n", res.n)
|
||||
printf("total sectors: %d", sumnumsectors)
|
||||
printf("total walls: %d", sumnumwalls)
|
||||
printf("total walls / total sectors: %.02f", sumnumwalls/sumnumsectors)
|
||||
printf("")
|
||||
printf("Walls/sector")
|
||||
|
||||
local meanwpers = sumratio/N
|
||||
printf(" mean: %.02f", meanwpers)
|
||||
printf(" stdev: %.02f", math.sqrt(sumsqratio/N - meanwpers^2))
|
||||
print(res)
|
||||
end
|
||||
|
|
89
polymer/eduke32/source/lunatic/stat.lua
Normal file
89
polymer/eduke32/source/lunatic/stat.lua
Normal file
|
@ -0,0 +1,89 @@
|
|||
-- Statistics module for Lunatic.
|
||||
|
||||
local ffi = require("ffi")
|
||||
|
||||
local math = require("math")
|
||||
local string = require("string")
|
||||
|
||||
|
||||
module(...)
|
||||
|
||||
|
||||
ffi.cdef[[
|
||||
typedef struct {
|
||||
double n;
|
||||
double m, s;
|
||||
double min, max;
|
||||
} runningstat_t;
|
||||
|
||||
typedef struct {
|
||||
const double n;
|
||||
const double mean, var, std;
|
||||
const double min, max;
|
||||
} runningstat_res_t;
|
||||
]]
|
||||
|
||||
|
||||
local res_mt = {
|
||||
__tostring = function(s)
|
||||
return
|
||||
string.format("N=%d; mean=%.5g, std=%.5g; min=%.5g, max=%.5g",
|
||||
s.n, s.mean, s.std, s.min, s.max)
|
||||
end
|
||||
}
|
||||
local rstatres = ffi.metatype("runningstat_res_t", res_mt)
|
||||
|
||||
|
||||
local mt = {
|
||||
__tostring = function(s)
|
||||
-- XXX: with this and the other serializing of ffi types, take care of
|
||||
-- NaN and Infs when reading back (e.g. by "nan=0/0" in that context)
|
||||
return "stat.new("..s.n..","..s.m..","..s.s..","..s.min..","..s.max..")"
|
||||
end,
|
||||
|
||||
-- See: Accurately computing running variance, by John D. Cook
|
||||
-- http://www.johndcook.com/standard_deviation.html
|
||||
__index = {
|
||||
add = function(s, num)
|
||||
if (s.n > 0) then
|
||||
-- N>0, recurrence
|
||||
s.n = s.n+1
|
||||
|
||||
local lastm = s.m
|
||||
s.m = lastm + (num-lastm)/s.n
|
||||
s.s = s.s + (num-lastm)*(num-s.m)
|
||||
|
||||
if (num < s.min) then s.min = num end
|
||||
if (num > s.max) then s.max = num end
|
||||
else
|
||||
-- N==0, initialization
|
||||
s.n = 1
|
||||
|
||||
s.m = num
|
||||
s.s = 0
|
||||
|
||||
s.min = num
|
||||
s.max = num
|
||||
end
|
||||
end,
|
||||
|
||||
getstats = function(s)
|
||||
local var = s.n > 1 and s.s/(s.n-1) or 0/0
|
||||
return rstatres(s.n, s.m, var, math.sqrt(var), s.min, s.max)
|
||||
end,
|
||||
},
|
||||
}
|
||||
local rstat = ffi.metatype("runningstat_t", mt)
|
||||
|
||||
function new(n,m,s, min,max)
|
||||
if (n == nil) then
|
||||
-- initialization containing no elements
|
||||
return rstat(0, 0, 0/0, 0/0, 0/0)
|
||||
elseif (m == nil) then
|
||||
-- same as initialization with N==0 above (one element)
|
||||
return rstat(1, n, 0, n, n)
|
||||
else
|
||||
-- generic initialization (internal use only)
|
||||
return rstat(n,m,s, min,max)
|
||||
end
|
||||
end
|
|
@ -229,6 +229,9 @@ gameevent(gv.EVENT_ENTERLEVEL,
|
|||
end
|
||||
)
|
||||
|
||||
local stat = require("stat")
|
||||
local hs = stat.new()
|
||||
|
||||
gameactor(1680, -- LIZTROOP
|
||||
function(i, playeri, dist)
|
||||
sprite[i].pal = math.random(32)
|
||||
|
@ -239,8 +242,13 @@ gameactor(1680, -- LIZTROOP
|
|||
local x,y,z = spr.x, spr.y, spr.z
|
||||
local t = gv.gethitickms()
|
||||
local hit = hitscan(x,y,z, spr.sectnum, 10, 10, 0, gv.CLIPMASK0)
|
||||
printf("hitscan took %.03f us, sec=%d, wal=%d, spr=%d", 1000*(gv.gethitickms()-t),
|
||||
hit.hitsect, hit.hitwall, hit.hitsprite)
|
||||
|
||||
hs:add(1000*(gv.gethitickms()-t))
|
||||
|
||||
if (hs.n == 300) then
|
||||
printf("hitscan: %s", tostring(hs:getstats()))
|
||||
hs = stat.new()
|
||||
end
|
||||
end
|
||||
)
|
||||
|
||||
|
|
Loading…
Reference in a new issue