EinsDreiDreiSieben/mods/futil/util/math.lua

162 lines
2.5 KiB
Lua

futil.math = {}
local floor = math.floor
local huge = math.huge
local max = math.max
local min = math.min
function futil.math.idiv(a, b)
local rem = a % b
return (a - rem) / b, rem
end
function futil.math.bound(m, v, M)
return max(m, min(v, M))
end
function futil.math.in_bounds(m, v, M)
return m <= v and v <= M
end
local in_bounds = futil.math.in_bounds
function futil.math.is_integer(v)
return floor(v) == v
end
local is_integer = futil.math.is_integer
function futil.math.is_u8(i)
return (type(i) == "number" and is_integer(i) and in_bounds(0, i, 0xFF))
end
function futil.math.is_u16(i)
return (type(i) == "number" and is_integer(i) and in_bounds(0, i, 0xFFFF))
end
function futil.math.sum(t, initial)
local sum
local start
if initial then
sum = initial
start = 1
else
sum = t[1]
start = 2
end
for i = start, #t do
sum = sum + t[i]
end
return sum
end
function futil.math.isum(i, initial)
local sum
if initial == nil then
sum = i()
else
sum = initial
end
local v = i()
while v do
sum = sum + v
v = i()
end
return sum
end
function futil.math.product(t, initial)
local product
local start
if initial then
product = initial
start = 1
else
product = t[1]
start = 2
end
for i = start, #t do
product = product * t[i]
end
return product
end
function futil.math.iproduct(i, initial)
local product
if initial == nil then
product = i()
else
product = initial
end
local v = i()
while v do
product = product * v
v = i()
end
return product
end
function futil.math.probabilistic_round(v)
return floor(v + math.random())
end
function futil.math.cmp(a, b)
return a < b
end
futil.math.deg2rad = math.deg
futil.math.rad2deg = math.rad
function futil.math.do_intervals_overlap(min1, max1, min2, max2)
return min1 <= max2 and min2 <= max1
end
-- i took one class from kahan and can't stop doing this
local function round(n)
local d = n % 1
local i = n - d
if i % 2 == 0 then
if d <= 0.5 then
return i
else
return i + 1
end
else
if d < 0.5 then
return i
else
return i + 1
end
end
end
function futil.math.round(number, mult)
if mult then
return round(number / mult) * mult
else
return round(number)
end
end
-- TODO this doesn't handle out-of-bounds exponents
function futil.math.to_float32(number)
if number == huge or number == -huge or number ~= number then
return number
end
local sign, significand, exponent = ("%a"):format(number):match("^(-?)0x([0-9a-f\\.]+)p([0-9+-]+)$")
return tonumber(("%s0x%sp%s"):format(sign, significand:sub(1, 8), exponent))
end