Skip to content

Instantly share code, notes, and snippets.

@CaptainPRICE
Last active August 20, 2021 22:13
Show Gist options
  • Save CaptainPRICE/342303bba104354257db0471bf996bd3 to your computer and use it in GitHub Desktop.
Save CaptainPRICE/342303bba104354257db0471bf996bd3 to your computer and use it in GitHub Desktop.
math.finite, math.isinf & math.isnan functions in pure Lua. Completely covered (all tests passed). https://i.imgur.com/1vzo2x9.png
local NAN = 0.0 / 0.0
local NINF = -math.huge
local PINF = math.huge
--- Returns true if given value is a finite number; otherwise false or nil if value is not of type string nor number.
function math.finite(value)
if type(value) == "string" then
value = tonumber(value)
if value == nil then return nil end
elseif type(value) ~= "number" then
return nil
end
return value > NINF and value < PINF
end
--- Returns 1 if given value is a positive infinity or -1 if given value is a negative infinity; otherwise 0 or nil if value is not of type string nor number.
function math.isinf(value)
if type(value) == "string" then
value = tonumber(value)
if value == nil then return nil end
elseif type(value) ~= "number" then
return nil
end
if value == PINF then return 1 end
if value == NINF then return -1 end
return 0
end
--- Returns true if given value is not a number (NaN); otherwise false or nil if value is not of type string nor number.
function math.isnan(value)
if type(value) == "string" then
value = tonumber(value)
if value == nil then return nil end
elseif type(value) ~= "number" then
return nil
end
return value ~= value
end
--
-- Unit tests.
--
local tests_index = {
"Finite_1",
"Finite_2",
"Finite_3",
"Finite_4",
"Finite_5",
"Finite_6",
"Infinity_1",
"Infinity_2",
"Infinity_3",
"Infinity_4",
"Infinity_5",
"Infinity_6",
"NaN_1",
"NaN_2",
"NaN_3",
"NaN_4",
"NaN_5",
"NaN_6",
}
local tests = {
Finite_1 = function() return math.finite(PINF) == false end,
Finite_2 = function() return math.finite(NINF) == false end,
Finite_3 = function() return math.finite(NAN) == false end,
Finite_4 = function() return math.finite(math.random(10000000000000.0, 10000000000000.0)) == true end,
Finite_5 = function() return math.finite("invalid number") == nil end,
Finite_6 = function() return math.finite("123456789") == true end,
Infinity_1 = function() return math.isinf(PINF) == 1 end,
Infinity_2 = function() return math.isinf(NINF) == -1 end,
Infinity_3 = function() return math.isinf(NAN) == 0 end,
Infinity_4 = function() return math.isinf(math.random(10000000000000.0, 10000000000000.0)) == 0 end,
Infinity_5 = function() return math.isinf("invalid number") == nil end,
Infinity_6 = function() return math.isinf("123456789") == 0 end,
NaN_1 = function() return math.isnan(PINF) == false end,
NaN_2 = function() return math.isnan(NINF) == false end,
NaN_3 = function() return math.isnan(NAN) == true end,
NaN_4 = function() return math.isnan(math.random(10000000000000.0, 10000000000000.0)) == false end,
NaN_5 = function() return math.isnan("invalid number") == nil end,
NaN_6 = function() return math.isnan("123456789") == false end,
}
local pass_count, fail_count, total_count = 0, 0, 0
for _, test_name in ipairs(tests_index) do
local test_func = tests[test_name]
total_count = total_count + 1
test_name = test_name:gsub("_", " ")
local test_result = test_func()
if test_result then
pass_count = pass_count + 1
else
fail_count = fail_count + 1
end
local test_result_text = test_result and "Test passed." or "Test FAILED!!!"
print("[" .. os.date("%d-%m-%Y %H:%M:%S") .. "] [" .. ("%0" .. tostring(#tests_index):len() .. ".0f"):format(total_count) .. "] " .. test_name .. ": " .. test_result_text)
end
print("-----------------------------------")
print("Total: " .. total_count .. " tests.")
print("Passed: " .. pass_count .. " / " .. total_count .. " (" .. ("%.2f"):format((pass_count / total_count) * 100.0) .. "% covered).")
print("Failed: " .. fail_count .. " / " .. total_count .. " (" .. ("%.2f"):format((fail_count / total_count) * 100.0) .. "% not covered).")
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment