I was transferring my game’s currency system to use Quicknum and I found a few bugs in the library in the process, specifically related to comparison functions (lt, gt, lte, gte, etc.)
I used AI to fix all the issues, but I’d still like to let you know if it missed anything.
Updated functions that had an issue:
--[[
n1 < n2
]]
function num.lt(n1, n2)
local m1, e1, m2, e2
-- Extraction logic for Input 1
if type(n1) == "buffer" then
m1 = buffer.readf64(n1, 0)
e1 = buffer.readf64(n1, 8)
elseif type(n1) == "number" then
m1, e1 = math.frexp(n1)
else
error("Wrong Type: lt(), Input 1")
end
-- Extraction logic for Input 2
if type(n2) == "buffer" then
m2 = buffer.readf64(n2, 0)
e2 = buffer.readf64(n2, 8)
elseif type(n2) == "number" then
m2, e2 = math.frexp(n2)
else
error("Wrong Type: lt(), Input 2")
end
local sign1 = math.sign(m1)
local sign2 = math.sign(m2)
-- 1. Compare Signs
if sign1 ~= sign2 then
return sign1 < sign2
end
-- 2. Handle Zero
if sign1 == 0 then return false end
-- 3. Compare Magnitudes based on Sign
if sign1 > 0 then
-- Both Positive: Lower exponent or lower mantissa is smaller
if e1 ~= e2 then
return e1 < e2
else
return m1 < m2
end
else
-- Both Negative: Higher exponent or lower mantissa is smaller
if e1 ~= e2 then
return e1 > e2
else
return m1 < m2
end
end
end
--[[
n1 <= n2
]]
function num.lte(n1, n2)
local m1, e1, m2, e2
-- Extraction logic for Input 1
if type(n1) == "buffer" then
m1 = buffer.readf64(n1, 0)
e1 = buffer.readf64(n1, 8)
elseif type(n1) == "number" then
m1, e1 = math.frexp(n1)
else
error("Wrong Type: lte(), Input 1")
end
-- Extraction logic for Input 2
if type(n2) == "buffer" then
m2 = buffer.readf64(n2, 0)
e2 = buffer.readf64(n2, 8)
elseif type(n2) == "number" then
m2, e2 = math.frexp(n2)
else
error("Wrong Type: lte(), Input 2")
end
local sign1 = math.sign(m1)
local sign2 = math.sign(m2) -- Fixed typo: changed m1 to m2
-- 1. Compare Signs
if sign1 ~= sign2 then
return sign1 < sign2
end
-- 2. Handle Zero (Both are 0)
if sign1 == 0 then return true end
-- 3. Compare Magnitudes based on Sign
if sign1 > 0 then
-- Both Positive
if e1 ~= e2 then
return e1 < e2
else
return m1 <= m2 -- Fixed: compare extracted mantissas, not buffers
end
else
-- Both Negative
if e1 ~= e2 then
-- A larger negative exponent means a smaller number
return e1 > e2
else
return m1 <= m2 -- Both negative, so smaller (more negative) mantissa is smaller
end
end
end
--[[
n1 > n2
]]
function num.gt(n1, n2)
local m1, e1, m2, e2
-- Extraction logic for Input 1
if type(n1) == "buffer" then
m1 = buffer.readf64(n1, 0)
e1 = buffer.readf64(n1, 8)
elseif type(n1) == "number" then
m1, e1 = math.frexp(n1)
else
error("Wrong Type: gt(), Input 1")
end
-- Extraction logic for Input 2
if type(n2) == "buffer" then
m2 = buffer.readf64(n2, 0)
e2 = buffer.readf64(n2, 8)
elseif type(n2) == "number" then
m2, e2 = math.frexp(n2)
else
error("Wrong Type: gt(), Input 2")
end
local sign1 = math.sign(m1)
local sign2 = math.sign(m2) -- Fixed typo: changed m1 to m2
-- 1. Compare Signs
if sign1 ~= sign2 then
return sign1 > sign2
end
-- 2. Handle Zero (Both are 0)
if sign1 == 0 then return false end
-- 3. Compare Magnitudes based on Sign
if sign1 > 0 then
-- Both Positive: Larger exponent or larger mantissa is greater
if e1 ~= e2 then
return e1 > e2
else
return m1 > m2
end
else
-- Both Negative: Smaller exponent or larger mantissa is greater
-- (Example: -10^2 is greater than -10^5)
if e1 ~= e2 then
return e1 < e2
else
return m1 > m2
end
end
end
--[[
n1 >= n2
]]
function num.gte(n1, n2)
local m1, e1, m2, e2
-- Extraction logic for Input 1
if type(n1) == "buffer" then
m1 = buffer.readf64(n1, 0)
e1 = buffer.readf64(n1, 8)
elseif type(n1) == "number" then
m1, e1 = math.frexp(n1)
else
error("Wrong Type: gte(), Input 1")
end
-- Extraction logic for Input 2
if type(n2) == "buffer" then
m2 = buffer.readf64(n2, 0)
e2 = buffer.readf64(n2, 8)
elseif type(n2) == "number" then
m2, e2 = math.frexp(n2)
else
error("Wrong Type: gte(), Input 2")
end
local sign1 = math.sign(m1)
local sign2 = math.sign(m2) -- Fixed typo: changed m1 to m2
-- 1. Compare Signs
if sign1 ~= sign2 then
return sign1 > sign2
end
-- 2. Handle Zero (Both are 0)
if sign1 == 0 then return true end
-- 3. Compare Magnitudes based on Sign
if sign1 > 0 then
-- Both Positive: Greater exponent or greater mantissa is gte
if e1 ~= e2 then
return e1 > e2
else
return m1 >= m2
end
else
-- Both Negative: Smaller exponent or greater (closer to 0) mantissa is gte
-- (Example: -1*2^2 is greater than -1*2^5)
if e1 ~= e2 then
return e1 < e2
else
return m1 >= m2
end
end
end
--[[
n1 == n2
]]
function num.eq(n1, n2)
local m1, e1, m2, e2
-- Extraction logic for Input 1
if type(n1) == "buffer" then
m1 = buffer.readf64(n1, 0)
e1 = buffer.readf64(n1, 8)
elseif type(n1) == "number" then
m1, e1 = math.frexp(n1)
else
error("Wrong Type: eq(), Input 1")
end
-- Extraction logic for Input 2
if type(n2) == "buffer" then
m2 = buffer.readf64(n2, 0)
e2 = buffer.readf64(n2, 8)
elseif type(n2) == "number" then
m2, e2 = math.frexp(n2)
else
error("Wrong Type: eq(), Input 2")
end
-- 1. Handle Zero (Both are 0)
if m1 == 0 and m2 == 0 then
return true
end
-- 2. Compare using an Epsilon
-- This ensures that tiny rounding errors don't break your "Buy" buttons.
-- We check if exponents match and mantissas are "close enough."
return e1 == e2 and math.abs(m1 - m2) < 1e-14
end
In addition, AI also implemented hexencode and hexdecode functions.
--[[
Encodes n into hexadecimal for ultra-fast syncing and saving.
A 16-byte buffer always results in a 32-character string.
]]
function num.hexencode(n)
if type(n) ~= "buffer" then error("Wrong Type: hexencode(), Input 1") end
local m = buffer.readf64(n, 0)
local e = buffer.readf64(n, 8)
-- Optimized special cases
if m == 0 then return "0" end
if m == 0.5 and e == 1 then return "1" end
local len = buffer.len(n)
local t = table.create(len)
for i = 0, len - 1 do
local b = buffer.readu8(n, i)
local h = math.floor(b / 16)
local l = b % 16
t[i + 1] = string.sub(hex_chars, h + 1, h + 1) .. string.sub(hex_chars, l + 1, l + 1)
end
return table.concat(t)
end
--[[
Decodes from .hexencode() back into a 16-byte buffer.
]]
function num.hexdecode(s)
if type(s) ~= "string" then error("Wrong Type: hexdecode(), Input 1") end
if s == "0" then
return buffer.create(16)
elseif s == "1" then
local buf = buffer.create(16)
buffer.writef64(buf, 0, 0.5)
buffer.writef64(buf, 8, 1) -- Corrected exponent offset
return buf
end
local buf = buffer.create(16)
for i = 1, #s, 2 do
local byte_hex = string.sub(s, i, i + 1)
local byte_val = hex_to_dec[byte_hex]
if byte_val then
buffer.writeu8(buf, (i - 1) / 2, byte_val)
end
end
return buf
end