Ahojky, chcel by som vám ukázať jeden stock čo som nakódil, fillArray(), ktorý dokáže vynulovať pole, resp. nastaviť každý prvok v poli na nejakú hodnotu.
Je to užitočné v tom, že je to rýchlejšie než použitie loopu, pomer rýchlosti sa odvíja od počtu prvkov, kde pre 100 prvkové pole je fillArray() 18x rýchlejší, pre 1000 a viac prvkové ~65krát rýchlejší.
Použitie
main() {
new pole[] = {1,2,3,4};
fillArray(pole, 55); // nastavi kazdu hodnotu v poli na 55
for (new i; i < sizeof (pole); i++) // vypise cele pole, teda 4 riadky s textom "55"
printf("%d", pole[i]);
}
Pre viac-rozmerné polia treba použiť cyklus fillArray()ov.
main() {
pole[][] = {{1,2}, {3,4}};
for (new i; i < sizeof (pole); i++)
fillArray(pole[i]); // default hodnota je 0, toto teda vynuluje cele pole
for (new i; i < sizeof (pole); i++)
for (new j; j < sizeof (pole[]); j++)
printf("%d", pole[i][j]);
}
Speedtest
Ťažko sa získavajú grafy pre rôzne veľkosti polí (lebo pawn nemá polia s dynamickou veľkosťou), ale pár manuálnymi pokusmi som zistil, že s kódom nižšie je fillArray() rýchlejší okolo 18x pre polia o veľkosti 100 prvkov, pre polia okolo 1000 prvkov okolo 70 krát rýchlejší a pre viac (až po 10 000 000 prvkové polia) to už osciluje medzi 60-65-70krát.
Získal som:
[19:45:51] Klasicka metoda: 74012 tickov
[19:45:52] fillArray() metoda: 1075 tickov
Pre kód:
main() {
#define MAX 1234567
new pole[2000];
new tick = GetTickCount();
for (new i; i < MAX; i++)
for (new j; j < sizeof(pole); j++)
pole[j] = 1;
printf("Klasicka metoda: %d tickov", GetTickCount() - tick);
tick = GetTickCount();
for (new i; i < MAX; i++)
fillArray(pole, 2);
printf("fillArray() metoda: %d tickov", GetTickCount() - tick);
}
Kód
(môžete copy-paste do modu)
stock fillArray(array[], value = 0, size = sizeof(array)) {
new cip;
size *= 4;
cip = get_code_relative_address();
#emit load.s.alt cip
#emit lctrl 6
#emit add
#emit add.c 56
#emit stor.s.pri cip
#emit load.s.alt size
#emit sref.s.alt cip
#emit load.s.alt array
#emit load.s.pri value
#emit fill 0
}
stock get_code_relative_address() {
new dat, cod;
#emit lctrl 1
#emit neg
#emit add.c 12
#emit stor.s.pri cod
#emit lref.s.pri cod
#emit stor.s.pri cod
#emit lctrl 1
#emit neg
#emit add.c 16
#emit stor.s.pri dat
#emit lref.s.pri dat
#emit stor.s.pri dat
return cod - dat;
}
Resp., aktuálna verzia (aj s pár vysvetľujúcimi komentmi) tu. Ó, Majstre! Uč ma!
Krátke vysvetlenie pre tých, čo vedia čo znamená slovo "assembler", ale nevedia čítať emit.