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_JavaScript_o_nedostatku_memorije() Which Returns Nothing Is External;
37
38 Integer32 DEBUG : = 0, broj_mjerenja : = 0;
44 Function zauzmi_memorijske_stranice(Integer32 broj_stranica) Which Returns
46 PointerToCharacter
47 Does { Integer32 nova_adresa_u_stranicama
52 : = asm_i32 (R"multiline(
62 ;; Sintaksu za višelinijske stringove preuzeo sam iz C++11-a, ta mi
63 ;; se sintaksa za višelinijske stringove nekako najviše sviđa.
64 (memory.grow
65 (i32.load %broj_stranica) ;; Compiler će zamijeniti `%broj_stranica` s
66 ;; asemblerskim kodom koji predstavlja pokazivač
67 ;; na varijablu `broj_stranica`. Razumijem da
68 ;; način na koji GCC i CLANG compileri za C++
69 ;; implementiraju inline assembly ima svoje
70 ;; prednosti, ali to je teže i za koristiti
71 ;; (pogotovo za ovakve jednostavne umetnute
72 ;; asemblerske kodove) i za implementirati u
73 ;; compileru.
74 )
75 )multiline");
76 If nova_adresa_u_stranicama = -1 Then { Return(-1); }
81 EndIf; Return nova_adresa_u_stranicama * 64 * 1024; }
87 EndFunction;
88
89 Integer32 velicina_niza;
90 PointerToInteger32 originalni_niz,
91 pomocni_niz;
95 Integer32 broj_obrnuto_poredanih_podniza, broj_vec_poredanih_podniza,
96 broj_pokretanja_QuickSorta, broj_pokretanja_MergeSorta,
97 broj_pokretanja_SelectSorta;
98
99 Decimal32 PRECISION : = 128;
110 Decimal32
111 memoizacija_prirodnog_logaritma[8192];
115 Function Eulerov_broj_na_potenciju(Decimal32 x)
116 Which Returns Decimal32 Is Declared;
118 Function prirodni_logaritam(Decimal32 x) Which Returns Decimal32 Does {
119 If x < 1 Then { Return(-prirodni_logaritam(1 / x)); }
120 EndIf;
121 If(x < 8192 and
122 not(memoizacija_prirodnog_logaritma[asm_f32( "(f32.nearest (f32.load %x))")] = 0)) Then {
125 Return
126 memoizacija_prirodnog_logaritma[asm_f32("(f32.nearest (f32.load %x))")];
127 }
128 EndIf;
129 If x > 8192 Then {
130 Return 1 + prirodni_logaritam(x / Eulerov_broj_na_potenciju(1));
131 }
132 EndIf;
133 Decimal32 zbroj : = 0, epsilon : = (x - 1) / (5 * PRECISION), i : = 1;
136 While(epsilon > 0 and i < x) or (epsilon < 0 and i > x) Loop {
137 zbroj += epsilon / i;
138 i += epsilon; }
142 EndWhile;
143 If x < 8192 Then {
144 Return
145 memoizacija_prirodnog_logaritma[asm_f32("(f32.nearest (f32.load %x))")]
146 : = zbroj;
147 }
148 EndIf;
149 Return zbroj;
150 }
151 EndFunction;
152
153 Decimal32
154 memoizacija_Eulerovog_algoritma[512];
157 Function abs(Decimal32 x) Which Returns Decimal32 Is
158 Declared;
161 Function Eulerov_broj_na_potenciju(Decimal32 x) Which Returns Decimal32 Does {
162 If(abs(x) < 64 and
163 not(memoizacija_Eulerovog_algoritma
164 [asm_f32("(f32.nearest (f32.mul (f32.const 4) (f32.load %x)))") +
165 256] = 0))
166 Then { Return memoizacija_Eulerovog_algoritma
173 [asm_f32("(f32.nearest (f32.mul (f32.const 4) (f32.load %x)))") + 256];
174 }
175 EndIf;
176 Decimal32 i : = 0, y : = 1, epsilon : = x / PRECISION;
178 While(epsilon > 0 and i < x) or (epsilon < 0 and i > x) Loop {
179 y += epsilon * y;
180 i += epsilon;
181 }
182 EndWhile;
183 If abs(x) < 64 Then {
184 Return memoizacija_Eulerovog_algoritma
185 [asm_f32("(f32.nearest (f32.mul (f32.const 4) (f32.load %x)))") + 256]
186 : = y;
187 }
188 EndIf;
189 Return y;
190 }
191 EndFunction;
192
193 Function abs(Decimal32 x) Which Returns Decimal32 Does {
194 Return(x < 0) ? -x : x; }
205 EndFunction;
206
207 Function ostatak_pri_dijeljenju(Decimal32 x,
208 Decimal32 y) Which Returns Decimal32 Does {
209 If DEBUG = 1 Then {
210 printString("Zatrazen je ostatak pri dijeljenju od brojeva: ");
211 printFloat(x);
214 printFloat(y);
215 printString("Sada ce se program mozda srusiti...");
216 }
217 EndIf;
218 If abs(x / y) > Eulerov_broj_na_potenciju(prirodni_logaritam(2) * 63) Then {
219 Return 0; }
222 EndIf;
223 Return x - y *Integer64(x / y); }
233 EndFunction;
234
235 Function pow(Decimal32 x, Decimal32 y) Which Returns Decimal32 Does {
236 Decimal32 result
237 : = Eulerov_broj_na_potenciju(prirodni_logaritam(abs(x)) * y);
238 Return x =
239 0 ? 0 : ostatak_pri_dijeljenju(x, 2) = 1 and x < 0 ? -result : result;
240 }
241 EndFunction;
242
243 Function hybrid_sort(Integer32 donja_granica, Integer32 gornja_granica,
245 Integer32 dubina_rekurzije) Which Returns Nothing Does {
246 If gornja_granica - donja_granica < 2 Then { Return;
251 }
252 ElseIf gornja_granica - donja_granica = 2 Then { If ValueAt(originalni_niz + donja_granica) >
258 ValueAt(originalni_niz + donja_granica + 1) Then {
259 Integer32 pomocna_varijabla_za_zamijenu
260 : = ValueAt(originalni_niz + donja_granica);
261 ValueAt(originalni_niz + donja_granica)
262 : = ValueAt(originalni_niz + donja_granica + 1);
263 ValueAt(originalni_niz + donja_granica + 1)
264 : = pomocna_varijabla_za_zamijenu;
265 }
266 EndIf;
267 Return;
268 }
269 ElseIf gornja_granica -
270 donja_granica<8 or asm_i32("(global.get $stack_pointer)")> 4 * 1024 -
271 73 Then {
272 broj_pokretanja_SelectSorta:
277 = broj_pokretanja_SelectSorta + 1;
278 Integer32 i : = donja_granica;
279 While i < gornja_granica Loop {
280 Integer32 gdje_je_minimum : = i;
281 Integer32 j : = i + 1;
282 While j < gornja_granica Loop {
283 If ValueAt(originalni_niz + gdje_je_minimum) >
284 ValueAt(originalni_niz + j) Then {
285 gdje_je_minimum
286
296 :
297 = j;
298 }
299 EndIf;
300 j += 1;
301 }
302 EndWhile;
303 Integer32 pomocna_varijabla_za_zamijenu : = ValueAt(originalni_niz + i);
304 ValueAt(originalni_niz + i) : = ValueAt(originalni_niz + gdje_je_minimum);
305 ValueAt(originalni_niz + gdje_je_minimum)
306 : = pomocna_varijabla_za_zamijenu;
307 i += 1;
308 }
309 EndWhile;
310 Return;
311 }
312 EndIf;
313 Decimal32 razvrstanost : = 0;
314 Integer32 i : = donja_granica, je_li_niz_vec_poredan : = 1;
315 While i < gornja_granica - 1 Loop {
316 razvrstanost +=
317 (ValueAt(originalni_niz + i) < ValueAt(originalni_niz + i + 1) or
318 ValueAt(originalni_niz + i) = ValueAt(originalni_niz + i + 1));
319 If ValueAt(originalni_niz + i) > ValueAt(originalni_niz + i + 1) Then {
320 je_li_niz_vec_poredan:
321 = 0;
322 }
323 EndIf;
324 i += 1;
325 }
326 EndWhile;
327 razvrstanost:
328 = razvrstanost / ((gornja_granica - donja_granica - 1) / 2.) - 1;
329 If abs(razvrstanost) > 1 Then {
331 printString("Apsolutna vrijednost razvrstanosti je veca od 1!");
333 printString("Relevantni dio niza iznosi:"); i:
343 = donja_granica;
344 While i < gornja_granica Loop {
345 printInteger(ValueAt(originalni_niz + i));
346 i += 1;
347 }
348 EndWhile;
349 printString("Kraj relevantnog dijela niza!");
350 }
351 EndIf;
352 If je_li_niz_vec_poredan and not(razvrstanost = 1 or razvrstanost > 1) Then {
353 printString("Niz je poredan, a razvrstanost nije 1.");
355 printString("Relevantni dio niza iznosi:");
356 i:
357 = donja_granica;
358 While i < gornja_granica Loop {
359 printInteger(ValueAt(originalni_niz + i));
360 i += 1;
361 }
362 EndWhile;
363 printString("Kraj relevantnog dijela niza!");
364 }
365 EndIf;
366 If not(je_li_niz_vec_poredan) and (razvrstanost = 1 or razvrstanost > 1)
367 Then {
368 printString("Razvrstanost je 1, a niz nije poredan!");
370 printString("Relevantni dio niza iznosi:");
371 i:
372 = donja_granica;
373 While i < gornja_granica Loop {
374 printInteger(ValueAt(originalni_niz + i));
375 i += 1;
376 }
377 EndWhile;
378 printString("Kraj relevantnog dijela niza!");
379 }
380 EndIf;
381 Decimal32 razvrstanost_na_potenciju[8] : = {1}; i:
389 = 1;
390 While i < 8 Loop {
391 razvrstanost_na_potenciju[i]
392 : = razvrstanost_na_potenciju[i - 1] * razvrstanost;
393 i += 1;
394 }
395 EndWhile;
396 Decimal32 polinom_pod_apsolutnom
400 : = 2.38854 * razvrstanost_na_potenciju[7] -
401 0.284258 * razvrstanost_na_potenciju[6] -
402 1.87104 * razvrstanost_na_potenciju[5] +
403 0.372637 * razvrstanost_na_potenciju[4] +
404 0.167242 * razvrstanost_na_potenciju[3] -
405 0.0884977 * razvrstanost_na_potenciju[2] + 0.315119 * razvrstanost;
406 Decimal32 Eulerov_broj_na_koju_potenciju
407 : = (prirodni_logaritam(gornja_granica - donja_granica) +
408 prirodni_logaritam(
409 prirodni_logaritam(gornja_granica - donja_granica))) *
410 1.05 +
411 (prirodni_logaritam(gornja_granica - donja_granica) -
412 prirodni_logaritam(
413 prirodni_logaritam(gornja_granica - donja_granica)) -
414 prirodni_logaritam(2)) *
415 0.9163 * abs(polinom_pod_apsolutnom);
416 Decimal32 koliko_usporedbi_ocekujemo_od_QuickSorta
417 : = Eulerov_broj_na_potenciju(Eulerov_broj_na_koju_potenciju);
418 Decimal32 koliko_usporedbi_ocekujemo_od_MergeSorta
419 : = (mod(broj_mjerenja, 2) + 1) *
420 (gornja_granica -
421 donja_granica) * prirodni_logaritam(gornja_granica - donja_granica) /
435 prirodni_logaritam(2);
436 If razvrstanost = 1 or razvrstanost > 1 Then {
438 broj_vec_poredanih_podniza += 1;
439 Return;
440 }
441 ElseIf razvrstanost = -1 or razvrstanost < -1 Then {
442 broj_obrnuto_poredanih_podniza += 1;
443 Integer32 i : = donja_granica;
444 Integer32 j : = gornja_granica - 1;
445 While i < gornja_granica Loop {
446 ValueAt(pomocni_niz + i) : = ValueAt(originalni_niz + j);
447 j -= 1;
448 i += 1;
449 }
450 EndWhile;
451 i:
452 = donja_granica;
453 While i < gornja_granica Loop {
454 ValueAt(originalni_niz + i) : = ValueAt(pomocni_niz + i);
455 i += 1;
456 }
457 EndWhile;
458 Return;
459 }
460 ElseIf(koliko_usporedbi_ocekujemo_od_MergeSorta <
461 koliko_usporedbi_ocekujemo_od_QuickSorta or
462 dubina_rekurzije > pow(2, 18 - prirodni_logaritam(velicina_niza) /
463 prirodni_logaritam(2))
464 ) and
472 not(gornja_granica - donja_granica =
473 velicina_niza and not(mod(broj_mjerenja, 3)))
474 Then {
477 broj_pokretanja_MergeSorta += 1;
483 Integer32 sredina_niza : = (gornja_granica + donja_granica) / 2;
484 hybrid_sort(donja_granica, sredina_niza, dubina_rekurzije + 1);
491 hybrid_sort(sredina_niza, gornja_granica, dubina_rekurzije + 1);
492 Integer32 i : = donja_granica;
495 Integer32 gdje_smo_u_prvom_nizu : = donja_granica;
496 Integer32 gdje_smo_u_drugom_nizu : = sredina_niza;
497 While i < gornja_granica Loop {
498 If(gdje_smo_u_prvom_nizu =
499 sredina_niza or
500 ValueAt(originalni_niz + gdje_smo_u_drugom_nizu) <
501 ValueAt(originalni_niz + gdje_smo_u_prvom_nizu)) and
502 gdje_smo_u_drugom_nizu < gornja_granica Then {
503 ValueAt(pomocni_niz + i)
504 : = ValueAt(originalni_niz + gdje_smo_u_drugom_nizu);
505 gdje_smo_u_drugom_nizu += 1;
506 }
507 Else {
508 ValueAt(pomocni_niz + i)
509 : = ValueAt(originalni_niz + gdje_smo_u_prvom_nizu);
510 gdje_smo_u_prvom_nizu += 1;
511 }
512 EndIf;
513 i += 1;
514 }
515 EndWhile;
516 i:
517 = donja_granica;
518 While i < gornja_granica Loop {
519 ValueAt(originalni_niz + i) : = ValueAt(pomocni_niz + i);
520 i += 1;
521 }
522 EndWhile;
523 Return;
524 }
525 Else { broj_pokretanja_QuickSorta += 1;
527 Integer32 pivot : = ValueAt(originalni_niz + gornja_granica - 1);
534 Integer32 i : = donja_granica - 1;
535 Integer32 j : = donja_granica;
536 Integer32 pomocna_varijabla_za_zamijenu;
537 While j < gornja_granica - 1 Loop {
538 If ValueAt(originalni_niz + j) < pivot Then {
539 i += 1;
540 pomocna_varijabla_za_zamijenu:
541 = ValueAt(originalni_niz + i);
542 ValueAt(originalni_niz + i) : = ValueAt(originalni_niz + j);
543 ValueAt(originalni_niz + j) : = pomocna_varijabla_za_zamijenu;
544 }
545 EndIf;
546 j += 1;
547 }
548 EndWhile;
549 pomocna_varijabla_za_zamijenu:
550 = ValueAt(originalni_niz + i + 1);
551 ValueAt(originalni_niz + i + 1)
552 : = ValueAt(originalni_niz + gornja_granica - 1);
553 ValueAt(originalni_niz + gornja_granica - 1)
554 : = pomocna_varijabla_za_zamijenu;
555 Integer32 gdje_je_pivot : = i + 1;
556 hybrid_sort(donja_granica, gdje_je_pivot, dubina_rekurzije + 1);
557 hybrid_sort(gdje_je_pivot, gornja_granica, dubina_rekurzije + 1);
558 Return;
559 }
560 EndIf;
561 printString("Izgleda da compiler nije ispravno "
563 "preveo kontrolne strukture!");
564 }
565 EndFunction;
566
567 Function pocetna_AEC_funkcija() Which Returns Nothing Does {
569 If originalni_niz = -1 or pomocni_niz = -1 Then {
570 Return; }
573 EndIf;
574 If abs(pow(3, 3) - 27) > 2 Then { printString("Izgleda da matematicke funkcije ne funkcioniraju dobro.");
578 printString("pow(3, 3) =");
579 printFloat(pow(3, 3));
580 }
581 EndIf;
582 Integer32 prijasnja_velicina_niza : = velicina_niza;
584 velicina_niza:
585 = daj_velicinu_niza();
586 If velicina_niza / (64 * 1024 / 4) +
588 not(not(mod(velicina_niza, 64 * 1024 / 4))) >
589 prijasnja_velicina_niza / (64 * 1024 / 4) +
590 not(not(mod(prijasnja_velicina_niza, 64 * 1024 / 4))) or
591 prijasnja_velicina_niza = 0 Then {
592 originalni_niz:
593 = zauzmi_memorijske_stranice(4 * velicina_niza / (64 * 1024) +
594 not(not(mod(velicina_niza, 64 * 1024 / 4))));
595 pomocni_niz:
596 = zauzmi_memorijske_stranice(4 * velicina_niza / (64 * 1024) +
597 not(not(mod(velicina_niza, 64 * 1024 / 4))));
598 If originalni_niz = -1 or pomocni_niz = -1 Then {
599 printString("Nema dovoljno memorije za nastavak programa!?");
600 izvijesti_JavaScript_o_nedostatku_memorije();
601 Return; }
603 EndIf;
604 }
605 EndIf;
606 kopiraj_niz_na_adresu(originalni_niz);
609 broj_obrnuto_poredanih_podniza:
611 = broj_vec_poredanih_podniza : = broj_pokretanja_QuickSorta
612 : = broj_pokretanja_MergeSorta : = broj_pokretanja_SelectSorta
613 : = 0; broj_mjerenja += 1;
617 pocni_mjerenje_vremena();
618 hybrid_sort(0, velicina_niza, 0);
619 zavrsi_mjerenje_vremena();
620 izvijesti_o_obrnuto_poredanim_nizovima(broj_obrnuto_poredanih_podniza);
623 izvijesti_o_poredanim_nizovima(broj_vec_poredanih_podniza);
624 izvijesti_o_pokretanju_QuickSorta(broj_pokretanja_QuickSorta);
625 izvijesti_o_pokretanju_MergeSorta(broj_pokretanja_MergeSorta);
626 izvijesti_o_pokretanju_SelectSorta(broj_pokretanja_SelectSorta);
627 Integer32 i : = 0;
629 While i < velicina_niza - 1 Loop {
630 If ValueAt(originalni_niz + i) > ValueAt(originalni_niz + i + 1) Then {
631 printString("Niz nije poredan!");
632 Return; }
635 EndIf;
636 i += 1;
637 }
638 EndWhile;
639 }
640 EndFunction;
641