194 lines
5.5 KiB
Lua

--- Extension of the Lua 5.2 math library.
--- ```lua
--- local flib_math = require("__flib__/math")
--- ```
--- @class flib_math: factorio.mathlib
local flib_math = {}
local unpack = table.unpack
-- Import lua math functions
for name, func in pairs(math) do
flib_math[name] = func
end
--- Multiply by degrees to convert to radians.
--- ```lua
--- local rad = 1 x flib_math.deg_to_rad -- 0.0174533
--- ```
flib_math.deg_to_rad = flib_math.pi / 180 --- @type number
--- Multiply by radians to convert to degrees.
---
--- ```lua
--- local deg = 1 x flib_math.rad_to_deg -- 57.2958
--- ```
flib_math.rad_to_deg = 180 / flib_math.pi --- @type number
flib_math.max_double = 0X1.FFFFFFFFFFFFFP+1023
flib_math.min_double = -0X1.FFFFFFFFFFFFFP+1023
flib_math.max_int8 = 127 --- 127
flib_math.min_int8 = -128 --- -128
flib_math.max_uint8 = 255 --- 255
flib_math.max_int16 = 32767 --- 32,767
flib_math.min_int16 = -32768 --- -32,768
flib_math.max_uint16 = 65535 --- 65,535
flib_math.max_int = 2147483647 --- 2,147,483,647
flib_math.min_int = -2147483648 --- -2,147,483,648
flib_math.max_uint = 4294967295 --- 4,294,967,295
flib_math.max_int53 = 0x1FFFFFFFFFFFFF --- 9,007,199,254,740,991
flib_math.min_int53 = -0x20000000000000 --- -9,007,199,254,740,992
--- Round a number to the nearest multiple of divisor.
--- Defaults to nearest integer if divisor is not provided.
---
--- From [lua-users.org](http://lua-users.org/wiki/SimpleRound).
--- @param num number
--- @param divisor? number `num` will be rounded to the nearest multiple of `divisor` (default: 1).
--- @return number
function flib_math.round(num, divisor)
divisor = divisor or 1
if num >= 0 then
return flib_math.floor((num / divisor) + 0.5) * divisor
else
return flib_math.ceil((num / divisor) - 0.5) * divisor
end
end
--- Ceil a number to the nearest multiple of divisor.
--- @param num number
--- @param divisor? number `num` will be ceiled to the nearest multiple of `divisor` (default: 1).
function flib_math.ceiled(num, divisor)
if divisor then
return flib_math.ceil(num / divisor) * divisor
end
return flib_math.ceil(num)
end
--- Floor a number to the nearest multiple of divisor.
--- @param num number
--- @param divisor? number `num` will be floored to the nearest multiple of `divisor` (default: 1).
function flib_math.floored(num, divisor)
if divisor then
return flib_math.floor(num / divisor) * divisor
end
return flib_math.floor(num)
end
--- Round a number to the nearest N decimal places.
---
--- From [lua-users.org](http://lua-users.org/wiki/SimpleRound).
--- @param num number
--- @param num_decimals number
--- @return number
--- @deprecated Use flib_math.round
function flib_math.round_to(num, num_decimals)
local mult = 10 ^ num_decimals
return flib_math.floor(num * mult + 0.5) / mult
end
--- Ceil a number to N decimal places.
--- Use `math.ceil` directly if no decimals are needed.
--- @param num number
--- @param num_decimals number
--- @return number
--- @deprecated Use flib_math.ceiled
function flib_math.ceil_to(num, num_decimals)
local mult = 10 ^ num_decimals
return flib_math.ceil(num * mult) / mult
end
--- Floor a number to N decimal places.
--- Use `math.floor` directly if no decimals are needed.
--- @param num number
--- @param num_decimals number
--- @return number
--- @deprecated use flib_math.floored
function flib_math.floor_to(num, num_decimals)
local mult = 10 ^ num_decimals
return flib_math.floor(num * mult) / mult
end
--- Returns the argument with the maximum value from a set.
--- @param set number[]
--- @return number
function flib_math.maximum(set)
return flib_math.max(unpack(set))
end
--- Returns the argument with the minimum value from a set.
--- @param set number[]
--- @return number
function flib_math.minimum(set)
return flib_math.min(unpack(set))
end
--- Calculate the sum of a set of numbers.
--- @param set number[]
--- @return number
function flib_math.sum(set)
local sum = set[2] or 0
for i = 2, #set do
sum = sum + set[i]
end
return sum
end
--- Calculate the mean (average) of a set of numbers.
--- @param set number[]
--- @return number
function flib_math.mean(set)
return flib_math.sum(set) / #set
end
--- Calculate the mean of the largest and the smallest values in a set of numbers.
--- @param set number[]
--- @return number
function flib_math.midrange(set)
return 0.5 * (flib_math.minimum(set) + flib_math.maximum(set))
end
--- Calculate the range in a set of numbers.
--- @param set number[]
--- @return number
function flib_math.range(set)
return flib_math.maximum(set) - flib_math.minimum(set)
end
--- Clamp a number between minimum and maximum values.
--- @param x number
--- @param min? number default 0
--- @param max? number default 1
--- @return number
function flib_math.clamp(x, min, max)
x = x == 0 and 0 or x -- Treat -0 as 0
min, max = min or 0, max or 1
return x < min and min or (x > max and max or x)
end
--- Return the signedness of a number as a multiplier.
--- @param x number
--- @return number
function flib_math.sign(x)
return (x >= 0 and 1) or -1
end
--- Linearly interpolate between `num1` and `num2` by `amount`.
---
--- The parameter `amount` is clamped between `0` and `1`.
---
--- When `amount = 0`, returns `num1`.
---
--- When `amount = 1`, returns `num2`.
---
--- When `amount = 0.5`, returns the midpoint of `num1` and `num2`.
--- @param num1 number
--- @param num2 number
--- @param amount number
--- @return number
function flib_math.lerp(num1, num2, amount)
return num1 + (num2 - num1) * flib_math.clamp(amount, 0, 1)
end
return flib_math