SimpleBit - Binary Simplified [OPEN SOURCE]

Minor Change

.BitUnpack() now returns a tuple instead an array.
So instead of:

local n = SimpleBit.BitPack(243,12,93,10)

local r = SimpleBit.BitUnpack(n)
local a = r[1] -- 243
local b = r[2] -- 12
local c = r[3] -- 93
local d = r[4] -- 10

This would be used:

local n = SimpleBit.BitUnpack

local a,b,c,d = SimpleBit.BitUnpack(n)
1 Like

Converting strings to an unsigned number and then packing that number if possible can save data.

1 Like

That’s what I was thinking, however I’m not sure how to make a number split.

1 Like

This doesn’t make any sense.

The top time is 4*10^(-7) or 0.0000004; e represents scientific notation: in other words whatever comes after it is what 10 is taken to the power of.
The bottom time is 0.000097
This means that even with your benchmarking, SimpleBit.Add(50,51) is actually 243 times slower than 50+51

Benchmarking data also tells us the following:

As you can see, in the 50th percentile, your method is 4.7051ms/0.0034ms = 1383 times slower. Note that every iteration was ran 1000 times:

["SimpleBit Add"] = function(Profiler, RandomNumber) -- You can change "Sample A" to a descriptive name for your function
	for i = 1, 1000 do
		local a = SimpleBit.Add(50, 51)
	end
end;

["Default Add"] = function(Profiler, RandomNumber)
	for i = 1, 1000 do
		local a = 50 + 51
	end
end;

This makes sense when you consider that the ALU specifically has an input for ADD. There is no way that trying to replicate addition in Lua code would be able to match the performance of a direct ALU calculation.

Your multiplication method is also very inefficient, especially for larger numbers. There is no need to hard-add numbers together to get the product. Even multiplying numbers like 1,432,551 and 1,321,415 shouldn’t take very long. Consider the following multiplication algorithm on the associated hardware:

Let’s benchmark multiplication:

["SimpleBit Multiply"] = function(Profiler, RandomNumber) -- You can change "Sample A" to a descriptive name for your function
	for i = 1, 1000 do
		local a = SimpleBit.Multiply(1, 1)
	end
end;

["Default Multiply"] = function(Profiler, RandomNumber)
	for i = 1, 1000 do
		local a = 100 * 123
	end
end;

I input the best possible run-time for the SimpleBit Multiplication method (with non-zero input). Here are the results:

I think you get the picture.

While I think it’s cool that you’re learning about how binary arithmetic works (and I just have to say keep learning, it gets super fun and interesting!), this module does not provide any benefit over the traditional * and + operations.

Small aside:
Gosh, you made me have to pull out my old notes on binary multiplication, can’t say it wasn’t enjoyable though! Thanks for the unexpected trip down memory lane!

9 Likes

Thanks! I seemed to have calculated my benchmarking wrong. But to be honest, I am not much big fan of the addition eithier. It was more of an extra, that I did not prioritise.

SimpleBit.BitPack and soon to be added SimpleBit.Hash is my priority right now.
The add and multiply arithmetic were more of a test than designed for actual usage.

But I appreciete your benchmarking!

The way I add the numbers also may slow down.


Basically I just add 1s or 0s to the Se (short for Sequence) variable.
The way R and the bit is calculated is by a combination of or, and and xor gates.
And since the loop does not break even if all the bits that could be added were added also slows it down.

I am sure even if I made the adder faster, it would still lack over arithmetic operations.

But apart from SimpleBit.Add, SimpleBit.Multiply, and SimpleBit.AddMany, the module offers bit packing and soon will offer key-based encription and hashing.

2 Likes

I did some tests on other functions for my SimpleBit module.

SimpleBit.Floor, SimpleBit.Double and SimpleBit.Half may be the only ones in the arithmetic section that are actually faster than the math version.

Top is math.floor()
Bottom is SimpleBit.Floor()
image
But still, it is a very slight difference.

1 Like

UPDATE :hammer:

New Functions!

.Floor()
Works the same as math.floor, but about 3-5x faster
.Double()
Doubles the integer given, works faster than n*2
.Half()
Halfs the integer given, works faster than n/2

.Combine()
Simply just bit32.bor() but with a different name.

.BinToInt()
Converts a Binary Sequence to a 32bit integer.

.BinToBooleanTable()
.BooleanTableToBin()
Converts a Binary Sequence into a table of Booleans.
Example: 101110 {true,false,true,true,true,false}

String Conversion!

This feature was requested by @regexman!

.StringToBin() converts a string into a binary sequence, that could then be sent into .BinToString() to get the original string.

Example Usage;

local SimpleBit = require(game.ReplicatedStorage.SimpleBit)

local Bin = SimpleBit.StringToBin('Hi there!')

local OriginalString = SimpleBit.BinToString(Bin)

OriginalString: 'Hi there!'

It can also store numbers as strings, but it stores them as characters, so each 1,2,3,4 ect. character is given it’s own 8 bits. .IntToBin is far better for converting integers into a BinSequence.

Plugin Available!

SimpleBit now has a plugin for managing the module!

link

For now it only updates/installs the module, but more settings will come!

What should I add next?

What should I add next to SimpleBit module?

This one literally is a lifesaver, thanks for this

1 Like

There is no need to convert anything, you can just write a function that converts a string to an unsigned number and then uses the function to pack the numbers into one number. It’s a pretty simple function. You should try it out. You can also just use a pre-existing library that does that for you.

Yes, but string.byte() can be done by itself, this just does string.byte() and string.char() and converts them into binary and back to number. Just an extra.

But as you mention it, I will add a function for byte and char to and from an unsigned number, not a binary string.

UPDATE :hammer:

New Functions!

.Ceil() (number) → (number)
Rounds up the number given. (A bit faster than math.ceil)
.IsInt() (number) → (boolean)
Checks if the given number is an integer.

Replacements!

.Add().BitAdd()
.Multiply().BitMultiply()
.Double().BitDouble()
.Half().BitHalf()

String Conversion 2!

Thanks for @Toxicherokingso for bringing this up!

.StringToUintS()
Parameters: (string) → (string)
Converts a string into a sequence of unassigned integers.
Example Input: 'Hello World!
Output: 72.101.108.108.111.32.87.111.114.108.100.33

.UintSToString()
Parameters: (string) → (string)
Converts a sequence of unassigned integers back into a string.
Example Input: 72.101.108.108.111.32.87.111.114.108.100.33
Output: 'Hello World!

UPDATE 3.25, 27TH OF JANUARY.

Minor Update!

New Functions:

.IsEven (number) → (boolean)
Returns true if the number is even.

.IsOdd (number) → (boolean)
Returns true if the number is odd.

.OverBit32Limit (number) → (boolean)
Checks if the number is above 2^32-1, if not, returns false.

Updates moved!

Future updates will now be sent here.

how would i use this? in my tds game?

SimpleBit v2 COMING OUT SOON!

For the past few months I’ve been working on a new SimpleBit release, that better utilizes the Bit32 library. Expect it to come out in 2-3 weeks or less!

Man it’s been more than 1 year i am waiting for it.

1 Like

i forgor :sob:, thanks for reminding me!

I’m almost done with bit64 functions, where the number is split into two bit32 parts.
Can’t promise much since I was meant to release this a year ago, but I’ll try to get it out and ready asap

SIMPLEBIT V2 RELEASED!