Clean up table integers

This commit is contained in:
Rerumu 2022-07-02 03:30:36 -04:00
parent d74124815b
commit 47079b7758

View File

@ -14,13 +14,11 @@ local bit_not = bit32.bnot
local bit_extract = bit32.extract local bit_extract = bit32.extract
local bit_replace = bit32.replace local bit_replace = bit32.replace
local math_floor = math.floor
local table_freeze = table.freeze local table_freeze = table.freeze
local from_u32, into_u32, from_u64, into_u64 local from_u32, from_u64, into_u64
local num_add, num_subtract, num_divide_unsigned, num_negate local num_subtract, num_divide_unsigned, num_negate
local num_not, num_or, num_shift_left local num_or, num_shift_left
local num_is_negative, num_is_zero, num_is_less_unsigned local num_is_negative, num_is_zero, num_is_less_unsigned
function Numeric.from_u32(data_1, data_2) function Numeric.from_u32(data_1, data_2)
@ -32,21 +30,16 @@ function Numeric.into_u32(data)
end end
function Numeric.from_u64(value) function Numeric.from_u64(value)
return from_u32(bit_and(value), math_floor(value / 0x100000000)) return from_u32(bit_and(value), bit_and(value / 0x100000000))
end end
function Numeric.into_u64(value) function Numeric.into_u64(value)
local data_1, data_2 = into_u32(value) return value[1] + value[2] * 0x100000000
return data_1 + data_2 * 0x100000000
end end
function Numeric.add(lhs, rhs) function Numeric.add(lhs, rhs)
local data_l_1, data_l_2 = into_u32(lhs) local data_1 = lhs[1] + rhs[1]
local data_r_1, data_r_2 = into_u32(rhs) local data_2 = lhs[2] + rhs[2]
local data_1 = data_l_1 + data_r_1
local data_2 = data_l_2 + data_r_2
if data_1 >= 0x100000000 then if data_1 >= 0x100000000 then
data_1 = data_1 - 0x100000000 data_1 = data_1 - 0x100000000
@ -61,11 +54,8 @@ function Numeric.add(lhs, rhs)
end end
function Numeric.subtract(lhs, rhs) function Numeric.subtract(lhs, rhs)
local data_l_1, data_l_2 = into_u32(lhs) local data_1 = lhs[1] - rhs[1]
local data_r_1, data_r_2 = into_u32(rhs) local data_2 = lhs[2] - rhs[2]
local data_1 = data_l_1 - data_r_1
local data_2 = data_l_2 - data_r_2
if data_1 < 0 then if data_1 < 0 then
data_1 = data_1 + 0x100000000 data_1 = data_1 + 0x100000000
@ -98,30 +88,21 @@ end
function Numeric.multiply(lhs, rhs) function Numeric.multiply(lhs, rhs)
if num_is_zero(lhs) or num_is_zero(rhs) then if num_is_zero(lhs) or num_is_zero(rhs) then
return NUM_ZERO return NUM_ZERO
end elseif num_is_less_unsigned(lhs, NUM_BIT_26) and num_is_less_unsigned(rhs, NUM_BIT_26) then
return from_u64(lhs[1] * rhs[1])
-- If both longs are small, use float multiplication
if num_is_less_unsigned(lhs, NUM_BIT_26) and num_is_less_unsigned(rhs, NUM_BIT_26) then
local data_l_1, _ = into_u32(lhs)
local data_r_1, _ = into_u32(rhs)
return from_u64(data_l_1 * data_r_1)
end end
-- Divide each long into 4 chunks of 16 bits, and then add up 4x4 products. -- Divide each long into 4 chunks of 16 bits, and then add up 4x4 products.
-- We can skip products that would overflow. -- We can skip products that would overflow.
local data_l_1, data_l_2 = into_u32(lhs) local a48 = bit_rshift(lhs[2], 16)
local data_r_1, data_r_2 = into_u32(rhs) local a32 = bit_and(lhs[2], 0xFFFF)
local a16 = bit_rshift(lhs[1], 16)
local a00 = bit_and(lhs[1], 0xFFFF)
local a48 = bit_rshift(data_l_2, 16) local b48 = bit_rshift(rhs[2], 16)
local a32 = bit_and(data_l_2, 0xFFFF) local b32 = bit_and(rhs[2], 0xFFFF)
local a16 = bit_rshift(data_l_1, 16) local b16 = bit_rshift(rhs[1], 16)
local a00 = bit_and(data_l_1, 0xFFFF) local b00 = bit_and(rhs[1], 0xFFFF)
local b48 = bit_rshift(data_r_2, 16)
local b32 = bit_and(data_r_2, 0xFFFF)
local b16 = bit_rshift(data_r_1, 16)
local b00 = bit_and(data_r_1, 0xFFFF)
local c00 = a00 * b00 local c00 = a00 * b00
local c16 = bit_rshift(c00, 16) local c16 = bit_rshift(c00, 16)
@ -161,23 +142,20 @@ function Numeric.divide_unsigned(lhs, rhs)
elseif num_is_zero(lhs) then elseif num_is_zero(lhs) then
return NUM_ZERO return NUM_ZERO
elseif num_is_less_unsigned(lhs, NUM_BIT_52) and num_is_less_unsigned(rhs, NUM_BIT_52) then elseif num_is_less_unsigned(lhs, NUM_BIT_52) and num_is_less_unsigned(rhs, NUM_BIT_52) then
local result = math_floor(into_u64(lhs) / into_u64(rhs)) return from_u64(into_u64(lhs) / into_u64(rhs))
return from_u64(result)
end end
local quotient = NUM_ZERO local quotient = NUM_ZERO
local remainder = NUM_ZERO local remainder = NUM_ZERO
local num_1, num_2 = into_u32(lhs)
for i = 63, 0, -1 do for i = 63, 0, -1 do
local rem_1, rem_2 = into_u32(num_shift_left(remainder, NUM_ONE)) local temp = num_shift_left(remainder, NUM_ONE)
local rem_1, rem_2 = temp[1], temp[2]
if i > 31 then if i > 31 then
rem_1 = bit_or(rem_1, bit_extract(num_2, i - 32, 1)) rem_1 = bit_or(rem_1, bit_extract(lhs[2], i - 32, 1))
else else
rem_1 = bit_or(rem_1, bit_extract(num_1, i, 1)) rem_1 = bit_or(rem_1, bit_extract(lhs[1], i, 1))
end end
remainder = from_u32(rem_1, rem_2) remainder = from_u32(rem_1, rem_2)
@ -206,34 +184,47 @@ function Numeric.divide_signed(lhs, rhs)
end end
function Numeric.negate(value) function Numeric.negate(value)
return num_add(num_not(value), NUM_ONE) local data_1 = bit_not(value[1]) + 1
local data_2 = bit_not(value[2])
if data_1 >= 0x100000000 then
data_1 = data_1 - 0x100000000
data_2 = data_2 + 1
end
if data_2 >= 0x100000000 then
data_2 = data_2 - 0x100000000
end
return from_u32(data_1, data_2)
end end
function Numeric.bit_and(lhs, rhs) function Numeric.bit_and(lhs, rhs)
local data_l_1, data_l_2 = into_u32(lhs) local data_1 = bit_and(lhs[1], rhs[1])
local data_r_1, data_r_2 = into_u32(rhs) local data_2 = bit_and(lhs[2], rhs[2])
return from_u32(bit_and(data_l_1, data_r_1), bit_and(data_l_2, data_r_2)) return from_u32(data_1, data_2)
end end
function Numeric.bit_not(value) function Numeric.bit_not(value)
local data_1, data_2 = into_u32(value) local data_1 = bit_not(value[1])
local data_2 = bit_not(value[2])
return from_u32(bit_not(data_1), bit_not(data_2)) return from_u32(data_1, data_2)
end end
function Numeric.bit_or(lhs, rhs) function Numeric.bit_or(lhs, rhs)
local data_l_1, data_l_2 = into_u32(lhs) local data_1 = bit_or(lhs[1], rhs[1])
local data_r_1, data_r_2 = into_u32(rhs) local data_2 = bit_or(lhs[2], rhs[2])
return from_u32(bit_or(data_l_1, data_r_1), bit_or(data_l_2, data_r_2)) return from_u32(data_1, data_2)
end end
function Numeric.bit_xor(lhs, rhs) function Numeric.bit_xor(lhs, rhs)
local data_l_1, data_l_2 = into_u32(lhs) local data_1 = bit_xor(lhs[1], rhs[1])
local data_r_1, data_r_2 = into_u32(rhs) local data_2 = bit_xor(lhs[2], rhs[2])
return from_u32(bit_xor(data_l_1, data_r_1), bit_xor(data_l_2, data_r_2)) return from_u32(data_1, data_2)
end end
function Numeric.shift_left(lhs, rhs) function Numeric.shift_left(lhs, rhs)
@ -241,20 +232,13 @@ function Numeric.shift_left(lhs, rhs)
if count < 32 then if count < 32 then
local pad = 32 - count local pad = 32 - count
local data_l_1, data_l_2 = into_u32(lhs)
local data_1 = bit_lshift(data_l_1, count) local data_1 = bit_lshift(lhs[1], count)
local data_2 = bit_replace(bit_rshift(data_l_1, pad), data_l_2, count, pad) local data_2 = bit_replace(bit_rshift(lhs[1], pad), lhs[2], count, pad)
return from_u32(data_1, data_2) return from_u32(data_1, data_2)
elseif count == 32 then
local data_l_1, _ = into_u32(lhs)
return from_u32(0, data_l_1)
else else
local data_l_1, _ = into_u32(lhs) return from_u32(0, bit_lshift(lhs[1], count - 32))
return from_u32(0, bit_lshift(data_l_1, count - 32))
end end
end end
@ -262,20 +246,12 @@ function Numeric.shift_right_unsigned(lhs, rhs)
local count = into_u64(rhs) local count = into_u64(rhs)
if count < 32 then if count < 32 then
local data_l_1, data_l_2 = into_u32(lhs) local data_1 = bit_replace(bit_rshift(lhs[1], count), lhs[2], 32 - count, count)
local data_2 = bit_rshift(lhs[2], count)
local data_1 = bit_replace(bit_rshift(data_l_1, count), data_l_2, 32 - count, count)
local data_2 = bit_rshift(data_l_2, count)
return from_u32(data_1, data_2) return from_u32(data_1, data_2)
elseif count == 32 then
local _, data_l_2 = into_u32(lhs)
return from_u32(data_l_2, 0)
else else
local _, data_l_2 = into_u32(lhs) return from_u32(bit_rshift(lhs[2], count - 32), 0)
return from_u32(bit_rshift(data_l_2, count - 32), 0)
end end
end end
@ -283,53 +259,42 @@ function Numeric.shift_right_signed(lhs, rhs)
local count = into_u64(rhs) local count = into_u64(rhs)
if count < 32 then if count < 32 then
local data_l_1, data_l_2 = into_u32(lhs) local data_1 = bit_replace(bit_rshift(lhs[1], count), lhs[2], 32 - count, count)
local data_2 = bit_arshift(lhs[2], count)
local data_1 = bit_replace(bit_rshift(data_l_1, count), data_l_2, 32 - count, count)
local data_2 = bit_arshift(data_l_2, count)
return from_u32(data_1, data_2) return from_u32(data_1, data_2)
else else
local _, data_l_2 = into_u32(lhs) local data_1 = bit_arshift(lhs[2], count - 32)
local data_2 = lhs[2] > 0x80000000 and 0xFFFFFFFF or 0
local data_1 = bit_arshift(data_l_2, count - 32)
local data_2 = data_l_2 > 0x80000000 and 0xFFFFFFFF or 0
return from_u32(data_1, data_2) return from_u32(data_1, data_2)
end end
end end
function Numeric.is_negative(value) function Numeric.is_negative(value)
local _, data_2 = into_u32(value) return value[2] >= 0x80000000
return data_2 >= 0x80000000
end end
function Numeric.is_zero(value) function Numeric.is_zero(value)
local data_1, data_2 = into_u32(value) return value[1] == 0 and value[2] == 0
return data_1 == 0 and data_2 == 0
end end
function Numeric.is_equal(lhs, rhs) function Numeric.is_equal(lhs, rhs)
local data_l_1, data_l_2 = into_u32(lhs) return lhs[1] == rhs[1] and lhs[2] == rhs[2]
local data_r_1, data_r_2 = into_u32(rhs)
return data_l_1 == data_r_1 and data_l_2 == data_r_2
end end
function Numeric.is_less_unsigned(lhs, rhs) function Numeric.is_less_unsigned(lhs, rhs)
local data_l_1, data_l_2 = into_u32(lhs) local lhs_2 = lhs[2]
local data_r_1, data_r_2 = into_u32(rhs) local rhs_2 = rhs[2]
return data_l_2 < data_r_2 or (data_l_2 == data_r_2 and data_l_1 < data_r_1) return lhs_2 < rhs_2 or (lhs_2 == rhs_2 and lhs[1] < rhs[1])
end end
function Numeric.is_greater_unsigned(lhs, rhs) function Numeric.is_greater_unsigned(lhs, rhs)
local data_l_1, data_l_2 = into_u32(lhs) local lhs_2 = lhs[2]
local data_r_1, data_r_2 = into_u32(rhs) local rhs_2 = rhs[2]
return data_l_2 > data_r_2 or (data_l_2 == data_r_2 and data_l_1 > data_r_1) return lhs_2 > rhs_2 or (lhs_2 == rhs_2 and lhs[1] > rhs[1])
end end
function Numeric.is_less_signed(lhs, rhs) function Numeric.is_less_signed(lhs, rhs)
@ -359,16 +324,13 @@ function Numeric.is_greater_signed(lhs, rhs)
end end
from_u32 = Numeric.from_u32 from_u32 = Numeric.from_u32
into_u32 = Numeric.into_u32
from_u64 = Numeric.from_u64 from_u64 = Numeric.from_u64
into_u64 = Numeric.into_u64 into_u64 = Numeric.into_u64
num_add = Numeric.add
num_subtract = Numeric.subtract num_subtract = Numeric.subtract
num_divide_unsigned = Numeric.divide_unsigned num_divide_unsigned = Numeric.divide_unsigned
num_negate = Numeric.negate num_negate = Numeric.negate
num_not = Numeric.bit_not
num_or = Numeric.bit_or num_or = Numeric.bit_or
num_shift_left = Numeric.shift_left num_shift_left = Numeric.shift_left