Bastion aims to serve as a highly performant, simplisitic, and expandable World of Warcraft data visualization framework.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
Bastion/scripts/Libraries/Math.lua

121 lines
5.3 KiB

local Tinkr, Bastion = ...
local NAN = math.huge * 0
local IS_NAN_GT_INF = (NAN or 0 ) > math.huge
local NAN_STR = tostring(NAN)
Bastion:RegisterLibrary(Bastion.Library:New({
name = 'Math',
exports = {
default = function(self) -- Function exports are called when the library is loaded
-- Return default first, and then the remaining exports
local Math = {}
Math.__index = Math
---Returns NAN
---@return number
function Math.GetNan()
assert(NAN)
return NAN
end
---checks if a value is NAN
---@param value number
---@return boolean @whether or not the value is NAN
function Math.IsNan(value)
if not NAN then error("NAN not set") end
if IS_NAN_GT_INF then
-- if NAN > math.huge (which it is in Wow's version of lua)
return value > math.huge and tostring(value) == NAN_STR
else
return tostring(value) == NAN_STR
end
end
---Rounds a number to the nearest significant value
---@param value number The number to be rounded
---@param sig number The value to round to the nearest multiple of (defaults to 1)
---@return number
function Math.Round(value, sig)
sig = sig or 1
return math.floor((value / sig) + 0.5) * sig
end
---Rounds a value down to a specified significant value.
---@param value number The number to be rounded
---@param sig? number The value to round down to the nearest multiple of (defaults to 1)
---@return number
function Math.Floor(value, sig)
sig = sig or 1
return math.floor(value / sig) * sig
end
---Rounds a value up to a specified significant value.
---@param value number The number to be rounded
---@param sig? number The value to round up to the nearest multiple of (defaults to 1)
---@return number
function Math.Ceil(value, sig)
sig = sig or 1
return math.ceil(value / sig) * sig
end
---Scales a value from one range to another.
---@param value number The number to be scaled
---@param fromStart number The start value of the range to scale from
---@param fromEnd number The end value of the range to scale from (can be less than fromStart)
---@param toStart number The start value of the range to scale to
---@param toEnd number The end value of the range to scale to (can be less than toStart)
---@return number
function Math.Scale(value, fromStart, fromEnd, toStart, toEnd)
assert(value >= math.min(fromStart, fromEnd) and value <= math.max(fromStart, fromEnd))
return toStart + ((value - fromStart) / (fromEnd - fromStart)) * (toEnd - toStart)
end
---Bounds a number between a min and max value.
---@param value number The number to be bounded
---@param minValue number The min value
---@param maxValue number The max value
---@return number
function Math.Bound(value, minValue, maxValue)
return math.min(math.max(value, minValue), maxValue)
end
---This code is a method that generates a random number within a given range.
---It ensures that there are at least 50 possible choices by making multiple copies of the range if necessary.
--- It also allows for the number to be divided by a specified divisor for decimals
---@param lowRange number The low end of the range
---@param highRange number The high end of the range
---@param divisor? number The divisor to divide the number by
---@return number
function Math.RandomNumberGenerator(lowRange, highRange, divisor)
local lowNum, highNum
divisor = divisor or 1
if not highRange then
highNum = lowRange
lowNum = 1
else
lowNum = lowRange
highNum = highRange
end
local total = 1
if math.abs(highNum - lowNum + 1) < 50 then -- if total values is less than 50
total = math.modf(50/math.abs(highNum - lowNum + 1)) -- make x copies required to be above 50
end
local choices = {}
for i = 1, total do -- iterate required number of times
for x = lowNum, highNum do -- iterate between the range
choices[#choices +1] = x -- add each entry to a table
end
end
local rtnVal = math.random(#choices) -- will now do a math.random of at least 50 choices
for i = 1, 10 do
rtnVal = math.random(#choices) -- iterate a few times for random randomness
end
return choices[rtnVal] / divisor
end
return Math
end
}
}))