1
15
16 Function daj_velicinu_niza() Which Returns Integer32 Is External;
18 Function kopiraj_niz_na_adresu(
19 PointerToInteger32 adresa) Which Returns Nothing Is External;
20 Function printString(PointerToCharacter str) Which Returns Nothing Is External;
21 Function printInteger(Integer32 n) Which Returns Nothing Is External;
22 Function printFloat(Decimal32 x) Which Returns Nothing Is External;
23 Function pocni_mjerenje_vremena() Which Returns Nothing Is External;
24 Function zavrsi_mjerenje_vremena() Which Returns Nothing Is External;
25 Function izvijesti_o_obrnuto_poredanim_nizovima(
26 Integer32 n) Which Returns Nothing Is External;
27 Function
28 izvijesti_o_poredanim_nizovima(Integer32 n) Which Returns Nothing Is External;
29 Function izvijesti_o_pokretanju_QuickSorta(
30 Integer32 n) Which Returns Nothing Is External;
31 Function izvijesti_o_pokretanju_MergeSorta(
32 Integer32 n) Which Returns Nothing Is External;
33 Function izvijesti_o_pokretanju_SelectSorta(
34 Integer32 n) Which Returns Nothing Is External;
35 Function
36 izvijesti_o_broju_usporedbi(Integer32 n) Which Returns Nothing Is External;
37 Function
38 izvijesti_JavaScript_o_nedostatku_memorije() Which Returns Nothing Is External;
39
40 Integer32 DEBUG : = 0, broj_mjerenja : = 0;
46 Function zauzmi_memorijske_stranice(Integer32 broj_stranica) Which Returns
48 PointerToCharacter
49 Does { Integer32 nova_adresa_u_stranicama
54 : = asm_i32 (R"multiline(
64 ;; Sintaksu za višelinijske stringove preuzeo sam iz C++11-a, ta mi
65 ;; se sintaksa za višelinijske stringove nekako najviše sviđa.
66 (memory.grow
67 (i32.load %broj_stranica) ;; Compiler će zamijeniti `%broj_stranica` s
68 ;; asemblerskim kodom koji predstavlja pokazivač
69 ;; na varijablu `broj_stranica`. Razumijem da
70 ;; način na koji GCC i CLANG compileri za C++
71 ;; implementiraju inline assembly ima svoje
72 ;; prednosti, ali to je teže i za koristiti
73 ;; (pogotovo za ovakve jednostavne umetnute
74 ;; asemblerske kodove) i za implementirati u
75 ;; compileru.
76 )
77 )multiline");
78 If nova_adresa_u_stranicama = -1 Then { Return(-1); }
83 EndIf; Return nova_adresa_u_stranicama * 64 * 1024; }
89 EndFunction;
90
91 Integer32 velicina_niza;
92 PointerToInteger32 originalni_niz,
93 pomocni_niz;
97 Integer32 broj_obrnuto_poredanih_podniza, broj_vec_poredanih_podniza,
98 broj_pokretanja_QuickSorta, broj_pokretanja_MergeSorta,
99 broj_pokretanja_SelectSorta, broj_usporedbi;
100
101 Decimal32 PRECISION : = 128;
112 Decimal32
113 memoizacija_prirodnog_logaritma[8192];
117 Function Eulerov_broj_na_potenciju(Decimal32 x)
118 Which Returns Decimal32 Is Declared;
120 Function prirodni_logaritam(Decimal32 x) Which Returns Decimal32 Does {
121 broj_usporedbi += 1;
122 If x < 1 Then { Return(-prirodni_logaritam(1 / x)); }
123 EndIf;
124 broj_usporedbi += 2;
125 If(x < 8192 and
126 not(memoizacija_prirodnog_logaritma[asm_f32( "(f32.nearest (f32.load %x))")] = 0)) Then {
129 Return
130 memoizacija_prirodnog_logaritma[asm_f32("(f32.nearest (f32.load %x))")];
131 }
132 EndIf;
133 broj_usporedbi += 1;
134 If x > 8192 Then {
135 Return 1 + prirodni_logaritam(x / Eulerov_broj_na_potenciju(1));
136 }
137 EndIf;
138 Decimal32 zbroj : = 0, epsilon : = (x - 1) / (5 * PRECISION), i : = 1;
141 While(epsilon > 0 and i < x) or (epsilon < 0 and i > x) Loop {
142 broj_usporedbi += 4;
143 zbroj += epsilon / i;
144 i += epsilon; }
148 EndWhile;
149 broj_usporedbi += 1;
150 If x < 8192 Then {
151 Return
152 memoizacija_prirodnog_logaritma[asm_f32("(f32.nearest (f32.load %x))")]
153 : = zbroj;
154 }
155 EndIf;
156 Return zbroj;
157 }
158 EndFunction;
159
160 Decimal32
161 memoizacija_Eulerovog_algoritma[512];
164 Function abs(Decimal32 x) Which Returns Decimal32 Is
165 Declared;
168 Function Eulerov_broj_na_potenciju(Decimal32 x) Which Returns Decimal32 Does {
169 broj_usporedbi += 2;
170 If(abs(x) < 64 and
171 not(memoizacija_Eulerovog_algoritma
172 [asm_f32("(f32.nearest (f32.mul (f32.const 4) (f32.load %x)))") +
173 256] = 0))
174 Then { Return memoizacija_Eulerovog_algoritma
181 [asm_f32("(f32.nearest (f32.mul (f32.const 4) (f32.load %x)))") + 256];
182 }
183 EndIf;
184 Decimal32 i : = 0, y : = 1, epsilon : = x / PRECISION;
186 While(epsilon > 0 and i < x) or (epsilon < 0 and i > x) Loop {
187 broj_usporedbi += 4;
188 y += epsilon * y;
189 i += epsilon;
190 }
191 EndWhile;
192 broj_usporedbi += 1;
193 If abs(x) < 64 Then {
194 Return memoizacija_Eulerovog_algoritma
195 [asm_f32("(f32.nearest (f32.mul (f32.const 4) (f32.load %x)))") + 256]
196 : = y;
197 }
198 EndIf;
199 Return y;
200 }
201 EndFunction;
202
203 Function abs(Decimal32 x) Which Returns Decimal32 Does {
204 broj_usporedbi += 1;
212 Return(x < 0) ? -x : x; }
216 EndFunction;
217
218 Function ostatak_pri_dijeljenju(Decimal32 x,
219 Decimal32 y) Which Returns Decimal32 Does {
220 broj_usporedbi += 2;
221 If DEBUG = 1 Then {
222 printString("Zatrazen je ostatak pri dijeljenju od brojeva: ");
223 printFloat(x);
226 printFloat(y);
227 printString("Sada ce se program mozda srusiti...");
228 }
229 EndIf;
230 If abs(x / y) > Eulerov_broj_na_potenciju(prirodni_logaritam(2) * 63) Then {
231 Return 0; }
234 EndIf;
235 Return x - y *Integer64(x / y); }
245 EndFunction;
246
247 Function pow(Decimal32 x, Decimal32 y) Which Returns Decimal32 Does {
248 Decimal32 result
249 : = Eulerov_broj_na_potenciju(prirodni_logaritam(abs(x)) * y);
250 broj_usporedbi += 2;
251 Return x =
252 0 ? 0 : ostatak_pri_dijeljenju(x, 2) = 1 and x < 0 ? -result : result;
253 }
254 EndFunction;
255
256 Function okreni_dio_niza(Integer32 donja_granica,
257 Integer32 gornja_granica) Which Returns Nothing Does {
258 Integer32 i : = donja_granica;
259 Integer32 j : = gornja_granica - 1;
260 While i < gornja_granica Loop {
261 ValueAt(pomocni_niz + i) : = ValueAt(originalni_niz + j);
262 j -= 1;
263 i += 1;
264 broj_usporedbi += 1;
265 }
266 EndWhile;
267 i:
268 = donja_granica;
269 While i < gornja_granica Loop {
270 ValueAt(originalni_niz + i) : = ValueAt(pomocni_niz + i);
271 i += 1;
272 broj_usporedbi += 1;
273 }
274 EndWhile;
275 }
276 EndFunction;
277
278 Function hybrid_sort(Integer32 donja_granica, Integer32 gornja_granica,
280 Integer32 dubina_rekurzije) Which Returns Nothing Does {
281 broj_usporedbi += 1;
282 If gornja_granica - donja_granica < 2 Then { Return;
287 }
288 ElseIf gornja_granica - donja_granica = 2 Then { broj_usporedbi += 1;
294 If ValueAt(originalni_niz + donja_granica) >
295 ValueAt(originalni_niz + donja_granica + 1) Then {
296 broj_usporedbi += 1;
297 Integer32 pomocna_varijabla_za_zamijenu
298 : = ValueAt(originalni_niz + donja_granica);
299 ValueAt(originalni_niz + donja_granica)
300 : = ValueAt(originalni_niz + donja_granica + 1);
301 ValueAt(originalni_niz + donja_granica + 1)
302 : = pomocna_varijabla_za_zamijenu;
303 }
304 EndIf;
305 Return;
306 }
307 ElseIf gornja_granica -
308 donja_granica<8 or asm_i32("(global.get $stack_pointer)")> 4 * 1024 -
309 73 Then {
310 broj_usporedbi += 2;
316 Integer32 je_li_niz_vec_poredan : = 1, i : = donja_granica;
317 While i < gornja_granica Loop {
318 broj_usporedbi += 2;
319 If ValueAt(originalni_niz + i) > ValueAt(originalni_niz + i + 1) Then {
320 je_li_niz_vec_poredan:
321 = 0;
322 Break;
323 }
324 EndIf;
325 i += 1;
326 }
327 EndWhile;
328 If je_li_niz_vec_poredan Then {
329 broj_vec_poredanih_podniza += 1;
330 Return;
331 }
332 EndIf;
333 Integer32 je_li_niz_obrnuto_poredan : = 1;
334 i:
335 = donja_granica;
336 While i < gornja_granica Loop {
337 broj_usporedbi += 2;
338 If ValueAt(originalni_niz + i) < ValueAt(originalni_niz + i + 1) Then {
339 je_li_niz_obrnuto_poredan:
340 = 0;
341 Break;
342 }
343 EndIf;
344 i += 1;
345 }
346 EndWhile;
347 If je_li_niz_obrnuto_poredan Then {
348 broj_obrnuto_poredanih_podniza += 1;
349 okreni_dio_niza(donja_granica, gornja_granica);
350 Return;
351 }
352 EndIf;
353 broj_pokretanja_SelectSorta += 1;
354 i:
355 = donja_granica;
356 While i < gornja_granica Loop {
357 broj_usporedbi += 1;
358 Integer32 gdje_je_minimum : = i;
359 Integer32 j : = i + 1;
360 While j < gornja_granica Loop {
361 broj_usporedbi += 2;
362 If ValueAt(originalni_niz + gdje_je_minimum) >
363 ValueAt(originalni_niz + j) Then {
364 gdje_je_minimum
365
375 :
376 = j;
377 }
378 EndIf;
379 j += 1;
380 }
381 EndWhile;
382 Integer32 pomocna_varijabla_za_zamijenu : = ValueAt(originalni_niz + i);
383 ValueAt(originalni_niz + i) : = ValueAt(originalni_niz + gdje_je_minimum);
384 ValueAt(originalni_niz + gdje_je_minimum)
385 : = pomocna_varijabla_za_zamijenu;
386 i += 1;
387 }
388 EndWhile;
389 Return;
390 }
391 EndIf;
392 Decimal32 razvrstanost : = 0;
393 Integer32 i : = donja_granica, je_li_niz_vec_poredan : = 1;
394 While i < gornja_granica - 1 Loop {
395 broj_usporedbi += 2;
396 razvrstanost +=
397 (ValueAt(originalni_niz + i) < ValueAt(originalni_niz + i + 1) or
398 ValueAt(originalni_niz + i) = ValueAt(originalni_niz + i + 1));
399 broj_usporedbi += 1;
400 If ValueAt(originalni_niz + i) > ValueAt(originalni_niz + i + 1) Then {
401 je_li_niz_vec_poredan:
402 = 0;
403 }
404 EndIf;
405 i += 1;
406 }
407 EndWhile;
408 razvrstanost:
409 = razvrstanost / ((gornja_granica - donja_granica - 1) / 2.) - 1;
410 broj_usporedbi += 1;
412 If abs(razvrstanost) > 1 Then {
413 printString("Apsolutna vrijednost razvrstanosti je veca od 1!");
415 printString("Relevantni dio niza iznosi:"); i:
425 = donja_granica;
426 While i < gornja_granica Loop {
427 printInteger(ValueAt(originalni_niz + i));
428 i += 1;
429 }
430 EndWhile;
431 printString("Kraj relevantnog dijela niza!");
432 asm("unreachable");
433 }
434 EndIf;
435 broj_usporedbi += 1;
436 If je_li_niz_vec_poredan and not(razvrstanost = 1) Then {
437 printString("Niz je poredan, a razvrstanost nije 1.");
439 printString("Relevantni dio niza iznosi:");
440 i:
441 = donja_granica;
442 While i < gornja_granica Loop {
443 broj_usporedbi += 1;
444 printInteger(ValueAt(originalni_niz + i));
445 i += 1;
446 }
447 EndWhile;
448 printString("Kraj relevantnog dijela niza!");
449 asm("unreachable");
450 }
451 EndIf;
452 broj_usporedbi += 1;
453 If not(je_li_niz_vec_poredan) and razvrstanost >= 1 Then {
454 printString("Razvrstanost je 1, a niz nije poredan!");
456 printString("Relevantni dio niza iznosi:");
457 i:
458 = donja_granica;
459 While i < gornja_granica Loop {
460 printInteger(ValueAt(originalni_niz + i));
461 i += 1;
462 }
463 EndWhile;
464 printString("Kraj relevantnog dijela niza!");
465 asm("unreachable");
466 }
467 EndIf;
468 Decimal32 razvrstanost_na_potenciju[8] : = {1}; i:
476 = 1;
477 While i < 8 Loop {
478 broj_usporedbi += 1;
479 razvrstanost_na_potenciju[i]
480 : = razvrstanost_na_potenciju[i - 1] * razvrstanost;
481 i += 1;
482 }
483 EndWhile;
484 Decimal32 polinom_pod_apsolutnom
488 : = 2.38854 * razvrstanost_na_potenciju[7] -
489 0.284258 * razvrstanost_na_potenciju[6] -
490 1.87104 * razvrstanost_na_potenciju[5] +
491 0.372637 * razvrstanost_na_potenciju[4] +
492 0.167242 * razvrstanost_na_potenciju[3] -
493 0.0884977 * razvrstanost_na_potenciju[2] + 0.315119 * razvrstanost;
494 Decimal32 Eulerov_broj_na_koju_potenciju
495 : = (prirodni_logaritam(gornja_granica - donja_granica) +
496 prirodni_logaritam(
497 prirodni_logaritam(gornja_granica - donja_granica))) *
498 1.05 +
499 (prirodni_logaritam(gornja_granica - donja_granica) -
500 prirodni_logaritam(
501 prirodni_logaritam(gornja_granica - donja_granica)) -
502 prirodni_logaritam(2)) *
503 0.9163 * abs(polinom_pod_apsolutnom);
504 Decimal32 koliko_usporedbi_ocekujemo_od_QuickSorta
505 : = Eulerov_broj_na_potenciju(Eulerov_broj_na_koju_potenciju);
506 Decimal32 koliko_usporedbi_ocekujemo_od_MergeSorta
507 : = (mod(broj_mjerenja, 2) + 1) *
508 (gornja_granica -
509 donja_granica) * prirodni_logaritam(gornja_granica - donja_granica) /
523 prirodni_logaritam(2);
524 broj_usporedbi += 1;
526 If razvrstanost >= 1 Then {
527 broj_vec_poredanih_podniza += 1;
528 Return;
529 }
530 ElseIf razvrstanost <= -1 Then {
531 broj_usporedbi += 1;
532 broj_obrnuto_poredanih_podniza += 1;
533 okreni_dio_niza(donja_granica, gornja_granica);
534 Return;
535 }
536 ElseIf(koliko_usporedbi_ocekujemo_od_MergeSorta <
537 koliko_usporedbi_ocekujemo_od_QuickSorta or
538 dubina_rekurzije > pow(2, 18 - prirodni_logaritam(velicina_niza) /
539 prirodni_logaritam(2))
540 ) and
548 not(gornja_granica - donja_granica =
549 velicina_niza and not(mod(broj_mjerenja, 3)))
550 Then {
553 broj_usporedbi += 1 + 1 + 1 + 1;
554 broj_pokretanja_MergeSorta += 1;
560 Integer32 sredina_niza : = (gornja_granica + donja_granica) / 2;
561 hybrid_sort(donja_granica, sredina_niza, dubina_rekurzije + 1);
568 hybrid_sort(sredina_niza, gornja_granica, dubina_rekurzije + 1);
569 Integer32 i : = donja_granica;
572 Integer32 gdje_smo_u_prvom_nizu : = donja_granica;
573 Integer32 gdje_smo_u_drugom_nizu : = sredina_niza;
574 While i < gornja_granica Loop {
575 broj_usporedbi += 3;
576 If(gdje_smo_u_prvom_nizu =
577 sredina_niza or
578 ValueAt(originalni_niz + gdje_smo_u_drugom_nizu) <
579 ValueAt(originalni_niz + gdje_smo_u_prvom_nizu)) and
580 gdje_smo_u_drugom_nizu < gornja_granica Then {
581 ValueAt(pomocni_niz + i)
582 : = ValueAt(originalni_niz + gdje_smo_u_drugom_nizu);
583 gdje_smo_u_drugom_nizu += 1;
584 }
585 Else {
586 ValueAt(pomocni_niz + i)
587 : = ValueAt(originalni_niz + gdje_smo_u_prvom_nizu);
588 gdje_smo_u_prvom_nizu += 1;
589 }
590 EndIf;
591 i += 1;
592 }
593 EndWhile;
594 i:
595 = donja_granica;
596 While i < gornja_granica Loop {
597 broj_usporedbi += 1;
598 ValueAt(originalni_niz + i) : = ValueAt(pomocni_niz + i);
599 i += 1;
600 }
601 EndWhile;
602 Return;
603 }
604 Else { broj_pokretanja_QuickSorta += 1;
606 Integer32 pivot : = ValueAt(originalni_niz + gornja_granica - 1);
613 Integer32 i : = donja_granica - 1;
614 Integer32 j : = donja_granica;
615 Integer32 pomocna_varijabla_za_zamijenu;
616 While j < gornja_granica - 1 Loop {
617 broj_usporedbi += 2;
618 If ValueAt(originalni_niz + j) < pivot Then {
619 i += 1;
620 pomocna_varijabla_za_zamijenu:
621 = ValueAt(originalni_niz + i);
622 ValueAt(originalni_niz + i) : = ValueAt(originalni_niz + j);
623 ValueAt(originalni_niz + j) : = pomocna_varijabla_za_zamijenu;
624 }
625 EndIf;
626 j += 1;
627 }
628 EndWhile;
629 pomocna_varijabla_za_zamijenu:
630 = ValueAt(originalni_niz + i + 1);
631 ValueAt(originalni_niz + i + 1)
632 : = ValueAt(originalni_niz + gornja_granica - 1);
633 ValueAt(originalni_niz + gornja_granica - 1)
634 : = pomocna_varijabla_za_zamijenu;
635 Integer32 gdje_je_pivot : = i + 1;
636 hybrid_sort(donja_granica, gdje_je_pivot, dubina_rekurzije + 1);
637 hybrid_sort(gdje_je_pivot, gornja_granica, dubina_rekurzije + 1);
638 Return;
639 }
640 EndIf;
641 printString("Izgleda da compiler nije ispravno "
643 "preveo kontrolne strukture!");
644 asm("unreachable");
645 }
646 EndFunction;
647
648 Function pocetna_AEC_funkcija() Which Returns Nothing Does {
650 If originalni_niz = -1 or pomocni_niz = -1 Then {
651 Return; }
654 EndIf;
655 If abs(pow(3, 3) - 27) > 2 Then { printString("Izgleda da matematicke funkcije ne funkcioniraju dobro.");
659 printString("pow(3, 3) =");
660 printFloat(pow(3, 3));
661 }
662 EndIf;
663 Integer32 prijasnja_velicina_niza : = velicina_niza;
665 velicina_niza:
666 = daj_velicinu_niza();
667 If velicina_niza / (64 * 1024 / 4) +
669 not(not(mod(velicina_niza, 64 * 1024 / 4))) >
670 prijasnja_velicina_niza / (64 * 1024 / 4) +
671 not(not(mod(prijasnja_velicina_niza, 64 * 1024 / 4))) or
672 prijasnja_velicina_niza = 0 Then {
673 originalni_niz:
674 = zauzmi_memorijske_stranice(4 * velicina_niza / (64 * 1024) +
675 not(not(mod(velicina_niza, 64 * 1024 / 4))));
676 pomocni_niz:
677 = zauzmi_memorijske_stranice(4 * velicina_niza / (64 * 1024) +
678 not(not(mod(velicina_niza, 64 * 1024 / 4))));
679 If originalni_niz = -1 or pomocni_niz = -1 Then {
680 printString("Nema dovoljno memorije za nastavak programa!?");
681 izvijesti_JavaScript_o_nedostatku_memorije();
682 asm("unreachable"); }
684 EndIf;
685 }
686 EndIf;
687 kopiraj_niz_na_adresu(originalni_niz);
690 broj_obrnuto_poredanih_podniza:
692 = broj_vec_poredanih_podniza : = broj_pokretanja_QuickSorta
693 : = broj_pokretanja_MergeSorta : = broj_pokretanja_SelectSorta
694 : = broj_usporedbi
695 : = 0; broj_mjerenja += 1;
699 pocni_mjerenje_vremena();
700 hybrid_sort(0, velicina_niza, 0);
701 zavrsi_mjerenje_vremena();
702 izvijesti_o_obrnuto_poredanim_nizovima(broj_obrnuto_poredanih_podniza);
705 izvijesti_o_poredanim_nizovima(broj_vec_poredanih_podniza);
706 izvijesti_o_pokretanju_QuickSorta(broj_pokretanja_QuickSorta);
707 izvijesti_o_pokretanju_MergeSorta(broj_pokretanja_MergeSorta);
708 izvijesti_o_pokretanju_SelectSorta(broj_pokretanja_SelectSorta);
709 izvijesti_o_broju_usporedbi(broj_usporedbi);
710 Integer32 i : = 0;
712 While i < velicina_niza - 1 Loop {
713 If ValueAt(originalni_niz + i) > ValueAt(originalni_niz + i + 1) Then {
714 printString("Niz nije poredan!");
715 asm("unreachable");
716 }
717 EndIf;
718 i += 1;
719 }
720 EndWhile;
721 }
722 EndFunction;
723