[Include] beta ibits
#1

Introduзгo

O que й o ibits ? ele й um manipulador de bits, funciona de forma que vocк consiga executar as mesmas operaзхes com manipulaзгo de variбveis, sу que com uma certa economia em questгo bytes.

Ele estб sendo lanзado como versгo de testes, entгo hб possibilidades de sofrer alteraзхes futuramente para melhorar sua sintaxe e possivelmente seu funcionamento.


Include
ibits.inc

pawn Код:
/*
* --- iBits ---
* Por Willian Luigi
* Atualizado - [15/10/2013]
* Atualizado - [04/11/2013]
* [iPs]TeaM
* mixmusicas.com.br ipsbr.net
*
*/

#if defined _ibits_included
#endinput
#endif
#define _ibits_included
#pragma library ibits

enum IPSI_BITS (<<=1)
{
    bit16 = 2,
    bit8,
    bit4,
    bit2,
    bit1
};

stock partBits(n,inicio,fim) {
    return (n >> inicio) & ~(~0 << (fim - inicio + 1));
}

// 1 bit
#define array_bit1:%0<%1,%2> \
                    %0[(%1 + cellbits) / cellbits][(%1 + cellbits) / cellbits]
#define bit1:%0<%1> \
                    %0[(%1 + cellbits) / cellbits]
#define getBit1(%0,%1) \
                    ( ( %0[%1 / cellbits] >> %1 ) & 0x01 )
stock setBit1(arr[], slot, val)
{
    return val ? (arr[slot / cellbits] ^= ((_:val % 0x02) << slot)) : (arr[slot/cellbits] &= ~(0x01 << slot));
}

// 2 bits
#define bit2:%0<%1> \
                    %0[(%1 + _:bit2) / _:bit2]
#define getBit2(%0,%1) \
                    ( %0[%1 / _:bit2] >> ( %1 << 1 ) ) % 0x04
stock setBit2(arr[], slot, val)
{
    return arr[slot/_:bit2] =  ((arr[slot/_:bit2] & ~(0x03 << (slot << 1)))) | ((_:val % 0x04) << (slot << 1));
}

// 4 bits
#define bit4:%0<%1> \
                    %0[(%1 + _:bit4) / _:bit4]
#define getBit4(%0,%1) \
                    ( %0[%1 / _:bit4] >> ( %1 << 2 ) ) % 0x10
stock setBit4(arr[], slot, val)
{
    return arr[slot/_:bit4] =  ((arr[slot/_:bit4] & ~(0xF << (slot << 2)))) | ((_:val % 0x10) << (slot << 2));
}

// 16 bits
#define bit16:%0<%1> \
                    %0[(%1 + _:bit16) / _:bit16]
#define getBit16(%0,%1) \
                    ( %0[%1 / _:bit16] >> ( %1 << 4 ) ) % (65536)
stock setBit16(arr[], slot, val)
{
    return arr[slot/_:bit16] =  ((arr[slot/_:bit16] & ~(65535 << (slot << 4)))) | ((_:val % 65536) << (slot << 4));
}


//geral bits
#define bit_var%0<%1@%2> \
                    new %0[(%1 + _:%2) / _:%2]
#define bit_var_set:%3(%0,%1,%2) \
                    setBit%3(%0,%1,%2)
#define bit_var_get:%2(%0,%1) \
                    getBit%2(%0,%1)

#define bit_array%0<%1,%2@%3> \
                    new %0[(_:%1)][(_:%2 + _:%3) / _:%3]
#define bit_array_set:%4(%0,%1,%2,%3) \
                    setBit%4(%0[%1],_:%2,%3)

#define bit_array_get:%3(%0,%1,%2) \
                    getBit%3(%0[%1],_:%2)


// funcionalidades

#define size(%0,%1) \
                (sizeof(%0) * _:%1) //Retorna o tamanho da estrutura


stock bool:any(arr[], slot, IPSI_BITS: type) //Verifica se algum bit da sequкncia estб ativo(1)
{
    switch(_:type)
    {
        case bit16: return bool:(getBit16(arr, slot) ^ 0b0) && 1;
        case bit4: return bool:(getBit4(arr, slot) ^ 0b0) && 1;
        case bit2: return bool:(getBit2(arr, slot) ^ 0b0) && 1;
        case bit1: return bool:(getBit1(arr, slot) ^ 0b0) && 1;
        default: return false;
    }
    return false;
}
stock bool:none(arr[], slot, IPSI_BITS: type) //Verifica se nenhum bit da sequкncia estб ativo(1)
{
    switch(_:type)
    {
        case bit16: return bool:(!(getBit16(arr, slot) ^ 0b0)) && 1;
        case bit4: return bool:(!(getBit4(arr, slot) ^ 0b0)) && 1;
        case bit2: return bool:(!(getBit2(arr, slot) ^ 0b0)) && 1;
        case bit1: return bool:(!(getBit1(arr, slot) ^ 0b0)) && 1;
        default: return false;
    }
    return false;
}

O ibits foi separado por:
Код:
1 bit		|	Variбveis booleanas, sу recebem 1 ou 0
2 bits		|	Variбveis que aceitam atй 3 valores(0, 1, 2, 3)
4 bits		|	Variбveis que aceitam atй 15 valores.
16 bits		|	Variбveis que aceitam atй 65535 valores.
O uso da include й simples e de fбcil compreensгo.
Para os muitos que nгo entendem do assunto, eu vou explicar de uma forma bem simples.


Quando vocк cria um vetor com valor de MAX_PLAYERS, vocк estб criando uma variбvel
que suportarб 32 bits multiplicados pelo tamanho dela, MAX_PLAYERS = 500,
logo temos 500 valores de 32bits, oque seria um valor muito, muito grande, que muitas vezes nгo sгo utilizados nem 30% disto.

Exemplo de uso visto normalmente:
pawn Код:
new admin[MAX_PLAYERS]; // 500
admin[playerid] = 5;
Em muitas vezes vocкs utilizam coisas do gкnero, onde vocк criou um vetor de 500 valores, onde cada valor contйm 32 bits.
Код:
00000000000000000000000000000000 //32 bits
Quando vocк seta o valor da variбvel admin para 5, vocк estб alterando o valor de nulo para:
Код:
00000000000000000000000000000101 //32 bits
Como vocкs podem perceber, 5 (101 em binбrio) foi um valor muito repugnante setado perto dos 32 bits. Isso indica que vocк alterou 3 bits apenas, lhe restando mais 29 sem uso, que normalmente nunca sгo utilizados ao longo do cуdigo inteiro.
Isso faz com que vocк ocupe mais memуria do que o necessбrio na maioria dos casos.



Utilizando ibits, vocк poderб manter o controle disto.
pawn Код:
new bit4:admin<MAX_PLAYERS>; // 250
setBit4(admin, 0, 5); //player 0
setBit4(admin, 1, 5); //player 1
Percebam a diferenзa logo no inicio, nгo temos mais um vetor de 500 valores, mas sim de 250, a metade do que havнamos requisitado no teste passado.
Eu setei 2 jogadores(0 e 1) para admin nнvel 5, percebam a diferenзa dos bits:
Код:
00000000000000000000000001010101 //32 bits
Percebam que o nъmero dos bits utilizados aumentou, pois eu setei 2 valores com um certo X limite de possibilidades para uma mesma variбvel, apenas alterando sua posiзгo na escala dos bits.

Isto faz com que possamos utilizar variбveis com valores normais economizando memуria.



Exemplo de uso:
Criando 'sistema' de admin, utilizando icmd 7.0

pawn Код:
new bit4: admin <MAX_PLAYERS>;
new bit1: adminTrabalhando <MAX_PLAYERS>;

public OnPlayerCommandText(playerid, commandid, params[])
{
    switch(commandid)
    {
        case iscmd("t,r,a,b,a,l,h,a,r"):
        {
            //seta a booleana do admin trabalhando para a inversa do valor antigo.
            setBit1(adminTrabalhando, playerid, !getBit1(adminTrabalhando, playerid));
        }
        case iscmd("m,a,t,a,r"):
        {
            if (!params[0]) SendClientMessage(playerid, -1, "Syntax: /matar [id]");

            //lendo valor da variбvel admin do playerid, para saber se ele tem nнvel..
            if (!getBit4(admin, playerid)) SendClientMessage(playerid, -1, "Vocк nгo й um admin.");

            //Lendo valor da var adminTrabalhando, para saber se ele estб em modo de trabalho.
            if (!getBit1(adminTrabalhando, playerid)) SendClientMessage(playerid, -1, "Vocк nгo estб em modo trabalho.");

            SetPlayerHealth(strval(params), 0.0);
        }
        case iscmd("a,d,m,i,n"):
        {
            if (!params[0]) SendClientMessage(playerid, -1, "Syntax: /admin [value]");

            if (0 > strval(params) > 5) SendClientMessage(playerid, -1, "Nнvel invбlido.");

            //setando valor da variбvel para a quantidade digitada
            setBit4(admin, playerid, strval(params));

            SendClientMessage(playerid, -1, "Vocк alterou seu nнvel de admin.");
        }
    }
}


Notas finais

O ibits foi feito de forma simples, mas mantendo o foco na qualidade, como estб versгo й apenas um teste,
a prуxima e possнvel atualizaзгo terб funcionalidades extras para melhor manipulaзгo dos dados.

Como vocкs viram, й sim algo de grande utilidade.



Crйditos
  • Willian Luigi
  • ipsBruno
  • [iPs]TeaM
Reply
#2

Em caso de variбveis booleanas, este sistema pode economizar seu script em questгo de uso de memуria em atй 32 vezes. Ocupando menos AMX, ocupando menos memуria RAM.


Alйm de ser bastante rбpido, em alguns testes, a velocidade sugerida foi de trкs vezes superior a do rBits.

Reply
#3

eita, agr sim os sistemas vao ser mt melhores..

so nao tem script de qualidade agora quem nao quer..

Parabens pra vc's 2
Reply
#4

Bastante interessante, isso serб bastante ъtil para reduzir atй metade do AMX podendo obter mais performance e todos sabemos que uma boa performance em um servidor grande й bastante bom.
Reply
#5

Код:
1 bit		|	Variбveis booleanas, sу recebem 1 ou 0
2 bits		|	Variбveis que aceitam atй 3 valores(0, 1, 2, 3)
4 bits		|	Variбveis que aceitam atй 15 valores.
16 bits		|	Variбveis que aceitam atй 65535 valores.
A partir de 2 bits, vocк diz que recebe atй X valores. Esses X valores sгo a quantia de cйlulas em que se pode armazenar ou й os nъmeros mesmo (e.i: 4bits sу suporta atй o nъmero 15) ?
Reply
#6

Quote:
Originally Posted by Falcon.
Посмотреть сообщение
Код:
1 bit		|	Variбveis booleanas, sу recebem 1 ou 0
2 bits		|	Variбveis que aceitam atй 3 valores(0, 1, 2, 3)
4 bits		|	Variбveis que aceitam atй 15 valores.
16 bits		|	Variбveis que aceitam atй 65535 valores.
A partir de 2 bits, vocк diz que recebe atй X valores. Esses X valores sгo a quantia de cйlulas em que se pode armazenar ou й os nъmeros mesmo (e.i: 4bits sу suporta atй o nъmero 15) ?
Sгo os valores mesmo, como eu citei do lado. 1 bit armazena apenas true ou false, 2 bits armazena (0, 1, 2, 3), 4 bits armazenam atй 15(0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15) e por fim 16 bits que armazenam 65535 valores, nгo achei necessбrio incluir o de 8 bits e o de 32, sгo poucos que utilizam valores prуximos de 65535, imagine maior, e valores com 8 bits podem ser simplesmente substituнdos por char:
pawn Код:
new var[20 char];
Reply
#7

Mas por exemplo, o dinheiro do GTA-SA suporta atй 8 dнgitos. Entгo pode-se armazenar 99999999, por isso perguntei =)

Em caso de arrays a include nгo funciona nй ? tipo:

PHP код:
enum debug
{
    
var1,
    
Float:var2,
    
var3[35],
    
bool:var4
}

new 
Ddebug[30][debug]; 
Reply
#8

Quote:
Originally Posted by Falcon.
Посмотреть сообщение
Mas por exemplo, o dinheiro do GTA-SA suporta atй 8 dнgitos. Entгo pode-se armazenar 99999999, por isso perguntei =)

Em caso de arrays a include nгo funciona nй ? tipo:

PHP код:
enum debug
{
    
var1,
    
Float:var2,
    
var3[35],
    
bool:var4
}
new 
Ddebug[30][debug]; 
Em parte sim, em parte nгo, veja um exemplo:
pawn Код:
#define admin   (0)
#define level   (1)

new bit4:PLAYERS[MAX_PLAYERS]<1>;

setBit4(PLAYERS[playerid], admin, 5);
setBit4(PLAYERS[playerid], level, 2);
Tem utilidade, mas vocк precisaria organizar seu pensamento de outra forma, por assim dizer.
OBS: eu usei #define por usar, vocк pode utilizar enum...
Reply
#9

muito bom parabens
nгo posso da rep
Reply
#10

Boa ira ajudar a muitos
Reply
#11

pawn Code:
enum IPSI_BITS (<<=1)

Poderia explicar qual a influкncia do cуdigo entre parкnteses? Jб vi em alguns scripts do Y_Less mas nгo sei nada a respeito.
Reply
#12

Quote:
Originally Posted by zPain
View Post
pawn Code:
enum IPSI_BITS (<<=1)

Poderia explicar qual a influкncia do cуdigo entre parкnteses? Jб vi em alguns scripts do Y_Less mas nгo sei nada a respeito.
Й que como eu separei os bits em 4 tipos, 1/2/4/16 eu precisava de um valor para calcular o limite deles.

1 = 32 bits, pois 1 bit poderia ser criado um vetor de 32 espaзos com uma variбvel.
2 = 16 bits, pois 2 bits ocupam um espaзo maior, logo 32 / 2 = 16, conseguiria dividir em 16 espaзos numa variбvel sу.

Essa manhг utilizada (<<=1), foi pra indicar que cada valor do enum seria deslocado 1 casa para a esquerda a partir do primeiro.
O primeiro valor era 2, logo o segundo seria 4, pois 0010 << 1 = 0100, e assim adiante.
0100 << 1 = 1000
1000 << 1 = 10000

Reply
#13

Entendi. Fiz um teste aqui e funcionou de acordo.
Reply
#14

Quote:
Originally Posted by Willian_Luigi
Посмотреть сообщение
Em parte sim, em parte nгo, veja um exemplo:
pawn Код:
#define admin   (0)
#define level   (1)

new bit4:PLAYERS[MAX_PLAYERS]<1>;

setBit4(PLAYERS[playerid], admin, 5);
setBit4(PLAYERS[playerid], level, 2);
Tem utilidade, mas vocк precisaria organizar seu pensamento de outra forma, por assim dizer.
OBS: eu usei #define por usar, vocк pode utilizar enum...
ah sim, mais tarde vou tentar fazer umas gambiarras aqui, rs.

Ficou muito bom, parabйns
Reply
#15

Meu que bom que temos membros inteligentes aqui agora, tanto conhecimento esta vendo agora.
Parece que a board estб melhorando.

Boa @Willl, manja dos paranaue
Reply
#16

Bastante interessante Willian, Уtimo trabalho!
Reply
#17

Queria entender deste assunto, porйm estou iniciando nele..

Tenho umas pequenas dъvidas em seu cуdigo...

Como vocк limitou para aceitar 3 valores?
pawn Code:
new bit2:admin<MAX_PLAYERS>;
Eu olhando cуdigo fone nгo vi nada de diferente:
pawn Code:
admin(MAX_PLAYERS + _:bit2) / _:bit2]
Queria saber como conseguiu diminuir .amx com este cбlculo :O


Mas enfim, bom trabalho Luigui :P

+Reputaзгo pra tu
Reply
#18

Quote:
Originally Posted by zSuYaNw
View Post
Tenho umas pequenas dъvidas em seu cуdigo...

Como vocк limitou para aceitar 3 valores?
pawn Code:
new bit2:admin<MAX_PLAYERS>;
Eu olhando cуdigo fone nгo vi nada de diferente:
pawn Code:
admin(MAX_PLAYERS + _:bit2) / _:bit2]
Queria saber como conseguiu diminuir .amx com este cбlculo :O
Matemбtica na hora do get / set, veja:
Code:
VALOR % 0x04
quando o membro utilizar um valor que seja acima de trкs, automaticamente este valor serб reduzido para a contagem normal, que seria de 0 a 3.

Code:
0 % 4 = 0
1 % 4 = 1
2 % 4 = 2
3 % 4 = 3
4 % 4 = 0
5 % 4 = 1
//...
A questгo do amx vem com o tamanho da var criada:
Code:
#define bit2:%0<%1> \
                        %0[(%1 + _:bit2) / _:bit2]
Como eu expliquei para o zPain, bit2 tem o valor de 16, logo se eu der entrada em uma var

pawn Code:
new bit2: var <2>;
Estarei fazendo:

Code:
2 + 16 = 18
18 / 16 = 1
Logo, vocк estб indicando que sу precisa de um vetor de 1 valor.

Oque seria diferente de uma var padrгo:
pawn Code:
new var[2];
Raciocinando da forma como expliquei na primeira pбgina, se tu criar uma variбvel
pawn Code:
new var[MAX_PLAYERS]; // 500 valores
para a diferenзa de
pawn Code:
new bit2:var<MAX_PLAYERS>; //32 valores
bastante diferente.
Reply
#19

Willian, caso eu tiver uma variбvel e for usar a include terei que alterб-la para array ?

PHP Code:
new minhavar;
//para:
new bit2:minhavar<1>; 
Quando vou criar sem o <> dб argument type mismatch, ao usar o setBit2 por exemplo.

----------

Teria como vocк criar para suportar outros valores, eu particularmente tenho variбveis que armazenam no mбximo 300, outras 700 (numerais). E acho que usar uma que suporta 65535 seria um desperdнcio (O que queremos evitar com a include).


--------------

Saberia me dizer se й possнvel otimizar algo isso, com ou sem a sua include ? (sem packet strings)

PHP Code:
enum samp
{
    
forum[33],
    
gtasa[33]
}
new 
seila[10][samp];
// OU
new forum[10][33];
new 
gtasa[10][33]; 
Reply
#20

O tipo da var precisa ser especificado sim, para manter o controle entre 1/2/4/8/16 bits.
E vocк precisa indicar o uso da mesma, se vocк vai usar apenas 1 vez

pawn Code:
new bit2:var<1>;
Se o uso for maior, jб sabe como fazer.
Como por exemplo, para jogadores:
pawn Code:
new bit2:var<MAX_PLAYERS>;
A respeito dos tipos adicionais, isso seria causaria quebras na hora da leitura/escrita dos bits.

Podemos arranjar soluзхes para umas coisas que vocк citou, agora para outras й algo a se pensar, vocк tem algum contato ? pode mandar-me por PM algo como Skype, que ai podemos discutir a respeito.

Abraзos.
Reply


Forum Jump:


Users browsing this thread: 3 Guest(s)