%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%                                                                        %
%                               WiMAX_SOVA                               %
%                                                                        %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%SOVA DEKODOVACI ALGORITMUS
%Vstupne premenne:
%data - prenesene data [double] 
%g - vytvaracie polynomy kodera [bin]
%L_uk - a-priori pravdepodobnost z predchadzajuce dekodera [double]
%index - urcuje poradie dekodera [int]
%naOut - nasledujuci vystup kodera [int]
%naStav - nasledujuci stav [int]
%preOut - predchadzajuci vystup [int]
%preStav - predchadzajuci stav [int]
%Vystupne premenne:
%out - a-posteriori vystup dekodera [double]
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
function out = WiMAX_SOVA(data,g,L_uk,index,naOut,naStav,preOut,preStav)

%%INICIALIZACIA HODNOT
[n,K] = size(g);                                                          
m = K - 1;                                                                 
dlz = length(L_uk);                                                       
max_stav = 2^m;                                                           
inf = 9e9;                                                                  
d = 15;                                                                     
metrika = repmat(-inf,max_stav,dlz+1);                                   
metrika(1,1) = 0;

%% CYKLUS PRE VYPOCET METRIK TRELLISU
for i = 1:dlz
y = data(3*i-2:3*i);                                                       
    %% VYPOCET METRIK
    for j = 1:max_stav
        v_0 = preOut(j,1:3);                                                %bit 0                                  
        v_1 = preOut(j,4:6);                                                %bit 1
        s_0 = preStav(j,1);                                                 %stav pre bit 0
        s_1 = preStav(j,2);                                                 %stav pre bit 1
        Mk0 = y*v_0' - L_uk(i)/2 + metrika(s_0,i);                          %vypocet metriky pre bit 0
        Mk1 = y*v_1' + L_uk(i)/2 + metrika(s_1,i);                          %vypocet metriky pre bit 1
        %%POROVNANIE METRIK
        if Mk0>Mk1
            metrika(j,i+1)=Mk0;                                        
            difM(j,i+1) = Mk0 - Mk1;                                    
            preBit(j,i+1) = 0;                                            
        else                                                               
            metrika(j,i+1)=Mk1;
            difM(j,i+1) = Mk1 - Mk0;
            preBit(j,i+1) = 1;
        end
    end
end

%%VOLBA NAJPRAVDEPODOBNEJSEJ CESTY
if index == 1
    cesta(1,dlz+1) = 1;                                                                              
else
    a = find(metrika(:,dlz+1)==max ...                                                        
               (metrika(:,dlz+1)));
    cesta(1,dlz+1) = a(1);
end

%% ZISTENIE STAVOV A BITOV ZODPOVEDAJUCICH NAJ. CESTE
for i = dlz:-1:1
    cestaB(i) = preBit(cesta(i+1),i+1);                                 
    cesta(i) = preStav(cesta(i+1), cestaB(i)+1);                         
end

%% VYPOCITANIE A-POSTERIORI VYSTUPU
for i = 1:dlz
    llr = inf;
    for j = 0:d
        if i+j<dlz+1
            bit = 1-cestaB(i+j);                                          
            stav = preStav(cesta(i+j+1), bit+1);                           
            for k=j-1:-1:0
                bit = preBit(stav,i+k+1);
                stav = preStav(stav, bit+1);
            end
            if bit~=cestaB(i) 
                llr = min(llr,difM(cesta(i+j+1), i+j+1));                 
            end
        end
    end
    out(i) = (2*cestaB(i) - 1) * llr;                                       %a-posteriori PRAVDEPODOBNOST
end 
end