[Include] DBits - 16-bit and 8-bit arrays support.
#1

[Include] DBits 1.1
> created by MrDeath537



Introduction:
This include allow us to create 16 and 8 bit arrays, you've to download it and put on "pawno\includes\" then include it on your script as:
pawn Код:
#include <DBits>


Creating variables:
Use the following syntax:
Код:
new
    Bit16:variable<size>,
    Bit8:variable<size>;

Functions:
  • Bit8_Get(variable[], slot):
    Returns the value of the specified slot on the variable.
  • Bit8_Set(variable[], slot, value):
    Sets the value of the specified slot on the variable.
  • Bit16_Get(variable[], slot):
    Returns the value of the specified slot on the variable.
  • Bit16_Set(variable[], slot, value):
    Sets the value of the specified slot on the variable.


Posible uses:
The main usage would be saving memory, why should you waste the double memory (if you need 16-bit variables) or the quadruple (if you need 8-bit variables) if you can use the right one and save memory?



Limits:
8-bits, maximum variable size: 256.
16-bits, maximum variable size: 65536.



Notes:
- It's impossible to create a single 8-bit or 16-bit variable, but not arrays, because this include uses "normal" variables.
- The 8-bit variables uses char-arrays.
- I did some tests and I didn't find any bug, please tell me if you find one.



Download:
Pastebin - First release
Pastebin - Update 1.1
Reply
#2

NICE very usefull !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
Reply
#3

GJ i will use it...i really needed this
Reply
#4

Nice!!, very good for improving efficiency in scripts
Reply
#5

Nice job!
Reply
#6

Nice, but I ran a speed test and the results are that your bit system is slower than the normal 32-bit array system. (Maybe I made some mistakes)

Here's the script I used: http://pastebin.com/biN6NUC6
And the results are:
Код:
8Bit:  115ms
16Bit: 768ms (wtf?)
32Bit: 107ms
Reply
#7

Very nice!

//Edit: To the speed comparator above:
This is no WTF. 8-bit and 32-bit is already built in in PAWN, 16-bit not. So 16-bit needs some calculations and this takes time.

//Edit 2: Why is there a DBIT_VAR?
pawn Код:
#define Bit16_Get(%0,%1)                                                        \
        (((DBITS_VAR=(%1)),DBITS_VAR&1)?(%0[(%1)/2]&0x0000FFFF):((%0[(%1)/2]>>>16)&0x0000FFFF))
You could just do this:
pawn Код:
#define Bit16_Get(%0,%1)                                                        \
        ((((%1)&1)?(%0[(%1)/2]&0x0000FFFF):((%0[(%1)/2]>>>16)&0x0000FFFF))
//Edit 3:
pawn Код:
#define Bit16:%0<%1>                                                            \
        %0[(%1)/2]
I'm not sure, but maybe you should round the real array size up:
pawn Код:
#define Bit16:%0<%1>                                                            \
        %0[((%1)+2)/2] // Round up here
Assume you want 31 16-bit cells, now you divide 31 by 2 and recieve 15. So there would be no 31st cell...
If you round up, there's a 32nd 16-bit cells, which you don't need, but it's still better.
Too much is better than not enough.
Reply
#8

Quote:
Originally Posted by Double-O-Seven
Посмотреть сообщение
Very nice!

//Edit: To the speed comparator above:
This is no WTF. 8-bit and 32-bit is already built in in PAWN, 16-bit not. So 16-bit needs some calculations and this takes time.
Oh ok, thanks for the explaination.
Reply
#9

Thanks for the comments.



Quote:
Originally Posted by Double-O-Seven
Посмотреть сообщение
Very nice!

//Edit: To the speed comparator above:
This is no WTF. 8-bit and 32-bit is already built in in PAWN, 16-bit not. So 16-bit needs some calculations and this takes time.

//Edit 2: Why is there a DBIT_VAR?
pawn Код:
#define Bit16_Get(%0,%1)                                                        \
        (((DBITS_VAR=(%1)),DBITS_VAR&1)?(%0[(%1)/2]&0x0000FFFF):((%0[(%1)/2]>>>16)&0x0000FFFF))
You could just do this:
pawn Код:
#define Bit16_Get(%0,%1)                                                        \
        ((((%1)&1)?(%0[(%1)/2]&0x0000FFFF):((%0[(%1)/2]>>>16)&0x0000FFFF))
//Edit 3:
pawn Код:
#define Bit16:%0<%1>                                                            \
        %0[(%1)/2]
I'm not sure, but maybe you should round the real array size up:
pawn Код:
#define Bit16:%0<%1>                                                            \
        %0[((%1)+2)/2] // Round up here
If I didn't use DBITS_VAR, the compiler gives a warning because that's like doing:
pawn Код:
if (1 == 1)
EDIT: I added the round up. Thanks.




Quote:
Originally Posted by Anzipane!
Посмотреть сообщение
Nice, but I ran a speed test and the results are that your bit system is slower than the normal 32-bit array system. (Maybe I made some mistakes)

Here's the script I used: http://pastebin.com/biN6NUC6
And the results are:
Код:
8Bit:  115ms
16Bit: 768ms (wtf?)
32Bit: 107ms
There isn't support for 16-bit, like Double-O-Seven said. That's the reason of why it's slow.
Reply
#10

Quote:
Originally Posted by Double-O-Seven
Посмотреть сообщение
OK, here are 2 suggestions for better efficiency:
1) The round up thing has always 1 cells which is never used. Did not think far enough before:
This would be better:
pawn Код:
#define Bit16:%0<%1>                                                                                                                    \
                %0[((%1)+1)/2)]
Only add 1. Why?
(30 + 2) / 2 = 16, while you actually only want 15 cells. 1 cell to much.
(31 + 2) / 2 = 16, here you actually want 16 cells.
Now better:
(30 + 1) / 2 = 15, exactly what you wanted, 15 cells.
(31 + 1) / 2 = 16, here you actually want 16 cells.

2) For speed: Instead of using / 2, you could use >>> 1 and you get the same result.
Division is probably slower than shifting. (However, I'm not sure about this.)
Could you believe me I used "+1" and then changed it? Look at the post edit history and check the pastebin link haha.
Reply
#11

How about adding support for nibbles?
Reply
#12

ah epic. Useful for some functions. Good Job MD
Reply
#13

Quote:
Originally Posted by Double-O-Seven
Посмотреть сообщение
How about adding support for nibbles?
I'm not good enough to try 4-bits support. *sadface*



Quote:
Originally Posted by ylleron
Посмотреть сообщение
ah epic. Useful for some functions. Good Job MD
Thank you.
Reply
#14

Quote:
Originally Posted by ******
Посмотреть сообщение
There's a better argument for using the "DBIT_VAR" than the one even MrDeath537 gave, consider this code:

pawn Код:
Bit16_Get(arr, ++i);
Without using "DBIT_VAR" that code will not work correctly as "i" will actually be incremented twice.
But even with DBIT_VAR, "i" will get incremented twice! The first time when DBIT_VAR is assigned with "i" and a second time in the following code...

Making the Bit16_Get function as a stock function could solve this.

//Edit: I've tried my luck with nibble coding.^^
pawn Код:
#define Nibbles:%0<%1> \
    %0[((%1) + 8) >>> 3]

stock Nibble_Get (arr [], slot)
{
    new shamt = (slot & 7) * 4; // (slot % 8) * 4
    return ((arr [slot >>> 3] & (0x0F << (shamt))) >>> shamt);
}

stock Nibble_Set (arr [], slot, val)
{
    new
        shamt = (slot & 7) * 4, // (slot % 8) * 4
        s = slot >>> 3;
    arr [s] &= ~(0x0F << shamt); // Set target "cell" to 0.
    //arr [s] |= (val << shamt); // Using this, you have to make sure that val < 16 or other cells may get changed.
    arr [s] |= ((val & 0x0F) << shamt); // This looks more save to me.
}
I'm absolutely not sure if this works. I didn't test it.
Reply
#15

Looks cool.
Reply
#16

Really nice script keep on mrdeath!
Reply
#17

Thanks for the comments.



Quote:
Originally Posted by Y_Less
Посмотреть сообщение
I would also point out this:

pawn Код:
#define Bit16_Get(%0,%1) (%0[(%1)>>>1]&(0x0000FFFF<<(((%1)&1)<<4)))
Directly based on the code in y_bits, which leads instantly on to:

pawn Код:
#define Bit4_Get(%0,%1) (%0[(%1)>>>3]&(0x0000000F<<(((%1)&7)<<2)))
As the basis of a nibble system.

In general (where "%2" is the size of data, only works with powers of 2). Note that this assumes a 32-bit cell size (the full generic solution is harder).

pawn Код:
#define BitX_Mask(%2)   ((1 << (%2)) - 1)
#define BitX_Log(%2)    log2(%2)
#define BitX_Shift(%2)  (5 - BitX_Log(%2))
#define BitX_Filter(%2) ((1 << BitX_Shift(%2)) - 1)

#define BitX_Get(%0,%1,%2) (%0[(%1) >>> BitX_Shift(%2)] & (BitX_Mask(%2) << (((%1) & BitX_Filter(%2)) << BitX_Log(%2))))
I've added extra brackets for convenience, and you're best off pre-calculating bits. For reference, here is log2 (base 2 logarithm) for relevant values:

pawn Код:
1 = 0
2 = 1
4 = 2
8 = 3
16 = 4
32 = 5
To be honest I don't understand, and I think I won't for some time... xD
Reply
#18

Pretty nice Mr Death, giving us great releases I'm going to look around this code then test it for myself. Yeah, great job.

Reply
#19

Is that possible to do:
pawn Код:
#define Bit16_Get(%0,%1) \
                (((DBITS_VAR=(%1)),DBITS_VAR&1)?(%0[(DBITS_VAR)/2]&0x0000FFFF):((%0[(DBITS_VAR)/2]>>>16)&0x0000FFFF))
to fix the i++ bug?

Also, I've been thinking of 64-bit integers some days ago, but I think it is too hard to code
Reply
#20

PAWN is limited to 32-bit integers so I don't think that's possible as long as you don't use any plugin support.
Reply


Forum Jump:


Users browsing this thread: 2 Guest(s)