Skip to content

Instantly share code, notes, and snippets.

@incinirate
Last active November 5, 2018 05:21
Show Gist options
  • Save incinirate/0b11ee7453eb32dde8500109ae88b339 to your computer and use it in GitHub Desktop.
Save incinirate/0b11ee7453eb32dde8500109ae88b339 to your computer and use it in GitHub Desktop.
Floating Point visualization for Riko4 (rlua)
local exp = 5
local frac = 3
local args = {...}
if args[1] then exp = tonumber(args[1]) end
if args[2] then frac = tonumber(args[2]) end
local bits = {0}
for i = 1, exp do
bits[i + 1] = 0
end
for i = 1, frac do
bits[#bits + 1] = 0
end
local cursor = 1
local function getExp()
local bias = (2^(exp - 1)) - 1
local pos = exp + 1
local val = 0
local normal = false
for i = 1, exp do
if bits[pos] == 1 then
val = val + 2^(i - 1)
normal = true
end
pos = pos - 1
end
val = val - bias
if normal then
return val
else
return 1 - bias
end
end
local function isInf()
for i = 1, exp do
if bits[i + 1] == 0 then
return false
end
end
for i = 1, frac do
if bits[i + exp + 1] == 1 then
return "nan"
end
end
return true
end
local function normal()
for i = 1, exp do
if bits[i + 1] == 1 then
return true
end
end
return false
end
local function isZero()
for i = 2, #bits do
if bits[i] == 1 then
return false
end
end
return true
end
local function gcd(x, y)
if x == y then return x end
if x == 0 then return y end
if y == 0 then return x end
if x % 2 == 0 then
if y % 2 == 1 then
return gcd(x / 2, y)
else
return gcd(x / 2, y / 2) * 2
end
end
if y % 2 == 0 then
return gcd(x, y / 2)
end
if x > y then
return gcd((x - y) / 2, y)
end
return gcd((y - x) / 2, x)
end
local function reduce(n, d)
if n % d == 0 then
return n / d
end
local div = gcd(n, d)
return n / div, d / div
end
local function drawBreakdown(y, pass, stn, std)
local cx, cy = write("= " .. (bits[1] == 1 and "-" or "+"), 4, y, 16)
local ival = isInf()
if ival == true then
cx = write("inf", cx, cy, 11)
elseif ival == "nan" then
cx = write("nan", cx, cy, 11)
elseif pass == 1 and isZero() then
cx = write("0", cx, cy, 16)
elseif pass == 2 then
local v = getExp()
local top, bot
if v >= 0 then
cx = write(tostring(2^v), cx, cy, 11)
top, bot = 2^v, 1
else
cx = write("1/" .. 2^(-v), cx, cy, 11)
top, bot = 1, 2^(-v)
end
if not std then
cx = write(" * " .. stn, cx, cy, 8)
local nx, ny = reduce(stn * top, bot)
drawBreakdown(y + 12, 3, nx, ny)
else
cx = write(" * " .. stn .. "/" .. std, cx, cy, 8)
local nx, ny = reduce(stn * top, std * bot)
drawBreakdown(y + 12, 3, nx, ny)
end
elseif pass == 3 then
if std then
cx = write(stn .. "/" .. std, cx, cy, 13)
else
cx = write(stn, cx, cy, 13)
end
else
cx = write("2^" .. getExp(), cx, cy, 11)
local sig = normal() and {1} or {}
local fval = normal() and "1/1" or "0"
for i = 1, frac do
if bits[1 + exp + i] == 1 then
fval = fval .. " + 1/" .. (2^i)
sig[#sig + 1] = 2^i
end
end
if pass == 1 then
local denom = sig[#sig]
local num = 0
for i = 1, #sig do
num = num + denom/sig[i]
end
local rn, rd = reduce(num, denom)
if not rd then
cx = write(" * " .. rn, cx, cy, 8)
else
cx = write(" * " .. rn .. "/" .. rd, cx, cy, 8)
end
drawBreakdown(y + 12, 2, rn, rd)
else
if #fval > 0 then
cx = write(" * (" .. fval .. ")", cx, cy, 8)
else
cx = write(" * 0", cx, cy, 8)
end
drawBreakdown(y + 12, 1)
end
end
end
local fw = gpu.font.data.w
function _draw()
cls()
write(bits[1], 4, 4, 16)
for i = 1, exp do
write(bits[1 + i], 4+(fw+1)*(i), 4, 11)
end
for i = 1, frac do
write(bits[1 + exp + i], 4+(fw+1)*(exp + i), 4, 8)
end
write("_", 4+(fw+1)*(cursor-1), 6)
drawBreakdown(16)
swap()
end
function _event(e, ...)
if e == "key" then
local k = ...
if k == "left" then
cursor = (cursor - 2) % (1 + exp + frac) + 1
elseif k == "right" then
cursor = cursor % (1 + exp + frac) + 1
elseif k == "space" then
bits[cursor] = 1 - bits[cursor]
end
elseif e == "char" then
local c = ...
if c == "1" or c == "0" then
bits[cursor] = tonumber(c)
end
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment