Добавлен , опубликован
Способ реализации:
Lua
Версия Warcraft:

Расширенная библиотека математики


Введение

Данная библиотека math расширяет возможности текущей версии одноименной библиотеки в Warcraft 3 reforged. Расширение на данный момент добавляет два модуля math.special и math.random. Предупреждение: math.random теперь таблица, но она может использоваться как функция, так как на нее установлена метатаблица равномерного распределения Последние изменения библиотеки можно найти на связанном git репозитории.

Модуль special

Краткое описание модуля

Модуль реализует некоторые специальные функции
  • Факториал
  • Гамма функция Римана
  • Логарифм гамма функции
  • Функция ошибок
  • Бета функция Римана

Текущий программный интерфейс (API) модуля special

do
    local special = math.special
    function special.factorial(n) end
    function special.gamma(x) end
    function special.loggamma(k) end
    function special.erf(x) end
    function special.beta(a, b) end
end

Исходный код модуля

math.special (release 16.09.2024)
math.special = math.special or {}
do
    local special = math.special

    function special.factorial(n)
        if n % 1 ~= 0 then return nil end
        if n == 0 or n == 1 then return 1 end
        return n*factorial(n-1)  
    end
    
    -- используем приближение Ланцоша
    function special.gamma(x)
        local g = 7
        local p = {
            0.99999999999980993,
            676.5203681218851,
           -1259.1392167224028,
            771.32342877765313,
           -176.61502916214059,
            12.507343278686905,
           -0.13857109526572012,
            9.9843695780195716e-6,
            1.5056327351493116e-7
        }
    
        if x < 0.5 then
            -- Формула дополнения
            return math.pi / (math.sin(math.pi * x) * special.gamma(1 - x))
        else
            x = x - 1
            local a = p[1]
            for i = 2, #p do
                a = a + p[i] / (x + i - 1)
            end
            local t = x + g + 0.5
            return math.sqrt(2 * math.pi) * t^(x + 0.5) * math.exp(-t) * a
        end
    end
    
        
   -- Функция для вычисления логарифма гамма-функции
    function special.loggamma(k)
        -- Для целых значений k используем приближение Стирлинга
        if k < 8 then
            -- Прямое вычисление для небольших k
            local res = 0
            for i = 2, k do
                res = res + math.log(i)
            end
            return res
        else
            -- Приближение Стирлинга
            local k_float = k
            local term1 = (k_float + 0.5) * math.log(k_float)
            local term2 = -k_float + 0.5 * math.log(2 * math.pi)
            local term3 = 1 / (12 * k_float)
            return term1 + term2 + term3
        end
    end
    
        -- Функция erf(x)
    function special.erf(x)
        -- Константы
        local a1 =  0.254829592
        local a2 = -0.284496736
        local a3 =  1.421413741
        local a4 = -1.453152027
        local a5 =  1.061405429
        local p  =  0.3275911
    
        -- Сохранение знака x
        local sign = 1
        if x < 0 then
            sign = -1
        end
        x = math.abs(x)
    
        -- Вычисление по формуле
        local t = 1.0 / (1.0 + p * x)
        local y = 1.0 - (((((a5 * t + a4) * t + a3) * t + a2) * t + a1) * t) * math.exp(-x * x)
    
        return sign * y
    end

    
    -- Функция beta(a, b)
    function special.beta(a, b)
        return math.exp(special.loggamma(a) + special.loggamma(b) - special.loggamma(a + b))
    end
    
end

Модуль random

Краткое описание модуля

Модуль позволяет генерировать случайные величины следующих распределений
  • Равномерное (хук из math.random)
  • Пуссоновское (rewrite реализации ptrs на c++ для numpy под lua)
  • Экспоненциальное (метод обратной функции)
  • Нормальное (метод Бокса-Мюллера)

Текущий программный интерфейс (API) модуля random

-- хук из старого math.random
function math.random() end
-- 
function math.random.uniform(...) end
function math.random.poisson(lambda) end
function math.random.exponential(lambda) end
function math.random.normal(mean, std) end

Исходный код модуля random

math.random (release 16.09.24)
do -- reqire "math.special"
    local uniform = {}
    uniform.rvs = (type(math.random) == "function") and math.random or math.uniform.rvs
    
    local random = {
      uniform = uniform,
      poisson = {},
      exponential = {},
      normal = {}
    }
    setmetatable(random, {__call = function(tbl,...) return random.uniform.rvs(...) end})
    
    local meta_distr = {
      __call = function(distr,...)
          return distr.rvs(...)
      end
    }
  
    for key, val in pairs(random) do
        setmetatable(val, meta_distr)
    end
    
    math.random = random
end


do -- poisson distribution
    local poisson = math.random.poisson
    local loggamma = math.special.loggamma
  
    function poisson.ptrs(lam)
      local slam = math.sqrt(lam)
      local loglam = math.log(lam)
      local b = 0.931 + 2.53 * slam
      local a = -0.059 + 0.02483 * b
      local invalpha = 1.1239 + 1.1328 / (b - 3.4)
      local vr = 0.9277 - 3.6224 / (b - 2)
      
      while true do
          local U = math.random() - 0.5
          local V = math.random()
          local us = 0.5 - math.abs(U)
          local k = math.floor((2 * a / us + b) * U + lam + 0.43)
          if (us >= 0.07) and (V <= vr) then
              return k
          end
          if (k < 0) or ((us < 0.013) and (V > us)) then
              -- Переходим к следующей итерации цикла
          else
              local lhs = math.log(V) + math.log(invalpha) - math.log(a / (us * us) + b)
              local rhs = -lam + k * loglam - loggamma(k + 1)
              if lhs <= rhs then
                  return k
              end
          end
        end
    end
    
    poisson.rvs = function(lambda) 
        return poisson.ptrs(lambda)
    end 
end

do -- exponential distribution
    local exponential = math.random.exponential
    
    function exponential.standart(lambda)
        local u = math.random()
        return - math.log(u) * lambda
    end
    
    exponential.rvs = function(lambda) 
        return exponential.standart(lambda)
    end
end


do -- normal distrebution
    local normal = math.random.normal
    
    function normal.box_muller()
        local u1 = math.random()
        local u2 = math.random()
        return math.sqrt(-2 * math.log(u1)) * math.cos(2 * math.pi * u2)
    end
    
    function normal.rvs(mean, std)
        mean = mean or 0
        std = std or 1
        return normal.box_muller()*std + mean 
    end
    
end

Заключение

Данный репозиторий я создал в основном для себя но ресурс с желанием поделиться наработками. Надеюсь на фидбек. Было бы интересно узнать о полезности данного репозитория для комьюнити. Может есть уже готовые работы, которые можно непосредственно внедрить в warcraft 3. Также было бы интересно узнать какие функции стоило бы еще внедрить в свою библиотеку.

Источники

Использованные источники

  • [1] - статья про то какие бывают алгоритмы пуассоновского распределения и какие используются в какой мат. системе.
  • [2] - ссылка на git репозиторий c данным проектом

Полезные источники

  • lua-set github.com/wscherphof/lua-set/tree/master
  • LuaSortingAlgorithms (github.com/DervexDev/LuaSortingAlgorithms) -
    репозиторий конвертированных из python алгоритмов сортировки.
  • cheapack - совсем не дешевый упаковщик *.lua файлов в *.wct файл Warcraft 3.
  • imp-lua-mm
  • luaforwindows -
    репозиторий хранящий Lua.exe файл для windows
  • lua-table - база функций расширяющих стандартный набор
    table c добавлением дополнительных свойств.
  • t-util - база функций расширяющих стандартный набор.
  • xlua - база функций расширяющих стандартный набор.
  • table-manual - официальный мануал по таблицам
`
ОЖИДАНИЕ РЕКЛАМЫ...
Этот комментарий удален
23
Ваш ресурс не прошёл автомодерацию. Пожалуйста, внесите исправления или ожидайте проверки модератором.
Причина
Подозрение в нарушении правил сайта. Требуется валидация человеком.
Your resource has not passed automoderation. Please make corrections or wait for the moderator to check.
Reason
Suspicion of violating site rules. Human validation required.
// CID0
30
Тоже делал свой рандом. В твоём рандоме можно делать инстансы со своим зерном?
Ответы (9)
11
nazarpunk, да не, я просто хотел пуассоновское распределение хорошее, заметил, что его генерация не такая простая задача, если делать оптимально. Ну и вдовесок закинул еще распределений на будущее. Если ты имеешь в виду генератор свой, то очень хороший источник тут.
11
nazarpunk, ааа посмотрел, у тебя тоже Twister как понимаю. А вообще имеет смысл свой алгоритм генерации внедрять? Хороший алгоритм нашел тут
11
nazarpunk, я сразу код смотрел, не читал статью. Мне показался похожим на этот алгоритм. Ошибся получается.
11
nazarpunk, точно, закинул в нейронку, попросил проанализировать. Правда в дешовую. Нейронка подороже мне ответила что:
GPT o1-Mini: Данный код реализует линейный конгруэнтный генератор (Linear Congruential Generator, LCG) с параметрами из ANSI C, а не алгоритм Mersenne Twister.
11
nazarpunk, по другой ссылке крипто метод на пайтоне. Вот это интересно было бы реализовать.
30
cheapack - совсем не дешевый упаковщик *.lua файлов в *.wct файл Warcraft 3.
Почему он не дешёвый, коль не секрет?
Ответы (1)
11
nazarpunk, потому что полезный. Его польза перекрывает его дешивизну. Поэтому мне кажется унизительно для него назвать его дешевым. ;D
Чтобы оставить комментарий, пожалуйста, войдите на сайт.