From fdfe65167ffa66825d89ac49a62c23b36b096bc3 Mon Sep 17 00:00:00 2001 From: Lars Mueller Date: Sun, 26 Feb 2023 15:39:37 +0100 Subject: [PATCH] Fix `math.fround` --- math.lua | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/math.lua b/math.lua index 23f510a..d7f01df 100644 --- a/math.lua +++ b/math.lua @@ -152,6 +152,9 @@ function tostring(number, base, digit_function, precision) end -- See https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/fround#polyfill +-- Rounds a 64-bit float to a 32-bit float; +-- if the closest 32-bit float is out of bounds, +-- the appropriate infinity is returned. function fround(number) if number == 0 or number ~= number then return number @@ -161,14 +164,18 @@ function fround(number) sign = -1 number = -number end - local exp = math_floor(math.log(number, 2)) + local _, exp = math.frexp(number) + exp = exp - 1 -- we want 2^exponent >= number > 2^(exponent-1) local powexp = 2 ^ math.max(-126, math.min(exp, 127)) - local leading = exp < -127 and 0 or 1 - local mantissa = math_floor((leading - number / powexp) * 0x800000 + 0.5) - if mantissa <= -0x800000 then + local leading = exp <= -127 and 0 or 1 -- subnormal number? + local mantissa = math.floor((number / powexp - leading) * 0x800000 + 0.5) + if + mantissa > 0x800000 -- doesn't fit in mantissa + or (exp >= 127 and mantissa == 0x800000) -- fits if the exponent can be increased + then return sign * inf end - return sign * powexp * (leading - mantissa / 0x800000) + return sign * powexp * (leading + mantissa / 0x800000) end -- Export environment