%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%                                                                        %
%                           CCSDS_MAXlogMAP                              %
%                                                                        %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%MAXlogMAP DEKODOVACI ALGORITMUS
%Vstupne premenne:
%Lc_yk - prenesene data [double]
%g - vytvaracie polynomy kodera [bin]
%L_uk - a-priori pravdepodobnost z predchadzajuceho 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:
%L_uky - a-posteriori vystup dekodera [double]
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
function [ L_uky ] = CCSDS_MAXlogMAP( Lc_yk,g,L_uk,index, naOut, ... 
    naStav, preOut, preStav )

%%INICIALIZACIA HODNOT
dlz = length(Lc_yk)/4;                                              
[n,K] = size(g); 
m = K - 1;
max_stav = 2^m;
Inf = 1e10;
Alpha=0;
Beta=0;
gamma=0;
stav2=0;
tempmax=0;
temp0=0;
temp1=0;
stav1=0;
    
    %%INICIALIZACIA ALPHA
    Alpha(1,1) = 0; 
    Alpha(1,2:max_stav) = -Inf*ones(1,max_stav-1);

    %%INICIALIZACIA BETA
    if index==1
       Beta(dlz,1) = 0;
       Beta(dlz,2:max_stav) = -Inf*ones(1,max_stav-1); 
    elseif index==2
       Beta(dlz,1:max_stav) = zeros(1,max_stav);
    else
       error('CHYBA!!!');
    end

    %%VYPOCET ALPHA PRECHOD TRELISOM V DOPREDNOM SMERE
    for k = 2:dlz+1
        Alpha = [Alpha;-Inf*ones(1,max_stav)];
        for stav2 = 1:max_stav
            gamma = -Inf*ones(1,max_stav);
            a = Lc_yk(1,4*k-6:4*k-4);                                       
            b = naOut(stav2,2:4)';                                 
            xxx = a*b;
            zzz = -Lc_yk(4*k-7)+xxx;
            %GAMMA PRE 0
            gamma(naStav(stav2,1)) = zzz;
            a = Lc_yk(4*k-6:4*k-4);
            b = naOut(stav2,6:8)';
            xxx = a*b;           
            zzz = Lc_yk(4*k-7)+xxx;
            %GAMMA PRE 1
            gamma(naStav(stav2,2)) = zzz + L_uk(k-1);
            
            %VYPOCET ALPHA
            if(Alpha(k-1,stav2)~=-Inf)
                x = Alpha(k,naStav(stav2,1));
                y1 = gamma(naStav(stav2,1));
                y2 = Alpha(k-1,stav2);
                y = y1+y2;
                Alpha(k,naStav(stav2,1)) = max([x,y]);
                x = Alpha(k,naStav(stav2,2));
                y1 = gamma(naStav(stav2,2));
                y2 = Alpha(k-1,stav2);
                y = y1+y2;
                Alpha(k,naStav(stav2,2)) = max([x,y]);
            end   
        end
    end     

    %%VYPOCET BETA PRECHOD TRELLISOM V SPATNOM SMERE
    for k = dlz-1:-1:1
        Beta(k,:) = -Inf;
        for stav1 = 1:max_stav
            gamma = -Inf*ones(1,max_stav);
            a = Lc_yk(1,4*k+2:4*k+4);                                      
            b = preOut(stav1,2:4)';                                   
            xxx = a*b;
            zzz = -Lc_yk(4*k+1)+xxx;
            %GAMMA PRE 0
            gamma(preStav(stav1,1)) = zzz;
            a = Lc_yk(1,4*k+2:4*k+4);
            b = preOut(stav1,6:8)';
            xxx = a*b;
            zzz = Lc_yk(4*k+1)+xxx;
            %GAMMA PRE 1
            gamma(preStav(stav1,2)) = zzz + L_uk(k+1);
            
            %VYPOCET BETA
            if(Beta(k+1,stav1)~=-Inf)
                x = Beta(k,preStav(stav1,1));
                y1 = gamma(preStav(stav1,1));
                y2 = Beta(k+1,stav1);
                y = y1+y2;
                Beta(k,preStav(stav1,1)) = max([x,y]);
                x = Beta(k,preStav(stav1,2));
                y1 = gamma(preStav(stav1,2));
                y2 = Beta(k+1,stav1);
                y = y1+y2;
                Beta(k,preStav(stav1,2)) = max([x,y]);
            end
        end
    end

    %%VYPOCET A-POSTERIORI PRAVDEPODOBNOSTI
    for k = 1:dlz
        for stav2 = 1:max_stav
            a = Lc_yk(4*k-2:4*k);                                           
            b = naOut(stav2,2:4)';                                 
            xxx = a*b;
            zzz = -Lc_yk(4*k-3)+xxx;
            gamma0 = zzz;
            a = Lc_yk(4*k-2:4*k);
            b = naOut(stav2,6:8)';
            xxx = a*b;
            zzz = Lc_yk(4*k-3)+xxx;
            gamma1 = zzz + L_uk(k);
            x = Alpha(k,stav2);
            y1 = Beta(k,naStav(stav2,1));
            y2 = Beta(k,naStav(stav2,2));
            temp0(stav2) = gamma0 + x + y1;
            temp1(stav2) = gamma1 + x + y2;
        end
        L_uky(k) = max(temp1) - max(temp0);                                 %a-posteriori pravdepodobnost
    end
end
