From a415cf5364d2ad1248e05bb7d7a3bda57a4a837e Mon Sep 17 00:00:00 2001 From: tenplus1 Date: Thu, 12 Sep 2024 11:21:32 +0100 Subject: [PATCH] tweak poisson functions --- hoes.lua | 13 +++------ init.lua | 6 ++--- statistics.lua | 73 ++++++++++++++++++++++---------------------------- 3 files changed, 37 insertions(+), 55 deletions(-) diff --git a/hoes.lua b/hoes.lua index 29ae2cf..e686575 100644 --- a/hoes.lua +++ b/hoes.lua @@ -251,7 +251,6 @@ local function hoe_area(pos, player) end -- replace dirt with tilled soil - res = nil res = minetest.find_nodes_in_area_under_air( {x = pos.x - r, y = pos.y - 1, z = pos.z - r}, {x = pos.x + r, y = pos.y + 2, z = pos.z + r}, @@ -318,13 +317,10 @@ minetest.register_entity("farming:hoebomb_entity", { local function throw_potion(itemstack, player) - local playerpos = player:get_pos() + local pos = player:get_pos() local obj = minetest.add_entity({ - x = playerpos.x, - y = playerpos.y + 1.5, - z = playerpos.z - }, "farming:hoebomb_entity") + x = pos.x, y = pos.y + 1.5, z = pos.z}, "farming:hoebomb_entity") if not obj then return end @@ -440,10 +436,7 @@ minetest.register_tool("farming:scythe_mithril", { if obj then obj:set_velocity({ - x = math.random(-10, 10) / 9, - y = 3, - z = math.random(-10, 10) / 9 - }) + x = math.random() - 0.5, y = 3, z = math.random() - 0.5}) end end end diff --git a/init.lua b/init.lua index 7d19dae..a562edc 100644 --- a/init.lua +++ b/init.lua @@ -17,8 +17,7 @@ farming = { select = {type = "fixed", fixed = {-0.5, -0.5, -0.5, 0.5, -5/16, 0.5}}, select_final = {type = "fixed", fixed = {-0.5, -0.5, -0.5, 0.5, -2.5/16, 0.5}}, registered_plants = {}, - min_light = 12, - max_light = 15, + min_light = 12, max_light = 15, mapgen = minetest.get_mapgen_setting("mg_name"), use_utensils = minetest.settings:get_bool("farming_use_utensils") ~= false, mtg = minetest.get_modpath("default"), @@ -59,8 +58,7 @@ end -- stats, locals, settings, function helper local statistics = dofile(farming.path .. "/statistics.lua") -local random = math.random -local floor = math.floor +local random, floor = math.random, math.floor local time_speed = tonumber(minetest.settings:get("time_speed")) or 72 local SECS_PER_CYCLE = (time_speed > 0 and (24 * 60 * 60) / time_speed) or 0 local function clamp(x, min, max) return (x < min and min) or (x > max and max) or x end diff --git a/statistics.lua b/statistics.lua index c5d5396..df12bd9 100644 --- a/statistics.lua +++ b/statistics.lua @@ -3,36 +3,36 @@ -- https://en.wikipedia.org/wiki/Error_function local statistics = {} -local ROOT_2 = math.sqrt(2.0) -local erf -local erf_inv +local random, floor, ceil = math.random, math.floor, math.ceil +local exp, log, sqrt = math.exp, math.log, math.sqrt +local ROOT_2 = sqrt(2.0) local A = 8 * (math.pi - 3.0) / (3.0 * math.pi * (4.0 - math.pi)) local B = 4.0 / math.pi local C = 2.0 / (math.pi * A) local D = 1.0 / A -erf = function(x) +local function erf(x) - if x == 0 then return 0; end + if x == 0 then return 0 end local xSq = x * x local aXSq = A * xSq - local v = math.sqrt(1.0 - math.exp(-xSq * (B + aXSq) / (1.0 + aXSq))) + local v = sqrt(1.0 - exp(-xSq * (B + aXSq) / (1.0 + aXSq))) return (x > 0 and v) or -v end -erf_inv = function(x) +local function erf_inv(x) - if x == 0 then return 0; end + if x == 0 then return 0 end - if x <= -1 or x >= 1 then return nil; end + if x <= -1 or x >= 1 then return nil end - local y = math.log(1 - x * x) + local y = log(1 - x * x) local u = C + 0.5 * y - local v = math.sqrt(math.sqrt(u * u - D * y) - u) + local v = sqrt(sqrt(u * u - D * y) - u) return (x > 0 and v) or -v end @@ -43,14 +43,10 @@ local function std_normal(u) end -local poisson -local cdf_table = {} - - local function generate_cdf(lambda_index, lambda) - local max = math.ceil(4 * lambda) - local pdf = math.exp(-lambda) + local max = ceil(4 * lambda) + local pdf = exp(-lambda) local cdf = pdf local t = { [0] = pdf } @@ -64,30 +60,32 @@ local function generate_cdf(lambda_index, lambda) end +local cdf_table = {} + for li = 1, 100 do cdf_table[li] = generate_cdf(li, 0.25 * li) end -poisson = function(lambda, max) +local function poisson(lambda, max) if max < 2 then - return (math.random() < math.exp(-lambda) and 0) or 1 + return (random() < exp(-lambda) and 0) or 1 elseif lambda >= 2 * max then return max end - local u = math.random() - local lambda_index = math.floor(4 * lambda + 0.5) + local u = random() + local lambda_index = floor(4 * lambda + 0.5) local cdfs = cdf_table[lambda_index] if cdfs then lambda = 0.25 * lambda_index - if u < cdfs[0] then return 0; end - if max > #cdfs then max = #cdfs + 1 else max = math.floor(max); end - if u >= cdfs[max - 1] then return max; end + if u < cdfs[0] then return 0 end + if max > #cdfs then max = #cdfs + 1 else max = floor(max) end + if u >= cdfs[max - 1] then return max end if max > 4 then -- Binary search @@ -95,30 +93,27 @@ poisson = function(lambda, max) while s + 1 < max do - local m = math.floor(0.5 * (s + max)) + local m = floor(0.5 * (s + max)) - if u < cdfs[m] then max = m; else s = m; end + if u < cdfs[m] then max = m else s = m end end else for i = 1, max - 1 do - if u < cdfs[i] then return i; end + if u < cdfs[i] then return i end end end return max else - local x = lambda + math.sqrt(lambda) * std_normal(u) + local x = lambda + sqrt(lambda) * std_normal(u) - return (x < 0.5 and 0) or (x >= max - 0.5 and max) or math.floor(x + 0.5) + return (x < 0.5 and 0) or (x >= max - 0.5 and max) or floor(x + 0.5) end end --- Error function. +-- Error and Inverse error functions statistics.erf = erf - --- Inverse error function. - statistics.erf_inv = erf_inv --- Standard normal distribution function (mean 0, standard deviation 1). @@ -126,13 +121,9 @@ statistics.erf_inv = erf_inv statistics.std_normal = function() - local u = math.random() + local u = random() - if u < 0.001 then - return -3.0 - elseif u > 0.999 then - return 3.0 - end + if u < 0.001 then return -3.0 elseif u > 0.999 then return 3.0 end return std_normal(u) end @@ -144,7 +135,7 @@ end statistics.normal = function(mu, sigma) - local u = math.random() + local u = random() if u < 0.001 then return mu - 3.0 * sigma @@ -164,7 +155,7 @@ statistics.poisson = function(lambda, max) lambda, max = tonumber(lambda), tonumber(max) - if not lambda or not max or lambda <= 0 or max < 1 then return 0; end + if not lambda or not max or lambda <= 0 or max < 1 then return 0 end return poisson(lambda, max) end