Last active
November 5, 2018 05:21
-
-
Save incinirate/0b11ee7453eb32dde8500109ae88b339 to your computer and use it in GitHub Desktop.
Floating Point visualization for Riko4 (rlua)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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