summaryrefslogtreecommitdiff
path: root/macros/arithdeco.sci
blob: 226c12d06bb8cbe51f9a460fbf4a90ad9546c7a8 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
function [seq] = arithdeco(code, count, len)
//   This function decodes the given code using arithmetic coding    
//    
//   Syntax
//   SEQ = ARITHDECO(CODE, COUNT, LEN) 
//
//   Description
//   SEQ = ARITHDECO(CODE, COUNT, LEN) decodes the given received seq (CODE) to message using arithmetic coding.
//   COUNT is vector which gives information about the source statistics (i.e. frequency of each symbol in the source alphabet)
//   CODE is the binary arithmetic code
//    
//   Source Alphabet is assumed to be {1,2,....N} where N is a positive integer
//   Therefore, sequence should be finite and positive 
//   Length of the COUNT should match the length of the source alphabet
//
//   Examples 
//   counts = [40 1 9];
//   len = 11;
//   seq = [1 3 2 1 1 1 3 3 1 1 2 ]
//   code = arithenco(seq,counts);
//   disp(code)
//   dseq=arithdeco(code,counts,len)
//   disp(dseq)
//   disp(seq)
//
//   Authors
//   Pola Lakshmi Priyanka, IIT Bombay

//Input argument check
    
    [outa,inpa]=argn(0);
    if(~inpa==3)
    error("comm:arithenco:Wrong number of Input Arguments");
    end
    
    [row_code,col_code]=size(code);
    [row_sta,col_sta]=size(count);
    
    // Check to make sure that sequence is 1D
    if(~(row_code==1|col_code==1))
        error("comm:arithenco: Invalid dimensions: Input Arithmetic Encoded Sequence should be 1D ");
    end
    
    // Check for source statistics matrix 
    if(~(row_sta==1|col_sta==1))
        error("comm:arithenco: Invalid dimensions: Argument 2 should be 1D ");
    end
    
    if(~isreal(code) | or(code<0) )
        error("comm:arithenco: Input sequence should be finite positive integer");
    end
    
    if(~isreal(count) | or(count<0) )
        error("comm:arithenco: Source statistics should be finite positive integer");
    end
    
    if(~isreal(len) | or(len<=0) | ~isscalar(len))
        error("comm:arithenco: length should be finite positive integer and scalar");
    end
    
   //Check the incoming orientation and adjust if necessary
    if (row_code > 1),
        code = code.';
    end
    
    if (row_sta > 1),
        count = count.';
    end
    
    // Check if the given code is binary
    for i=1:length(code)
    if (~(code(i)==1 | code(i)==0 ))
        error("comm:arithenco:Input Arithmetic Encoded Sequence is not binary");
    end
    end
    
    [row_s,col_s]=size(code);
    [row_c,col_c]=size(count);
    
    //Calculate the cumulative count
    cum_count=[0,cumsum(count)];
    total_count=cum_count(length(cum_count));
    
    //Initialization
    m=ceil(log2(total_count)) + 2;
    low=zeros(1,m);
    up=ones(1,m);
    dec_low=0;
    dec_up=2^m-1;
    seq= zeros(1,len);
    seq_index=1;
    k=m;
    tag=code(1:m);
    dec_tag=0;
    value=0;
    for i=1:length(tag)
        dec_tag=dec_tag+tag(i)*2^(length(tag)-i);
    end
    
    //loop till you decode entire seq
    while (seq_index <= len)

        // Compute value
        value =floor( ((dec_tag-dec_low+1)*total_count-1)/(dec_up-dec_low+1) );
        
        //Decode the symbol and update it
        c=find(cum_count <= value)
        ptr=c(length(c))
        
        seq(seq_index)=ptr;
        seq_index=seq_index+1;
        
        //Compute lower and upper bounds
        dec_low_new = dec_low + floor( (dec_up-dec_low+1)*cum_count(ptr)/total_count );
        dec_up = dec_low + floor( (dec_up-dec_low+1)*cum_count(ptr+1)/total_count )-1;
        dec_low = dec_low_new;
        
        for i=1:m
        low(i)=strtod(part(dec2bin(dec_low,m),i))
        end
        for i=1:m
        up(i)=strtod(part(dec2bin(dec_up,m),i))
        end

        //Loop while E1, E2 or E3 condition
        while(isequal(low(1),up(1))) | (isequal(low(2),1) & isequal(up(2),0))
        
        if (k==length(code)) then
            break;
        end
        
        k=k+1;
            if isequal(low(1),up(1)) then //E1 or E2 holds
                
                //Left shift
                low=[low(2:m) 0];
                up=[up(2:m) 1];
                tag=[tag(2:m) code(k)];
                
            elseif (isequal(low(2),1) & isequal(up(2),0)) then //for E3 
                
                //left shift
                low=[low(2:m),0];
                up=[up(2:m),1];
                tag=[tag(2:m) code(k)];
                
                low(1)=bitxor(low(1),1);
                up(1)=bitxor(up(1),1);
                tag(1)=bitxor(tag(1),1);
                
            end
        end
        dec_low=0;dec_up=0;dec_tag=0;
        for i=1:length(low)
        dec_low=dec_low+low(i)*2^(length(low)-i);
        dec_up=dec_up+up(i)*2^(length(up)-i);
        dec_tag=dec_tag+tag(i)*2^(length(tag)-i);
        end
    end
    
endfunction