1/* Copyright (c) 2007-2011 Xiph.Org Foundation, Mozilla Corporation,
2                           Gregory Maxwell
3   Written by Jean-Marc Valin, Gregory Maxwell, and Timothy B. Terriberry */
4/*
5   Redistribution and use in source and binary forms, with or without
6   modification, are permitted provided that the following conditions
7   are met:
8
9   - Redistributions of source code must retain the above copyright
10   notice, this list of conditions and the following disclaimer.
11
12   - Redistributions in binary form must reproduce the above copyright
13   notice, this list of conditions and the following disclaimer in the
14   documentation and/or other materials provided with the distribution.
15
16   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17   ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
20   OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
21   EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
22   PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
23   PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
24   LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
25   NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
26   SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27*/
28
29#ifdef HAVE_CONFIG_H
30#include "config.h"
31#endif
32
33#include <stdlib.h>
34#include <stdio.h>
35#include <math.h>
36#include <time.h>
37#include "entcode.h"
38#include "entenc.h"
39#include "entdec.h"
40#include <string.h>
41
42#include "entenc.c"
43#include "entdec.c"
44#include "entcode.c"
45
46#ifndef M_LOG2E
47# define M_LOG2E    1.4426950408889634074
48#endif
49#define DATA_SIZE 10000000
50#define DATA_SIZE2 10000
51
52int main(int _argc,char **_argv){
53  ec_enc         enc;
54  ec_dec         dec;
55  long           nbits;
56  long           nbits2;
57  double         entropy;
58  int            ft;
59  int            ftb;
60  int            sz;
61  int            i;
62  int            ret;
63  unsigned int   sym;
64  unsigned int   seed;
65  unsigned char *ptr;
66  const char    *env_seed;
67  ret=0;
68  entropy=0;
69    if (_argc > 2) {
70	fprintf(stderr, "Usage: %s [<seed>]\n", _argv[0]);
71	return 1;
72    }
73  env_seed = getenv("SEED");
74  if (_argc > 1)
75    seed = atoi(_argv[1]);
76  else if (env_seed)
77    seed = atoi(env_seed);
78  else
79    seed = time(NULL);
80  /*Testing encoding of raw bit values.*/
81  ptr = (unsigned char *)malloc(DATA_SIZE);
82  ec_enc_init(&enc,ptr, DATA_SIZE);
83  for(ft=2;ft<1024;ft++){
84    for(i=0;i<ft;i++){
85      entropy+=log(ft)*M_LOG2E;
86      ec_enc_uint(&enc,i,ft);
87    }
88  }
89  /*Testing encoding of raw bit values.*/
90  for(ftb=1;ftb<16;ftb++){
91    for(i=0;i<(1<<ftb);i++){
92      entropy+=ftb;
93      nbits=ec_tell(&enc);
94      ec_enc_bits(&enc,i,ftb);
95      nbits2=ec_tell(&enc);
96      if(nbits2-nbits!=ftb){
97        fprintf(stderr,"Used %li bits to encode %i bits directly.\n",
98         nbits2-nbits,ftb);
99        ret=-1;
100      }
101    }
102  }
103  nbits=ec_tell_frac(&enc);
104  ec_enc_done(&enc);
105  fprintf(stderr,
106   "Encoded %0.2lf bits of entropy to %0.2lf bits (%0.3lf%% wasted).\n",
107   entropy,ldexp(nbits,-3),100*(nbits-ldexp(entropy,3))/nbits);
108  fprintf(stderr,"Packed to %li bytes.\n",(long)ec_range_bytes(&enc));
109  ec_dec_init(&dec,ptr,DATA_SIZE);
110  for(ft=2;ft<1024;ft++){
111    for(i=0;i<ft;i++){
112      sym=ec_dec_uint(&dec,ft);
113      if(sym!=(unsigned)i){
114        fprintf(stderr,"Decoded %i instead of %i with ft of %i.\n",sym,i,ft);
115        ret=-1;
116      }
117    }
118  }
119  for(ftb=1;ftb<16;ftb++){
120    for(i=0;i<(1<<ftb);i++){
121      sym=ec_dec_bits(&dec,ftb);
122      if(sym!=(unsigned)i){
123        fprintf(stderr,"Decoded %i instead of %i with ftb of %i.\n",sym,i,ftb);
124        ret=-1;
125      }
126    }
127  }
128  nbits2=ec_tell_frac(&dec);
129  if(nbits!=nbits2){
130    fprintf(stderr,
131     "Reported number of bits used was %0.2lf, should be %0.2lf.\n",
132     ldexp(nbits2,-3),ldexp(nbits,-3));
133    ret=-1;
134  }
135  /*Testing an encoder bust prefers range coder data over raw bits.
136    This isn't a general guarantee, will only work for data that is buffered in
137     the encoder state and not yet stored in the user buffer, and should never
138     get used in practice.
139    It's mostly here for code coverage completeness.*/
140  /*Start with a 16-bit buffer.*/
141  ec_enc_init(&enc,ptr,2);
142  /*Write 7 raw bits.*/
143  ec_enc_bits(&enc,0x55,7);
144  /*Write 12.3 bits of range coder data.*/
145  ec_enc_uint(&enc,1,2);
146  ec_enc_uint(&enc,1,3);
147  ec_enc_uint(&enc,1,4);
148  ec_enc_uint(&enc,1,5);
149  ec_enc_uint(&enc,2,6);
150  ec_enc_uint(&enc,6,7);
151  ec_enc_done(&enc);
152  ec_dec_init(&dec,ptr,2);
153  if(!enc.error
154   /*The raw bits should have been overwritten by the range coder data.*/
155   ||ec_dec_bits(&dec,7)!=0x05
156   /*And all the range coder data should have been encoded correctly.*/
157   ||ec_dec_uint(&dec,2)!=1
158   ||ec_dec_uint(&dec,3)!=1
159   ||ec_dec_uint(&dec,4)!=1
160   ||ec_dec_uint(&dec,5)!=1
161   ||ec_dec_uint(&dec,6)!=2
162   ||ec_dec_uint(&dec,7)!=6){
163    fprintf(stderr,"Encoder bust overwrote range coder data with raw bits.\n");
164    ret=-1;
165  }
166  srand(seed);
167  fprintf(stderr,"Testing random streams... Random seed: %u (%.4X)\n", seed, rand() % 65536);
168  for(i=0;i<409600;i++){
169    unsigned *data;
170    unsigned *tell;
171    unsigned tell_bits;
172    int       j;
173    int zeros;
174    ft=rand()/((RAND_MAX>>(rand()%11U))+1U)+10;
175    sz=rand()/((RAND_MAX>>(rand()%9U))+1U);
176    data=(unsigned *)malloc(sz*sizeof(*data));
177    tell=(unsigned *)malloc((sz+1)*sizeof(*tell));
178    ec_enc_init(&enc,ptr,DATA_SIZE2);
179    zeros = rand()%13==0;
180    tell[0]=ec_tell_frac(&enc);
181    for(j=0;j<sz;j++){
182      if (zeros)
183        data[j]=0;
184      else
185        data[j]=rand()%ft;
186      ec_enc_uint(&enc,data[j],ft);
187      tell[j+1]=ec_tell_frac(&enc);
188    }
189    if (rand()%2==0)
190      while(ec_tell(&enc)%8 != 0)
191        ec_enc_uint(&enc, rand()%2, 2);
192    tell_bits = ec_tell(&enc);
193    ec_enc_done(&enc);
194    if(tell_bits!=(unsigned)ec_tell(&enc)){
195      fprintf(stderr,"ec_tell() changed after ec_enc_done(): %i instead of %i (Random seed: %u)\n",
196       ec_tell(&enc),tell_bits,seed);
197      ret=-1;
198    }
199    if ((tell_bits+7)/8 < ec_range_bytes(&enc))
200    {
201      fprintf (stderr, "ec_tell() lied, there's %i bytes instead of %d (Random seed: %u)\n",
202               ec_range_bytes(&enc), (tell_bits+7)/8,seed);
203      ret=-1;
204    }
205    ec_dec_init(&dec,ptr,DATA_SIZE2);
206    if(ec_tell_frac(&dec)!=tell[0]){
207      fprintf(stderr,
208       "Tell mismatch between encoder and decoder at symbol %i: %i instead of %i (Random seed: %u).\n",
209       0,ec_tell_frac(&dec),tell[0],seed);
210    }
211    for(j=0;j<sz;j++){
212      sym=ec_dec_uint(&dec,ft);
213      if(sym!=data[j]){
214        fprintf(stderr,
215         "Decoded %i instead of %i with ft of %i at position %i of %i (Random seed: %u).\n",
216         sym,data[j],ft,j,sz,seed);
217        ret=-1;
218      }
219      if(ec_tell_frac(&dec)!=tell[j+1]){
220        fprintf(stderr,
221         "Tell mismatch between encoder and decoder at symbol %i: %i instead of %i (Random seed: %u).\n",
222         j+1,ec_tell_frac(&dec),tell[j+1],seed);
223      }
224    }
225    free(tell);
226    free(data);
227  }
228  /*Test compatibility between multiple different encode/decode routines.*/
229  for(i=0;i<409600;i++){
230    unsigned *logp1;
231    unsigned *data;
232    unsigned *tell;
233    unsigned *enc_method;
234    int       j;
235    sz=rand()/((RAND_MAX>>(rand()%9U))+1U);
236    logp1=(unsigned *)malloc(sz*sizeof(*logp1));
237    data=(unsigned *)malloc(sz*sizeof(*data));
238    tell=(unsigned *)malloc((sz+1)*sizeof(*tell));
239    enc_method=(unsigned *)malloc(sz*sizeof(*enc_method));
240    ec_enc_init(&enc,ptr,DATA_SIZE2);
241    tell[0]=ec_tell_frac(&enc);
242    for(j=0;j<sz;j++){
243      data[j]=rand()/((RAND_MAX>>1)+1);
244      logp1[j]=(rand()%15)+1;
245      enc_method[j]=rand()/((RAND_MAX>>2)+1);
246      switch(enc_method[j]){
247        case 0:{
248          ec_encode(&enc,data[j]?(1<<logp1[j])-1:0,
249           (1<<logp1[j])-(data[j]?0:1),1<<logp1[j]);
250        }break;
251        case 1:{
252          ec_encode_bin(&enc,data[j]?(1<<logp1[j])-1:0,
253           (1<<logp1[j])-(data[j]?0:1),logp1[j]);
254        }break;
255        case 2:{
256          ec_enc_bit_logp(&enc,data[j],logp1[j]);
257        }break;
258        case 3:{
259          unsigned char icdf[2];
260          icdf[0]=1;
261          icdf[1]=0;
262          ec_enc_icdf(&enc,data[j],icdf,logp1[j]);
263        }break;
264      }
265      tell[j+1]=ec_tell_frac(&enc);
266    }
267    ec_enc_done(&enc);
268    if((ec_tell(&enc)+7U)/8U<ec_range_bytes(&enc)){
269      fprintf(stderr,"tell() lied, there's %i bytes instead of %d (Random seed: %u)\n",
270       ec_range_bytes(&enc),(ec_tell(&enc)+7)/8,seed);
271      ret=-1;
272    }
273    ec_dec_init(&dec,ptr,DATA_SIZE2);
274    if(ec_tell_frac(&dec)!=tell[0]){
275      fprintf(stderr,
276       "Tell mismatch between encoder and decoder at symbol %i: %i instead of %i (Random seed: %u).\n",
277       0,ec_tell_frac(&dec),tell[0],seed);
278    }
279    for(j=0;j<sz;j++){
280      int fs;
281      int dec_method;
282      dec_method=rand()/((RAND_MAX>>2)+1);
283      switch(dec_method){
284        case 0:{
285          fs=ec_decode(&dec,1<<logp1[j]);
286          sym=fs>=(1<<logp1[j])-1;
287          ec_dec_update(&dec,sym?(1<<logp1[j])-1:0,
288           (1<<logp1[j])-(sym?0:1),1<<logp1[j]);
289        }break;
290        case 1:{
291          fs=ec_decode_bin(&dec,logp1[j]);
292          sym=fs>=(1<<logp1[j])-1;
293          ec_dec_update(&dec,sym?(1<<logp1[j])-1:0,
294           (1<<logp1[j])-(sym?0:1),1<<logp1[j]);
295        }break;
296        case 2:{
297          sym=ec_dec_bit_logp(&dec,logp1[j]);
298        }break;
299        case 3:{
300          unsigned char icdf[2];
301          icdf[0]=1;
302          icdf[1]=0;
303          sym=ec_dec_icdf(&dec,icdf,logp1[j]);
304        }break;
305      }
306      if(sym!=data[j]){
307        fprintf(stderr,
308         "Decoded %i instead of %i with logp1 of %i at position %i of %i (Random seed: %u).\n",
309         sym,data[j],logp1[j],j,sz,seed);
310        fprintf(stderr,"Encoding method: %i, decoding method: %i\n",
311         enc_method[j],dec_method);
312        ret=-1;
313      }
314      if(ec_tell_frac(&dec)!=tell[j+1]){
315        fprintf(stderr,
316         "Tell mismatch between encoder and decoder at symbol %i: %i instead of %i (Random seed: %u).\n",
317         j+1,ec_tell_frac(&dec),tell[j+1],seed);
318      }
319    }
320    free(enc_method);
321    free(tell);
322    free(data);
323    free(logp1);
324  }
325  ec_enc_init(&enc,ptr,DATA_SIZE2);
326  ec_enc_bit_logp(&enc,0,1);
327  ec_enc_bit_logp(&enc,0,1);
328  ec_enc_bit_logp(&enc,0,1);
329  ec_enc_bit_logp(&enc,0,1);
330  ec_enc_bit_logp(&enc,0,2);
331  ec_enc_patch_initial_bits(&enc,3,2);
332  if(enc.error){
333    fprintf(stderr,"patch_initial_bits failed");
334    ret=-1;
335  }
336  ec_enc_patch_initial_bits(&enc,0,5);
337  if(!enc.error){
338    fprintf(stderr,"patch_initial_bits didn't fail when it should have");
339    ret=-1;
340  }
341  ec_enc_done(&enc);
342  if(ec_range_bytes(&enc)!=1||ptr[0]!=192){
343    fprintf(stderr,"Got %d when expecting 192 for patch_initial_bits",ptr[0]);
344    ret=-1;
345  }
346  ec_enc_init(&enc,ptr,DATA_SIZE2);
347  ec_enc_bit_logp(&enc,0,1);
348  ec_enc_bit_logp(&enc,0,1);
349  ec_enc_bit_logp(&enc,1,6);
350  ec_enc_bit_logp(&enc,0,2);
351  ec_enc_patch_initial_bits(&enc,0,2);
352  if(enc.error){
353    fprintf(stderr,"patch_initial_bits failed");
354    ret=-1;
355  }
356  ec_enc_done(&enc);
357  if(ec_range_bytes(&enc)!=2||ptr[0]!=63){
358    fprintf(stderr,"Got %d when expecting 63 for patch_initial_bits",ptr[0]);
359    ret=-1;
360  }
361  ec_enc_init(&enc,ptr,2);
362  ec_enc_bit_logp(&enc,0,2);
363  for(i=0;i<48;i++){
364    ec_enc_bits(&enc,0,1);
365  }
366  ec_enc_done(&enc);
367  if(!enc.error){
368    fprintf(stderr,"Raw bits overfill didn't fail when it should have");
369    ret=-1;
370  }
371  ec_enc_init(&enc,ptr,2);
372  for(i=0;i<17;i++){
373    ec_enc_bits(&enc,0,1);
374  }
375  ec_enc_done(&enc);
376  if(!enc.error){
377    fprintf(stderr,"17 raw bits encoded in two bytes");
378    ret=-1;
379  }
380  free(ptr);
381  return ret;
382}
383