Last active
February 19, 2023 01:43
-
-
Save LunNova/9cf050df81619e6a559cfb573b772915 to your computer and use it in GitHub Desktop.
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
function fp_to_bytes(fp, bytes, is_double) | |
local val = tonumber(fp) | |
-- it's a NaN or inf | |
if val ~= val or val == math.huge or val == -math.huge then | |
bytes[1] = (val ~= val or val == math.huge) and 0x7f or 0xff | |
bytes[2] = (val ~= val and 0xf9 or 0xf8) | |
local max = is_double and 8 or 4 | |
for i = 3, max do | |
bytes[i] = 0 | |
end | |
return | |
end | |
local sign = 0 | |
if val < 0 then | |
sign = 1 | |
val = -val | |
end | |
local mantissa, exponent = math.frexp(val) | |
if val == 0 then | |
mantissa = 0 | |
exponent = 0 | |
else | |
mantissa = (mantissa * 2 - 1) * math.ldexp(0.5, is_double and 53 or 24) | |
exponent = exponent + (is_double and 1022 or 126) | |
end | |
local pos | |
if is_double then | |
val = mantissa | |
for i = 8, 3, -1 do | |
bytes[i] = math.floor(val) % (2 ^ 8) | |
val = math.floor(val / (2 ^ 8)) | |
end | |
else | |
bytes[4] = math.floor(mantissa) % (2 ^ 8) | |
val = math.floor(mantissa / (2 ^ 8)) | |
bytes[3] = math.floor(val) % (2 ^ 8) | |
val = math.floor(val / (2 ^ 8)) | |
end | |
bytes[2] = math.floor(exponent * (is_double and 16 or 128) + val) % (2 ^ 8) | |
val = math.floor((exponent * (is_double and 16 or 128) + val) / (2 ^ 8)) | |
bytes[1] = math.floor(sign * 128 + val) % (2 ^ 8) | |
end | |
function bytes_to_fp(bytes, is_double) | |
local n = is_double and 8 or 4 | |
-- NaN or inf | |
if (bytes[1] == 0x7F or bytes[1] == 0xff) and bytes[2] >= 0xf8 then | |
if bytes[2] == 0xf8 then | |
local all_zero = true | |
for i = 3, n do | |
if bytes[i] ~= 0 then | |
all_zero = false | |
break | |
end | |
end | |
if all_zero then | |
return bytes[1] == 0x7F and 1/0 or -1/0 | |
end | |
end | |
return 0/0 | |
end | |
local sign = 1 | |
if bytes[1] > 127 then | |
sign = -1 | |
end | |
local mantissa = bytes[2] % (is_double and 16 or 128) | |
for i = 3, n do | |
mantissa = mantissa * (2 ^ 8) + bytes[i] | |
end | |
local exponent = (bytes[1] % 128) * (is_double and 16 or 2) + math.floor(bytes[2] / (is_double and 16 or 128)) | |
if exponent == 0 then | |
return 0.0 | |
else | |
mantissa = (math.ldexp(mantissa, is_double and -52 or -23) + 1) * sign | |
return math.ldexp(mantissa, exponent - (is_double and 1023 or 127)) | |
end | |
end | |
function test_roundtrip(inp) | |
bytes = {} | |
for i = 1, 8 do | |
bytes[i] = 0 | |
end | |
fp_to_bytes(inp, bytes, true) | |
-- for i, v in ipairs(bytes) do | |
-- print (i, string.format("%x", v)) | |
-- end | |
-- print(bytes) | |
print(inp, "==", bytes_to_fp(bytes, true)) | |
end | |
test_roundtrip(0) | |
test_roundtrip(1.234) | |
test_roundtrip(-9876.5432) | |
test_roundtrip(1/0) | |
test_roundtrip(-1/0) | |
test_roundtrip(0/0) |
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
0 == 0 | |
1.234 == 1.234 | |
-9876.5432 == -9876.5432 | |
inf == inf | |
-inf == -inf | |
nan == nan |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment