Fix conversion operations and implement saturation
Namie fixie
This commit is contained in:
parent
50b5680bef
commit
3853e06efa
@ -10,6 +10,7 @@ local i64 = ffi.typeof("int64_t")
|
||||
local math_ceil = math.ceil
|
||||
local math_floor = math.floor
|
||||
local to_number = tonumber
|
||||
local to_signed = bit.tobit
|
||||
|
||||
local NUM_ZERO = i64(0)
|
||||
local NUM_ONE = i64(1)
|
||||
@ -34,8 +35,6 @@ do
|
||||
local copysign = {}
|
||||
local nearest = {}
|
||||
|
||||
local to_signed = bit.tobit
|
||||
|
||||
local math_abs = math.abs
|
||||
local math_min = math.min
|
||||
local math_max = math.max
|
||||
@ -396,6 +395,7 @@ end
|
||||
do
|
||||
local wrap = {}
|
||||
local truncate = {}
|
||||
local saturate = {}
|
||||
local extend = {}
|
||||
local convert = {}
|
||||
local promote = {}
|
||||
@ -404,6 +404,10 @@ do
|
||||
|
||||
local bit_and = bit.band
|
||||
|
||||
local NUM_MIN_I64 = bit.lshift(NUM_ONE, 63)
|
||||
local NUM_MAX_I64 = bit.bnot(NUM_MIN_I64)
|
||||
local NUM_MAX_U64 = bit.bnot(NUM_ZERO)
|
||||
|
||||
-- This would surely be an issue in a multi-thread environment...
|
||||
-- ... thankfully this isn't one.
|
||||
local RE_INSTANCE = ffi.new([[union {
|
||||
@ -421,13 +425,66 @@ do
|
||||
|
||||
truncate.i32_f32 = truncate_f64
|
||||
truncate.i32_f64 = truncate_f64
|
||||
|
||||
function truncate.u32_f32(num)
|
||||
return (to_signed(truncate_f64(num)))
|
||||
end
|
||||
|
||||
truncate.u32_f64 = truncate.u32_f32
|
||||
|
||||
truncate.i64_f32 = i64
|
||||
truncate.i64_f64 = i64
|
||||
truncate.u64_f32 = i64
|
||||
truncate.u64_f64 = i64
|
||||
|
||||
function truncate.u64_f64(num)
|
||||
return (i64(u64(num)))
|
||||
end
|
||||
|
||||
truncate.f32 = truncate_f64
|
||||
truncate.f64 = truncate_f64
|
||||
|
||||
function saturate.i32_f64(num)
|
||||
if num <= -0x80000000 then
|
||||
return -0x80000000
|
||||
elseif num >= 0x7FFFFFFF then
|
||||
return 0x7FFFFFFF
|
||||
else
|
||||
return to_signed(truncate_f64(num))
|
||||
end
|
||||
end
|
||||
|
||||
function saturate.u32_f64(num)
|
||||
if num <= 0 then
|
||||
return 0
|
||||
elseif num >= 0xFFFFFFFF then
|
||||
return -1
|
||||
else
|
||||
return to_signed(truncate_f64(num))
|
||||
end
|
||||
end
|
||||
|
||||
function saturate.i64_f64(num)
|
||||
if num >= 2 ^ 63 - 1 then
|
||||
return NUM_MAX_I64
|
||||
elseif num <= -2 ^ 63 then
|
||||
return NUM_MIN_I64
|
||||
elseif num ~= num then
|
||||
return NUM_ZERO
|
||||
else
|
||||
return i64(num)
|
||||
end
|
||||
end
|
||||
|
||||
function saturate.u64_f64(num)
|
||||
if num >= 2 ^ 64 then
|
||||
return NUM_MAX_U64
|
||||
elseif num <= 0 or num ~= num then
|
||||
return NUM_ZERO
|
||||
else
|
||||
return i64(u64(num))
|
||||
end
|
||||
end
|
||||
|
||||
function extend.i32_n8(num)
|
||||
num = bit_and(num, 0xFF)
|
||||
|
||||
@ -535,6 +592,7 @@ do
|
||||
|
||||
module.wrap = wrap
|
||||
module.truncate = truncate
|
||||
module.saturate = saturate
|
||||
module.extend = extend
|
||||
module.convert = convert
|
||||
module.demote = demote
|
||||
|
@ -364,6 +364,7 @@ end
|
||||
do
|
||||
local wrap = {}
|
||||
local truncate = {}
|
||||
local saturate = {}
|
||||
local extend = {}
|
||||
local convert = {}
|
||||
local demote = {}
|
||||
@ -372,55 +373,23 @@ do
|
||||
|
||||
local math_ceil = math.ceil
|
||||
local math_floor = math.floor
|
||||
local math_clamp = math.clamp
|
||||
|
||||
local string_pack = string.pack
|
||||
local string_unpack = string.unpack
|
||||
|
||||
local NUM_ZERO = Integer.ZERO
|
||||
local NUM_MIN_I64 = num_from_u32(0, 0x80000000)
|
||||
local NUM_MAX_I64 = num_from_u32(0xFFFFFFFF, 0x7FFFFFFF)
|
||||
local NUM_MAX_U64 = num_from_u32(0xFFFFFFFF, 0xFFFFFFFF)
|
||||
|
||||
local num_from_u64 = Integer.from_u64
|
||||
local num_into_u64 = Integer.into_u64
|
||||
|
||||
local num_negate = Integer.negate
|
||||
local num_is_negative = Integer.is_negative
|
||||
|
||||
function wrap.i32_i64(num)
|
||||
local data_1, _ = num_into_u32(num)
|
||||
|
||||
return data_1
|
||||
end
|
||||
|
||||
truncate.i32_f32 = to_u32
|
||||
truncate.i32_f64 = to_u32
|
||||
truncate.u32_f32 = no_op
|
||||
truncate.u32_f64 = no_op
|
||||
|
||||
function truncate.i64_f32(num)
|
||||
if num < 0 then
|
||||
local temp = num_from_u64(-math_ceil(num))
|
||||
|
||||
return num_negate(temp)
|
||||
else
|
||||
local temp = math_floor(num)
|
||||
|
||||
return num_from_u64(temp)
|
||||
end
|
||||
end
|
||||
|
||||
function truncate.i64_f64(num)
|
||||
if num < 0 then
|
||||
local temp = num_from_u64(-math_ceil(num))
|
||||
|
||||
return num_negate(temp)
|
||||
else
|
||||
local temp = math_floor(num)
|
||||
|
||||
return num_from_u64(temp)
|
||||
end
|
||||
end
|
||||
|
||||
truncate.u64_f32 = num_from_u64
|
||||
truncate.u64_f64 = num_from_u64
|
||||
|
||||
function truncate.f32(num)
|
||||
local function truncate_f64(num)
|
||||
if num >= 0 then
|
||||
return math_floor(num)
|
||||
else
|
||||
@ -428,7 +397,78 @@ do
|
||||
end
|
||||
end
|
||||
|
||||
truncate.f64 = truncate.f32
|
||||
function wrap.i32_i64(num)
|
||||
local data_1, _ = num_into_u32(num)
|
||||
|
||||
return data_1
|
||||
end
|
||||
|
||||
function truncate.i32_f32(num)
|
||||
return to_u32(truncate_f64(num))
|
||||
end
|
||||
|
||||
truncate.i32_f64 = to_u32
|
||||
truncate.u32_f32 = truncate_f64
|
||||
truncate.u32_f64 = truncate_f64
|
||||
|
||||
function truncate.i64_f32(num)
|
||||
if num < 0 then
|
||||
local temp = num_from_u64(-num)
|
||||
|
||||
return num_negate(temp)
|
||||
else
|
||||
return num_from_u64(num)
|
||||
end
|
||||
end
|
||||
|
||||
truncate.i64_f64 = truncate.i64_f32
|
||||
|
||||
function truncate.u64_f32(num)
|
||||
if num <= 0 then
|
||||
return NUM_ZERO
|
||||
else
|
||||
return num_from_u64(math_floor(num))
|
||||
end
|
||||
end
|
||||
|
||||
truncate.u64_f64 = truncate.u64_f32
|
||||
|
||||
truncate.f32 = truncate_f64
|
||||
truncate.f64 = truncate_f64
|
||||
|
||||
function saturate.i32_f64(num)
|
||||
local temp = math_clamp(truncate_f64(num), -0x80000000, 0x7FFFFFFF)
|
||||
|
||||
return to_u32(temp)
|
||||
end
|
||||
|
||||
function saturate.u32_f64(num)
|
||||
local temp = math_clamp(truncate_f64(num), 0, 0xFFFFFFFF)
|
||||
|
||||
return to_u32(temp)
|
||||
end
|
||||
|
||||
local truncate_i64_f64 = truncate.i64_f64
|
||||
|
||||
function saturate.i64_f64(num)
|
||||
if num >= 2 ^ 63 - 1 then
|
||||
return NUM_MAX_I64
|
||||
elseif num <= -2 ^ 63 then
|
||||
return NUM_MIN_I64
|
||||
else
|
||||
return truncate_i64_f64(num)
|
||||
end
|
||||
end
|
||||
|
||||
function saturate.u64_f64(num)
|
||||
if num >= 2 ^ 64 then
|
||||
return NUM_MAX_U64
|
||||
elseif num <= 0 then
|
||||
return NUM_ZERO
|
||||
else
|
||||
return truncate_i64_f64(num)
|
||||
end
|
||||
end
|
||||
|
||||
function extend.i32_n8(num)
|
||||
num = bit_and(num, 0xFF)
|
||||
@ -504,7 +544,7 @@ do
|
||||
return num_from_u32(num, 0)
|
||||
end
|
||||
|
||||
convert.f32_i32 = no_op
|
||||
convert.f32_i32 = to_i32
|
||||
convert.f32_u32 = no_op
|
||||
|
||||
function convert.f32_i64(num)
|
||||
@ -520,17 +560,7 @@ do
|
||||
convert.f32_u64 = num_into_u64
|
||||
convert.f64_i32 = to_i32
|
||||
convert.f64_u32 = no_op
|
||||
|
||||
function convert.f64_i64(num)
|
||||
if num_is_negative(num) then
|
||||
local temp = num_negate(num)
|
||||
|
||||
return -num_into_u64(temp)
|
||||
else
|
||||
return num_into_u64(num)
|
||||
end
|
||||
end
|
||||
|
||||
convert.f64_i64 = convert.f32_i64
|
||||
convert.f64_u64 = num_into_u64
|
||||
|
||||
demote.f32_f64 = no_op
|
||||
@ -565,6 +595,7 @@ do
|
||||
|
||||
module.wrap = wrap
|
||||
module.truncate = truncate
|
||||
module.saturate = saturate
|
||||
module.extend = extend
|
||||
module.convert = convert
|
||||
module.demote = demote
|
||||
|
Loading…
x
Reference in New Issue
Block a user