summaryrefslogtreecommitdiff
path: root/macros/arithdeco.sci
diff options
context:
space:
mode:
Diffstat (limited to 'macros/arithdeco.sci')
-rw-r--r--macros/arithdeco.sci170
1 files changed, 170 insertions, 0 deletions
diff --git a/macros/arithdeco.sci b/macros/arithdeco.sci
new file mode 100644
index 0000000..95a06b9
--- /dev/null
+++ b/macros/arithdeco.sci
@@ -0,0 +1,170 @@
+function [seq] = arithdeco(code, count, len)
+// This function decodes the given code using arithmetic coding
+
+// Calling sequence
+// 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 whihc 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)
+
+// Bibliography
+// Sayood, K., Introduction to Data Compression, Morgan Kaufmann, 2000, Chapter 4, Section 4.4.3.
+
+// See also
+// arithenco
+
+// 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