Is an int32 custom type possible?

While working on an update of my bit32 module, I’ve been wondering if it is possible to make a type that accepts numbers between the int32 range. (0 -> 4,294,967,295). If any float, negative, or number above 4,294,967,295 is added, it would not show as compatible.

2 Likes

I don’t see why not, just follow this t’ing down here with your preference:

1 Like

Hey, thanks for the resource but unfortunately it won’t really work for what I’m trying. But I’ll try what I can and update you on it.

Ok my b :sweat_smile:, I’ll try to respond the best I can.

i guess you can just do if statements?

if 0 < val < 4294967295 then warn("Not compatiable") end

Yeah that is sort of what I am trying to do. My idea is that I can make an Int32 custom type with a function like int32.new() and then narrow the inputs to only include the 4 bytes of information, incoded in utf8.

local function ToInt(value)
    return math.floor(value % 4294967296)
end
print(ToInt(28374.3458745)) -- 28374
print(ToInt(4294967298)) -- 2

this will not make a real int it will still be stored in memory as a double and consume the same amount of memory as a double the CPU will still compute it like a double

4 Likes

Alright. Since it can’t be stored as a single int, I might as well combine 2 ints into a float to maximize efficiency.

Edit: Forgot to mention there is a way to store a ‘single int’, although under utf8 incodement.

function li32.pack(n:number): int32
	return {['v']=utf8.char(extr(n,0,8),extr(n,8,8),extr(n,16,8),extr(n,24,8))}
end
1 Like

CPU’s are very efficient working with doubles if you like you can use bitwise operations to store multiple values in a single variable while it will use less ram it wont be as fast as using the double directly

1 Like

Not much need for bit32 in this case to combine two int32s, as bit32 can’t work for floats. There is an easier way to do this however:

tonumber(int32..'.'..int32:reverse()), in this way both int32s would remain intact as a double.

Edit: even more than 2 int32’s can be added since doubles have more than 2^32-1 of ‘int’ space.

this is a string the way strings work is each character uses 1 byte

so something like
728354.34534534 would use 15 bytes plus anything lua stores behind the scenes like the string length that could be saved as a int but i have not looked into the source code of lua strings

and strings are character arrays so they will be a lot slower then using doubles directly

1 Like

yes, I am aware of that and it’s why I added tonumber.

Strange, since utf8 has 2^30-1 different characters, that would mean it is 20 bits (2.5 bytes)

kind of strange to convert 2 numbers into a character array then back to a number

also you need to be careful with precision errors Programming in Lua : 2.3
so im not 100% sure but you might get precision errors at values like 4294967295.4294967295

the first 128 characters use 1 byte then it will go up to 2 bytes and 3 bytes and so on

here is how to use bitwise

-- the 2 numbers we want to save
local value1 = 123
local value2 = 46346

-- save both numbers into a single variable (double)
local save = bit32.replace(value1, value2, 16, 16)

-- extract the 2 values back from the single variable (double)
local loadedValue1 = bit32.extract(save, 0, 16)
local loadedValue2 = bit32.extract(save, 16, 16)

-- print the 2 values
print(loadedValue1)
print(loadedValue2)

because bit32 only gives us 32 bits we can split it into 16,16 so that would give us a max value range of 0 to 65535 but if you like you can split it any way you like for instance 8, 8, 8, 8 or 20, 12

bitwise operations are very fast but still not as fast as using the double directly

Yes, I know how to use bitwise. I made a public resource on it.

Also something’s up with converting utf8 back to its numeric form, and I don’t know why.

I used this code:

local s = {}
local miscal = 0
for c=1, 1048575 do
	s[#s+1] = utf8.char(c)
end
local str = table.concat(s,'')
for i, v in pairs(s) do
	if not utf8.codepoint(str:sub(i)) == v then
		miscal+=1
	end
end


print(miscal)

And it errored, suggesting that not all utf8s can be converted back

in this video I show how to convert numbers into base 90

so you could store 65610000 values just using 4 characters in a string

or 5904900000 values with just 5 characters

the reason I use base 90 is because there are only 94 characters that you can save into the datastore that consume only 1 character

the 4 characters that are missing are - , space delete but i use - to indicate negative numbers and , to split numbers and I left out white space characters

doubles use 8 bytes and according to Lua object memory sizes | WoWWiki | Fandom strings use 24 + length bytes so using 2 separate number variables would use less memory then a empty string

image

1 Like
local Int32 = {}

function Int32.new(Value)
	local Int = {}
	setmetatable(Int, {__index = Int32})
	Int.Value = if Value < -4294967295 or Value > 4294967295 then 0 elseif Value > -4294967295 and Value < 0 then math.abs(math.floor(Value)) elseif Value > 0 and Value < 4294967296 then math.floor(Value) else 0
	return Int
end

local Int = Int32.new(10)
print(Int.Value) --10
local Int2 = Int32.new(20.32)
print(Int2.Value) --20
local Int3 = Int32.new(-1)
print(Int3.Value) --1